2009-10-28 98 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