使用自定义Razor视图引擎处理布局属性

Spa*_*ile 12 c# asp.net-mvc viewengine multi-tenant razor

我已经实现了一个类似于这里描述的多租户视图引擎:

让我覆盖视图的搜索位置,如下所示:

    MasterLocationFormats = new[]
    {
        "~/Views/%1/{1}/{0}.cshtml",
        "~/Views/%1/Shared/{0}.cshtml",
        "~/Views/Default/{1}/{0}.cshtml",
        "~/Views/Default/Shared/{0}.cshtml",
    };
Run Code Online (Sandbox Code Playgroud)

其中%1替换为活动租户的正确文件夹.这是一个很好的例外问题.当我在我的视图上定义布局路径时,如下所示:

Layout = "~/Views/Default/Shared/_MyLyout.cshtml";
Run Code Online (Sandbox Code Playgroud)

由于我必须硬编码布局页面的确切位置,这有点违背了多租户的目的.我希望能够做到这样的事情:

Layout = "~/Views/%1/Shared/_MyLyout.cshtml";
Run Code Online (Sandbox Code Playgroud)

如果我想允许租户拥有他们的一个布局页面,我将如何支持这个?

我试图摆弄我覆盖的视图引擎方法:

  • CreatePartialView
  • CreateView的
  • 文件已存在

但似乎没有任何东西能够动态指定布局页面.

更新:

这是我到目前为止所做的工作.我使用了这个问题的答案/sf/answers/650191881/稍加修改以创建一个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." );
}
Run Code Online (Sandbox Code Playgroud)

这与saravanan建议的类似.然后我可以使用以下代码在我的视图中设置布局:

Layout = Html.GetLayoutPageForTenant( "_Home" );
Run Code Online (Sandbox Code Playgroud)

不幸的是,这复制了自定义视图引擎正在做的工作,这似乎是错误的方法.

Sar*_*nan 4

我想提出以下想法,

_ViewStart.cshtml我们设置布局页面的文件中,您可以使用类似的内容,即基于租户的布局 url 的想法,或者通过从数据库获取来填充控制器中的文件夹名称。

@{
    Layout = ViewBag.TenantLayoutPageUrl;
 }
Run Code Online (Sandbox Code Playgroud)

或者

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

如果您有一些静态租户数据表示形式,例如Identity将跟踪租户自定义的静态类,我们可以使用它并最大程度地减少与数据库的往返。

请分享您对此实施的想法,以便它对社区有用