2011-08-30 45 views
0

我正在使用ASP.NET MVC開發應用程序框架。本質上,最終目標是能夠登錄到管理界面,創建一個新的租戶與自定義設置,啓用他們想要的模塊(博客,購物籃等)...工作完成 - 滿意的客戶與新的網站。我沒有使用單獨的應用程序,因爲會有很多共享代碼,並且這樣更容易維護,也因爲在高峯時間將新的相同節點聯機起來非常容易。用於動態加載模塊的租戶特定路由

根據爲租戶加載的模塊,不同的路由適用於每個租戶。在我看來,有三個選項:

  • 擁有所有租戶共享相同的路由集合 - 但是如果有很多模塊,它會通過很多並不需要的路線進行搜索的,有些模塊可能會有相互衝突的路線。

  • 爲每個租戶添加必要的路由到全局路由集合並擴展路由類以查看域 - 但是隨着更多租戶的添加,這可能會最終導致數百條路由。

  • 找出租戶首先被訪問的內容,然後只搜索他們自己的私人路由集合 - 這將是理想的,但我已經搜索了幾個小時,並且完全不知道該怎麼做!

所以任何人都可以點我在正確的方向,爲第三個選項或解釋爲什麼無論是前兩個是不是真的那麼糟嗎?

回答

0

每個網站在您的應用程序中的區別?如果我們假設每個租戶都將通過唯一的域名或子域名進行標識,那麼您可以通過一條路線和一些RouteConstraints完成路由。創建兩個約束,一個用於控制器,另一個用於操作。假設你會在你的數據庫中的表,其列出特定租戶可用控制器/動作,你的約束將是如下:

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中,定義您的路線如下:

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。

+0

感謝您的詳細回覆。這在我的問題的選項1下,我曾想過實現我自己的路由約束。這仍然意味着,如果我有很多模塊,有很多路由不必要的搜索 - 這是不好的? – stewartml

+0

通過路線運行的成本很小。但是,根據您提供的信息,您爲什麼認爲會有如此多的路線?不明顯的是,你將需要很多路由,特別是如果你使用RouteConstraints或者如果你使用自定義的'RouteHandler'(正如我在http://stackoverflow.com/questions/7222533/polymorphic-model-binding/7222990#中討論的那樣) 7222990)。 – counsellorben

+0

我猜想我認爲如果有很多模塊,可能會有大量的路由,這些模塊至少有一條來自它們的區域註冊的路由。我想盡管在更大的計劃中,從長遠來看,我不會擁有許多模塊,如果它足夠快,就像你說的那樣,我也可以按照自己的方式去做。我可能會使用動作過濾器來切換控制器/動作,但我很喜歡你的方式。感謝您的幫助:) – stewartml