我已经实现了一个类似于这里描述的多租户视图引擎:
- http://weblogs.asp.net/imranbaloch/archive/2011/06/27/view-engine-with-dynamic-view-location.aspx
让我重写视图的搜索位置,像这样:
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";
如果我想让租户有他们的一个布局页面,我该如何去支持这一点?
我已经尝试过修改我覆盖的视图引擎方法:
- CreatePartialView CreateView
- FileExists
但是似乎没有任何迹象表明自己能够动态地指定布局页面。
更新:
这是我目前为止所做的工作。我使用这个问题的答案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" );
不幸的是,这重复了自定义视图引擎正在做的工作,这似乎是错误的。
我想提出以下想法,
在_ViewStart.cshtml
文件中,我们设置了布局页面,您可以使用这样的东西,基于租户布局url的想法或文件夹名称正在通过从DB中获取来填充控制器。
@{
Layout = ViewBag.TenantLayoutPageUrl;
}
或
@{
Layout = string.Format("~/Views/{0}/Shared/_MyLyout.cshtml",ViewBag.TenantId);
}
如果您有一些静态租户数据表示,如静态Identity
类,将跟踪您的租户的自定义,我们可以使用它,并尽量减少到数据库的往返。
请分享你对这个实现的想法,这样它将对社区有用
试试,
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">
您可以在租户视图文件夹(~/Views/%1/_ViewStart.cshtml
)中添加以下_ViewStart.cshtml
。每个租户都可以管理自己的布局文件。
@{
Layout = VirtualPathUtility.GetDirectory(PageContext.Page.VirtualPath) + "Shared/_Layout.cshtml";
}