1

アプリには複数のテナントがあります。すべてのテナントには、ユーザーが認識できる短いコードが割り当てられています。URL でそのコードをルート パラメーターとして使用し、Ninject にテナントのデータベース接続文字列を含む DbContext をテナント固有のコントローラーに挿入させたいと考えています。

調べるために、私は CarController を持っており、すべてのテナントには独自の製品があります。URL は {tenantcode}/{controller}/{action} のようになります。この部分のやり方はわかりました。

ただし、テナントによってインスタンス化されるべきではないコントローラーがいくつかあります。具体的には、ホーム コントローラーと、ログイン/登録用のアカウント コントローラーです。これらは関係ありません。

したがって、必要な URL の例:

  • myapp.com/ - ホームコントローラー
  • 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 に答える