1

我们的应用程序有多个租户。每个租户都有一个分配给他们的短代码,用户可以通过该短代码了解他们。我想在我的 URL 中使用该代码作为路由参数,并让 Ninject 将带有租户数据库连接字符串的 DbContext 注入到特定于租户的控制器中。

所以为了检查我有一个 CarController,每个租户都有自己的产品。URL 看起来像 {tenantcode}/{controller}/{action}。我明白如何做这部分。

但是,我有几个不应该由租户实例化的控制器。具体来说,家庭控制器和用于登录/注册的帐户控制器。这些都无所谓。

所以我需要的示例网址:

  • myapp.com/ - HomeController
  • myapp.com/Account/Login - AccountController
  • myapp.com/GM/Car/Add - 注入了 GM 的 DbContext 的 CarController
  • myapp.com/Ford/Car/Add - 注入了 Ford 的 DbContext 的 CarController

如何从路由中排除某些控制器?运行 ASP.NET MVC 5。


非常感谢 Darko Z 让我朝着正确的方向前进。我最终使用了传统路由的混合体,以及 MVC 5 中基于新属性的路由。

首先,“排除”的路线用新的 RouteAttribute 类装饰

public class HomeController : Controller
{
    private readonly TenantContext context;

    public HomeController(TenantContext Context)
    {
        this.context = Context;
    }

    //
    // GET: http://myapp.com/
    // By decorating just this action with an empty RouteAttribute, we make it the "start page"
    [Route]
    public ActionResult Index(bool Error = false)
    {
        // Look up and make a nice list of the tenants this user can access
        var tenantQuery =
            from u in context.Users
            where u.UserId == userId
            from t in u.Tenants
            select new
            {
                t.Id,
                t.Name,
            };

        return View(tenantQuery);
    }
}

// By decorating this whole controller with RouteAttribute, all /Account URLs wind up here
[Route("Account/{action}")]
public class AccountController : Controller
{
    //
    // GET: /Account/LogOn
    public ActionResult LogOn()
    {
        return View();
    }

    //
    // POST: /Account/LogOn
    [HttpPost]
    public ActionResult LogOn(LogOnViewModel model, string ReturnUrl)
    {
        // Log on logic here
    }
}

接下来,我注册了 Darko Z 建议的租户通用路由。在创建其他路由之前调用 MapMvcAttributeRoutes() 很重要。这是因为我的基于属性的路线是“例外”,就像他说的那样,这些例外必须位于顶部,以确保它们首先被拾取。

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        // exceptions are the attribute-based routes
        routes.MapMvcAttributeRoutes();

        // tenant code is the default route
        routes.MapRoute(
            name: "Tenant",
            url: "{tenantcode}/{controller}/{action}/{id}",
            defaults: new { controller = "TenantHome", action = "Index", id = UrlParameter.Optional }
        );
    }
}
4

1 回答 1

2

所以我确信你知道你在 MVC 中按照从最具体到最通用的顺序指定路由。所以在你的情况下,我会做这样的事情:

//exclusions - basically hardcoded, pacing this at the top will 
//ensure that these will be picked up first. Of course this means 
//you must make sure that tenant codes cannot be the same as any 
//controller name here
routes.MapRoute(
    "Home",                                              
    "Home/{action}/{id}",                         
    new { controller = "Home", action = "Index", id = "" } 
);

routes.MapRoute(
    "Account",                                              
    "Account/{action}/{id}",                         
    new { controller = "Account", action = "Index", id = "" } 
);

//tenant generic route
routes.MapRoute(
    "Default",                                              
    "{tenantcode}/{controller}/{action}",                         
    new { tenantcode = "Default", controller = "Tenant", action = "Index" } 
);

//default route
routes.MapRoute(
    "Default",                                              
    "{controller}/{action}/{id}",                         
    new { controller = "Home", action = "Index", id = "" } 
);

这显然只有在排除的控制器比需要租户代码的控制器少的情况下才有用。如果不是,那么您可以采取相反的方法并扭转上述情况。这里的主要内容是(很高兴被证明是错误的)在 AddRoute 调用中无法进行通用忽略。虽然有一个 IgnoreRoute,但它完全不应用任何路由规则并用于静态资源。希望有帮助。

于 2013-10-25T21:03:34.870 回答