问题描述
我使用ASP.NET MVC开发一个应用程序框架。本质上说,最终目标是要能够登录到管理界面,创建自定义设置的新租户,使他们想要的模块(博客,购物篮等)......完成任务 - 客户满意的新网站。我不使用单独的应用程序,因为会有大量的共享code,并且它会更容易保持这种方式,也因为这将是pretty容易在高峰带来了新的,相同的节点联机倍。
I am using ASP.NET MVC to develop an application framework. Essentially, the end goal is to be able to log into an admin interface, create a new tenant with custom settings, enable the modules they want (blog, shopping basket, etc)... job done - satisfied customer with new website. I'm not using separate applications because there will be a lot of shared code and it would be easier to maintain this way, and also because it would be pretty easy to bring a new, identical node online at peak times.
根据加载哪些模块的租户,不同的路线适用于每个租户。在我看来,有三个选项:
Depending on what modules are loaded for the tenant, different routes are applicable for each tenant. As I see it, there are three options:
-
有所有租户共享相同的路由集合 - 。但是如果有很多模块,它会通过很多途径来寻找它并不需要的,有些模块可能有冲突的路线
Have all tenants share the same route collection - however if there are a lot of modules it'll be searching through a lot of routes it doesn't need to, and some modules may well have conflicting routes.
为每个租户添加必要的路由到全球航线收集和扩展路由类在域看,以及 - 但这可能很快与数百名在添加更多的租户路线的结束
Add the necessary routes for each tenant to the global route collection and extend the route class to look at the domain as well - but this could quickly end up with hundreds of routes as more tenants are added.
工作出了什么房客被访问,然后再只搜索自己的私人珍藏的路线 - !这将是理想的,但我已经搜查了几个小时完全不知道该怎么做。
Work out what tenant is being accessed first and then only search their own private route collection - this would be ideal, but I've searched for hours and have absolutely no idea how to do it!
所以,任何人都可以点我在正确的方向,为第三个选项,或者解释为什么无论是前两个是不是真的那么糟糕吗?
So can anyone point me in the correct direction for the third option or explain why either of the first two aren't really that bad?
推荐答案
如何将每个网站在您的应用程序区分开来?如果我们假设每个用户将一个独特的域名或子域名标识,那么你可以用一条路线,有些 RouteConstraints
完成你的路由。创建两个限制,一个是控制器,其它为行动。假设你会在你的数据库中的表其中列出特定租户可用控制器/动作,你的约束将是如下:
How will each website be distinguished in your app? If we assume each tenant will be identified by a unique domain name or subdomain name, then you can accomplish your routing with one route and some RouteConstraints
. Create two constraints, one for controllers, the other for actions. Assuming that you will have tables in your database which list the available controllers/actions for a specific tenant, your constraints would be as follows:
using System;
using System.Web;
using System.Web.Routing;
namespace ExampleApp.Extensions
{
public class IsControllerValidForTenant : IRouteConstraint
{
public IsControllerValidForTenant() { }
private DbEntities _db = new DbEntities();
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
// determine domain
var domainName = httpContext.Request.Url.DnsSafeHost;
var siteId = _db.Sites.FirstorDefault(s => s.DomainName == domainName).SiteId;
// passed constraint if this controller is valid for this tenant
return (_db.SiteControllers.Where(sc => sc.Controller == values[parameterName].ToString() && sc.SiteId == siteId).Count() > 0);
}
}
public class IsActionValidForTenant : IRouteConstraint
{
public IsActionValidForTenant() { }
private DbEntities _db = new DbEntities();
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
// determine domain
var domainName = httpContext.Request.Url.DnsSafeHost;
var siteId = _db.Sites.FirstorDefault(s => s.DomainName == domainName).SiteId;
// passed constraint if this action is valid for this tenant
return (_db.SiteActions.Where(sa => sa.Action == values[parameterName].ToString() && sa.SiteId == siteId).Count() > 0);
}
}
}
然后,在Global.asax.cs中,定义您的路线如下:
Then, in Global.asax.cs, define your route as follows:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
new { controller = new IsControllerValidForTenant(), action = new IsActionValidForTenant(),}
);
}
当一个请求时,该限制将检查控制器和动作是否有效的领域,因此,只有为租户有效的控制器和动作将通过RouteConstraints。
When a request comes in, the constraints will examine whether the controller and action are valid for the domain, so that only valid controllers and actions for that tenant will pass the RouteConstraints.
这篇关于动态加载的模块特定租户的路线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!