我已经实现了一个类似于这里描述的多租户视图引擎:
这让我可以覆盖这样的视图的搜索位置:
MasterLocationFormats = new[]
{
"~/Views/%1/{1}/{0}.cshtml",
"~/Views/%1/Shared/{0}.cshtml",
"~/Views/Default/{1}/{0}.cshtml",
"~/Views/Default/Shared/{0}.cshtml",
};
其中%1
替换为活动租户的正确文件夹。这工作得很好,例外一个问题。当我像这样在视图上定义布局路径时:
Layout = "~/Views/Default/Shared/_MyLyout.cshtml";
这有点违背了多租户的目的,因为我必须硬编码布局页面的确切位置。我希望能够做这样的事情:
Layout = "~/Views/%1/Shared/_MyLyout.cshtml";
如果我想让租户拥有他们的一个布局页面,我将如何支持这一点?
我试过摆弄我覆盖的视图引擎方法:
- 创建局部视图
- 创建视图
- 文件已存在
但似乎没有任何东西指向能够动态指定布局页面。
更新:
这是我到目前为止的工作。我使用这个问题的答案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." );
}
这类似于 saravanan 的建议。然后我可以使用以下代码在我的视图中设置布局:
Layout = Html.GetLayoutPageForTenant( "_Home" );
不幸的是,这重复了自定义视图引擎正在做的工作,这似乎是错误的方法。