12

ここで説明されているものと同様のマルチテナント ビュー エンジンを実装しました。

次のように、ビューの検索場所をオーバーライドできます。

    MasterLocationFormats = new[]
    {
        "~/Views/%1/{1}/{0}.cshtml",
        "~/Views/%1/Shared/{0}.cshtml",
        "~/Views/Default/{1}/{0}.cshtml",
        "~/Views/Default/Shared/{0}.cshtml",
    };

%1、アクティブなテナントの正しいフォルダーに置き換えられます。これは、1つの問題を除いてうまく機能しています。ビューでレイアウト パスを次のように定義すると、次のようになります。

Layout = "~/Views/Default/Shared/_MyLyout.cshtml";

レイアウト ページの正確な場所をハード コーディングする必要があるため、マルチテナンシーを使用するという目的が無効になります。私はこのようなことができるようにしたい:

Layout = "~/Views/%1/Shared/_MyLyout.cshtml";

テナントが 1 つのレイアウト ページを持つことを許可したい場合、これをどのようにサポートしますか?

オーバーライドしたビュー エンジン メソッドをいじってみました。

  • CreatePartialView
  • CreateView
  • ファイルが存在しています

しかし、レイアウト ページを動的に指定できるようになるとは思えません。

アップデート:

これが私がこれまで取り組んできたことです。この質問への回答https://stackoverflow.com/a/9288455/292578を少し変更して HTML ヘルパーを作成しました。

public static string GetLayoutPageForTenant( this HtmlHelper html, string LayoutPageName )
{
    var layoutLocationFormats = new[]
    {
        "~/Views/{2}/{1}/{0}.cshtml",
        "~/Views/{2}/Shared/{0}.cshtml",
        "~/Views/Default/{1}/{0}.cshtml",
        "~/Views/Default/Shared/{0}.cshtml",
    };

    var controller = html.ViewContext.Controller as MultiTenantController;
    if( controller != null )
    {
        var tenantName = controller.GetTenantSchema();
        var controllerName = html.ViewContext.RouteData.Values["Controller"].ToString();

        foreach( var item in layoutLocationFormats )
        {
            var resolveLayoutUrl = string.Format( item, LayoutPageName, controllerName, tenantName );
            var fullLayoutPath = HostingEnvironment.IsHosted ? HostingEnvironment.MapPath( resolveLayoutUrl ) : System.IO.Path.GetFullPath( resolveLayoutUrl );
            if( File.Exists( fullLayoutPath ) ) return resolveLayoutUrl;
        }
    }

    throw new Exception( "Page not found." );
}

これは、サラバナンが提案したものと似ています。次に、次のコードを使用してビューにレイアウトを設定できます。

Layout = Html.GetLayoutPageForTenant( "_Home" );

残念ながら、これはカスタム ビュー エンジンが行っている作業と重複しており、間違った方法のように思われます。

4

3 に答える 3

4

次のアイデアを提案したいのですが、

レイアウト ページを設定する_ViewStart.cshtmlファイルでは、このようなものを使用できます。これは、テナント ベースのレイアウト URL またはフォルダー名が DB から取得してコントローラーに入力されるという考え方です。

@{
    Layout = ViewBag.TenantLayoutPageUrl;
 }

また

 @{
    Layout = string.Format("~/Views/{0}/Shared/_MyLyout.cshtml",ViewBag.TenantId);
 }

Identityテナントのカスタマイズを追跡する静的クラスなど、いくつかの静的テナント データ表現がある場合は、それを使用してデータベースへのラウンド トリップを最小限に抑えることができます。

コミュニティに役立つように、この実装に関するアイデアを共有してください

于 2013-05-11T12:41:24.607 に答える
1

試す、

public class CustomWebViewPage : WebViewPage
{
    public override void ExecutePageHierarchy()
    {
        if (Context.Items["__MainView"] == null)
        {
            this.Layout = String.Format("~/Views/Shared/{0}/_Layout.cshtml", ViewContext.Controller.GetType().Namespace);
            Context.Items["__MainView"] = "Not Null";
        }
        base.ExecutePageHierarchy();
    }

    public override void Execute()
    {
    }
}

public class CustomWebViewPage<T> : WebViewPage<T>
{
    public override void ExecutePageHierarchy()
    {
        if (Context.Items["__MainView"] == null)
        {
            this.Layout = String.Format("~/Views/Shared/{0}/_Layout.cshtml", ViewContext.Controller.GetType().Namespace);
            Context.Items["__MainView"] = "Not Null";
        }
        base.ExecutePageHierarchy();
    }

    public override void Execute()
    {
    }
}

<system.web.webPages.razor>
  <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
  <pages pageBaseType="Mv4App.CustomWebViewPage">
于 2013-05-16T07:03:26.323 に答える
0

_ViewStart.cshtmlテナント ビュー フォルダ ( )に以下を追加できます~/Views/%1/_ViewStart.cshtml。各テナントは、独自のレイアウト ファイルを管理できます。

@{
    Layout =  VirtualPathUtility.GetDirectory(PageContext.Page.VirtualPath) + "Shared/_Layout.cshtml";
}
于 2013-05-17T14:38:19.520 に答える