2009-10-28 95 views
12

我注意到在MVC 2 Preview 2中,AreaRegistration正在以任意順序加載每個區域的路由。是否有一種先於另一種獲得一種的好方法?MVC 2區域註冊路由訂購

例如,我有兩個區域 - 「網站」和「管理員」。兩者都有一個「Blog」控制器。

我想以下幾點:

/admin/ --> go to Admin's Blog controller 
/  --> go to Site's Blog controller. 

的問題是,它首先加載該網站的途徑,因此它匹配{controller}/{action}/{id}而不是admin/{controller}/{action}/{id}當我去到URL「/管理/」。然後我得到一個404,因爲在「網站」區域沒有管理員控制器。

這兩個區域默認爲「Blog」控制器。我意識到我可以簡單地將site/{controller}/...作爲url,但我寧願在可能的情況下在根目錄下。我也嘗試在全局RegisterRoutes函數中保留默認路由,但是,它不會發送到「站點」區域。

在此先感謝!

回答

7

目前無法訂購區域。不過,我認爲儘量讓每個區域儘可能獨立於其他區域是有意義的,因此順序無關緊要。

例如,可以用每個控制器的特定路由代替默認的{controller}/{action}/{id}路由,而不是使用默認的{controller}/{action}/{id}路由。或者向該默認路由添加約束。

我們正在考慮允許排序的選項,但我們不想過度複雜功能。

+0

嘿菲爾,感謝您的解釋。 我最終將我的「站點」移出區域,現在它是「默認/非區域」部分(具有根和視圖和控制器)。然後我將我的命名空間參數設置爲默認控制器,以避免「模糊控制器」錯誤。 此外,我可能會設置約束,像^((?!管理)。*)忽略管理員在站點區域路線。 我同意,增加更多的複雜性並不是很好,儘管看起來mvc 1(非區域)路線可能潛在地嚴重依賴於訂單。 謝謝! – Jason 2009-10-29 14:58:15

+0

路由過程通常取決於規則順序,所以'排序'功能可能很重要。 – twk 2009-11-03 22:56:15

+0

請查看我對兩種技術的迴應,這兩種技術可以讓您按任何順序訂購區域註冊(以及它們的路線)。 – Eilon 2010-01-21 07:40:43

30

除了Haacked說的,訂購區域註冊(以及它們的路線)是非常有可能的。您只需手動註冊每個區域,無論您想要的順序如何。它不像調用RegisterAllAreas()那麼光滑,但它絕對可行。

protected void Application_Start() { 
    var area1reg = new Area1AreaRegistration(); 
    var area1context = new AreaRegistrationContext(area1reg.AreaName, RouteTable.Routes); 
    area1reg.RegisterArea(area1context); 

    var area2reg = new Area2AreaRegistration(); 
    var area2context = new AreaRegistrationContext(area2reg.AreaName, RouteTable.Routes); 
    area2reg.RegisterArea(area2context); 

    var area3reg = new Area3AreaRegistration(); 
    var area3context = new AreaRegistrationContext(area3reg.AreaName, RouteTable.Routes); 
    area3reg.RegisterArea(area3context); 
} 

另一種選擇是採取RegisterAllAreas()的代碼,將其複製到自己的應用程序,並建立自己的機制來確定順序。如果你想要內置方法所具有的所有奇特的緩存邏輯,那麼複製代碼是相當多的,但你的應用甚至可能不需要這樣做。

+0

很好的答案。此外,如果您製作方法的代碼較少,那麼它就是每個區域的一行代碼。 – CRice 2016-07-24 12:21:00

4

我使此解決方案:

AreaUtils.cs

using System; 
    using System.Web.Mvc; 
    using System.Web.Routing; 

    namespace SledgeHammer.Mvc.Site 
    { 
     public static class Utils 
     { 
       public static void RegisterArea<T>(RouteCollection routes, 
    object state) where T : AreaRegistration 

      { 
       AreaRegistration registration = 
    (AreaRegistration)Activator.CreateInstance(typeof(T)); 

        AreaRegistrationContext context = 
    new AreaRegistrationContext(registration.AreaName, routes, state); 

        string tNamespace = registration.GetType().Namespace; 
        if (tNamespace != null) 
       { 
        context.Namespaces.Add(tNamespace + ".*"); 
       } 

       registration.RegisterArea(context); 
      } 
     } 

    } 

在global.asax中:

Utils.RegisterArea<SystemAreaRegistration>(RouteTable.Routes, null); 
Utils.RegisterArea<ClientSitesAreaRegistration>(RouteTable.Routes, null); 

//AreaRegistration.RegisterAllAreas(); do not dublicate register areas 

否requred變化產生的區域的註冊代碼。 我還在路由中使用自定義常量來按請求(系統域或用戶站點)中的域類型過濾路由。

這是我區註冊爲例:

namespace SledgeHammer.MVC.Site.Areas.System 
{ 
    public class SystemAreaRegistration : AreaRegistration 
    { 
     public override string AreaName 
     { 
      get { return "System"; } 
     } 

     public override void RegisterArea(AreaRegistrationContext context) 
     { 
      context.MapRoute(
       "System_Feedback", 
       "Feedback", 
       new { controller = "Feedback", action = "Index" } 
      ); 
      context.MapRoute(
       "System_Information", 
       "Information/{action}/{id}", 
       new { controller = "Information", action = "Index", id = UrlParameter.Optional } 
      ); 
     } 
    } 
} 



namespace SledgeHammer.MVC.Site.Areas.ClientSites 
{ 
    public class ClientSitesAreaRegistration : AreaRegistration 
    { 
     public override string AreaName 
     { 
      get { return "ClientSites"; } 
     } 

     public override void RegisterArea(AreaRegistrationContext context) 
     { 
      context.MapRoute(
       "ClientSites_default", 
       "{controller}/{action}/{id}", 
       new { controller = "Site", action = "Index", id = UrlParameter.Optional }, 
       new { Host = new SiteInGroups("clients") } 
      ); 
     } 
    } 
} 
+0

您的util類非常棒,因爲它指出您需要爲區域添加名稱空間,否則路徑將不會鏈接到控制器 – 2011-10-19 20:08:19

4

僅供參考,

在MVC3(不知道MVC2),當你只是想根映射到特定區域/控制器,你可以簡單地使用全球路線。 只記得指定命名空間/區域。

routes.MapRoute(
     "CatchRoot", "", 
     new { controller = "SITEBLOG-CONTROLLER-NAME", action = "Index"} 
    ).DataTokens.Add("area", "SITE-AREA-NAME"); 
+0

+1 - 這是一個很好的解決方案,因爲它允許將所有內容分組到一個區域區域作爲一個更清潔的網址來捕捉所有人。 – 2012-08-13 22:27:04

+0

完美的作品!允許我將所有控制器都放在區域內,而不是「特殊區域」和實際區域。對於任何想要相同的人,請在路由配置中註冊默認路由。 – FDIM 2014-04-17 09:14:08