如何在 MVC 5 中创建多租户视图结构
How do I create a multi-tenant view structure in MVC 5
我正在构建一个演示项目,其中多个租户将拥有自己的视图集合。此外,如果租户没有专门的视图,则默认视图集合将可用。我看过多个关于使用多租户进行代码方面的教程,其中每个租户都有自己的数据库。但是view方面好像有点欠缺
在伪代码中:
Get Me the User information view
Get tentantname from current context
Check /views/{tentantname}/userinfo/index.cshtml
if found return /views/{tentantname}/userinfo/index.cshtml
else return /views/base/userinfo/index.html
我不确定在哪里处理这段代码? (创建一个基本控制器来覆盖对视图的调用)
我应该创建自己的 RazorViewEngine 版本吗?
这是在路由配置中处理的吗? (这是更多的控制器路由然后在哪里寻找视图)
需要覆盖什么方法?
我找到了有关更改所有视图的基本目录的教程,但我希望根据具体情况处理每个视图的查找。在 运行 请求的当前上下文中利用一个值。
参考第一个答案进行编辑。
对 RazorViewEngine 所做的更改删除了示例中使用的许多可重写方法。同一作者添加了更新 http://weblogs.asp.net/imranbaloch/custom-viewengine-aspnet5-mvc6
但是这个版本没有进入视图位置检查和重写。我认为答案是传递给构造函数的参数之一。我认为如果可以覆盖它们我可以完成我的任务。这是元数据中的 RazorViewEngine:
//
// Summary:
// Default implementation of Microsoft.AspNet.Mvc.Razor.IRazorViewEngine.
//
// Remarks:
// For ViewResults returned from controllers, views should be located in Microsoft.AspNet.Mvc.Razor.RazorViewEngine.ViewLocationFormats
// by default. For the controllers in an area, views should exist in Microsoft.AspNet.Mvc.Razor.RazorViewEngine.AreaViewLocationFormats.
public class RazorViewEngine : IRazorViewEngine, IViewEngine
{
//
// Summary:
// Initializes a new instance of the Microsoft.AspNet.Mvc.Razor.RazorViewEngine
// class.
//
// Parameters:
// pageFactory:
// The page factory used for creating Microsoft.AspNet.Mvc.Razor.IRazorPage instances.
public RazorViewEngine(IRazorPageFactory pageFactory, IRazorViewFactory viewFactory, IOptions<RazorViewEngineOptions> optionsAccessor, IViewLocationCache viewLocationCache);
//
// Summary:
// Gets the locations where this instance of Microsoft.AspNet.Mvc.Razor.RazorViewEngine
// will search for views within an area.
//
// Remarks:
// The locations of the views returned from controllers that belong to an area.
// Locations are composite format strings (see http://msdn.microsoft.com/en-us/library/txafckwd.aspx),
// which contains following indexes: {0} - Action Name {1} - Controller Name {2}
// - Area name The values for these locations are case-sensitive on case-senstive
// file systems. For example, the view for the Test action of HomeController should
// be located at /Views/Home/Test.cshtml. Locations such as /views/home/test.cshtml
// would not be discovered
public virtual IEnumerable<string> AreaViewLocationFormats { get; }
//
// Summary:
// Gets the locations where this instance of Microsoft.AspNet.Mvc.Razor.RazorViewEngine
// will search for views.
//
// Remarks:
// The locations of the views returned from controllers that do not belong to an
// area. Locations are composite format strings (see http://msdn.microsoft.com/en-us/library/txafckwd.aspx),
// which contains following indexes: {0} - Action Name {1} - Controller Name The
// values for these locations are case-sensitive on case-senstive file systems.
// For example, the view for the Test action of HomeController should be located
// at /Views/Home/Test.cshtml. Locations such as /views/home/test.cshtml would not
// be discovered
public virtual IEnumerable<string> ViewLocationFormats { get; }
//
// Summary:
// Gets the case-normalized route value for the specified route key.
//
// Parameters:
// context:
// The Microsoft.AspNet.Mvc.ActionContext.
//
// key:
// The route key to lookup.
//
// Returns:
// The value corresponding to the key.
//
// Remarks:
// The casing of a route value in Microsoft.AspNet.Mvc.ActionContext.RouteData is
// determined by the client. This making constructing paths for view locations in
// a case sensitive file system unreliable. Using the Microsoft.AspNet.Mvc.Abstractions.ActionDescriptor.RouteValueDefaults
// for attribute routes and Microsoft.AspNet.Mvc.Abstractions.ActionDescriptor.RouteConstraints
// for traditional routes to get route values produces consistently cased results.
public static string GetNormalizedRouteValue(ActionContext context, string key);
//
public RazorPageResult FindPage(ActionContext context, string pageName);
//
public ViewEngineResult FindPartialView(ActionContext context, string partialViewName);
//
public ViewEngineResult FindView(ActionContext context, string viewName);
}
如果你注意到只有一两个属性是虚拟的。我认为可以覆盖构造函数参数之一,以便在调用 FindView() 时可以完成某些操作。我现在不知道,也找不到示例或教程。
是的,您将创建自己的继承自 RazorViewEngine
的 CustomViewEngine。在那里,您将从上下文中读取租户名称,然后指定要查找的路径。
这里是blog post describing creating your own ViewEngine.
更新:您还应该检查 View Location Expander
我正在构建一个演示项目,其中多个租户将拥有自己的视图集合。此外,如果租户没有专门的视图,则默认视图集合将可用。我看过多个关于使用多租户进行代码方面的教程,其中每个租户都有自己的数据库。但是view方面好像有点欠缺
在伪代码中:
Get Me the User information view
Get tentantname from current context
Check /views/{tentantname}/userinfo/index.cshtml
if found return /views/{tentantname}/userinfo/index.cshtml
else return /views/base/userinfo/index.html
我不确定在哪里处理这段代码? (创建一个基本控制器来覆盖对视图的调用)
我应该创建自己的 RazorViewEngine 版本吗?
这是在路由配置中处理的吗? (这是更多的控制器路由然后在哪里寻找视图)
需要覆盖什么方法?
我找到了有关更改所有视图的基本目录的教程,但我希望根据具体情况处理每个视图的查找。在 运行 请求的当前上下文中利用一个值。
参考第一个答案进行编辑。
对 RazorViewEngine 所做的更改删除了示例中使用的许多可重写方法。同一作者添加了更新 http://weblogs.asp.net/imranbaloch/custom-viewengine-aspnet5-mvc6 但是这个版本没有进入视图位置检查和重写。我认为答案是传递给构造函数的参数之一。我认为如果可以覆盖它们我可以完成我的任务。这是元数据中的 RazorViewEngine:
//
// Summary:
// Default implementation of Microsoft.AspNet.Mvc.Razor.IRazorViewEngine.
//
// Remarks:
// For ViewResults returned from controllers, views should be located in Microsoft.AspNet.Mvc.Razor.RazorViewEngine.ViewLocationFormats
// by default. For the controllers in an area, views should exist in Microsoft.AspNet.Mvc.Razor.RazorViewEngine.AreaViewLocationFormats.
public class RazorViewEngine : IRazorViewEngine, IViewEngine
{
//
// Summary:
// Initializes a new instance of the Microsoft.AspNet.Mvc.Razor.RazorViewEngine
// class.
//
// Parameters:
// pageFactory:
// The page factory used for creating Microsoft.AspNet.Mvc.Razor.IRazorPage instances.
public RazorViewEngine(IRazorPageFactory pageFactory, IRazorViewFactory viewFactory, IOptions<RazorViewEngineOptions> optionsAccessor, IViewLocationCache viewLocationCache);
//
// Summary:
// Gets the locations where this instance of Microsoft.AspNet.Mvc.Razor.RazorViewEngine
// will search for views within an area.
//
// Remarks:
// The locations of the views returned from controllers that belong to an area.
// Locations are composite format strings (see http://msdn.microsoft.com/en-us/library/txafckwd.aspx),
// which contains following indexes: {0} - Action Name {1} - Controller Name {2}
// - Area name The values for these locations are case-sensitive on case-senstive
// file systems. For example, the view for the Test action of HomeController should
// be located at /Views/Home/Test.cshtml. Locations such as /views/home/test.cshtml
// would not be discovered
public virtual IEnumerable<string> AreaViewLocationFormats { get; }
//
// Summary:
// Gets the locations where this instance of Microsoft.AspNet.Mvc.Razor.RazorViewEngine
// will search for views.
//
// Remarks:
// The locations of the views returned from controllers that do not belong to an
// area. Locations are composite format strings (see http://msdn.microsoft.com/en-us/library/txafckwd.aspx),
// which contains following indexes: {0} - Action Name {1} - Controller Name The
// values for these locations are case-sensitive on case-senstive file systems.
// For example, the view for the Test action of HomeController should be located
// at /Views/Home/Test.cshtml. Locations such as /views/home/test.cshtml would not
// be discovered
public virtual IEnumerable<string> ViewLocationFormats { get; }
//
// Summary:
// Gets the case-normalized route value for the specified route key.
//
// Parameters:
// context:
// The Microsoft.AspNet.Mvc.ActionContext.
//
// key:
// The route key to lookup.
//
// Returns:
// The value corresponding to the key.
//
// Remarks:
// The casing of a route value in Microsoft.AspNet.Mvc.ActionContext.RouteData is
// determined by the client. This making constructing paths for view locations in
// a case sensitive file system unreliable. Using the Microsoft.AspNet.Mvc.Abstractions.ActionDescriptor.RouteValueDefaults
// for attribute routes and Microsoft.AspNet.Mvc.Abstractions.ActionDescriptor.RouteConstraints
// for traditional routes to get route values produces consistently cased results.
public static string GetNormalizedRouteValue(ActionContext context, string key);
//
public RazorPageResult FindPage(ActionContext context, string pageName);
//
public ViewEngineResult FindPartialView(ActionContext context, string partialViewName);
//
public ViewEngineResult FindView(ActionContext context, string viewName);
}
如果你注意到只有一两个属性是虚拟的。我认为可以覆盖构造函数参数之一,以便在调用 FindView() 时可以完成某些操作。我现在不知道,也找不到示例或教程。
是的,您将创建自己的继承自 RazorViewEngine
的 CustomViewEngine。在那里,您将从上下文中读取租户名称,然后指定要查找的路径。
这里是blog post describing creating your own ViewEngine.
更新:您还应该检查 View Location Expander