我注意到在MVC 2 Preview 2中,AreaRegistration正在以任意顺序加载每个区域的路由。有没有一种好方法让一个先于另一个?
例如,我有两个区域 - “网站”和“管理员”。两者都有一个“博客”控制器。
我想要以下内容:
/admin/ --> go to Admin's Blog controller
/ --> go to Site's Blog controller.
问题在于它首先加载网站的路线,因此当我转到网址“/ admin /”时,它匹配{controller}/{action}/{id}
而不是admin/{controller}/{action}/{id}
。然后我得到404,因为“站点”区域中没有管理员控制器。
两个区域都默认为“博客”控制器。我意识到我可以简单地将site/{controller}/...
作为网址,但如果可能的话,我宁愿把它放在根端。我还尝试在全局RegisterRoutes函数中保留默认路由,但是,它不会被发送到“站点”区域。
提前致谢!
答案 0 :(得分: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()的代码,将其复制到您自己的应用程序中,并构建您自己的机制来确定订单。如果您想要内置方法所具有的所有花哨的缓存逻辑,那么复制相当多的代码,但您的应用可能甚至不需要。
答案 1 :(得分:7)
目前无法订购区域。但是,我认为尝试使每个区域尽可能独立于其他区域是有意义的,因此顺序无关紧要。
例如,不是使用默认的{controller} / {action} / {id}路由,而是将其替换为每个控制器的特定路由。或者为该默认路线添加约束。
我们正在考虑允许订购的选项,但我们不想让功能过于复杂。
答案 2 :(得分: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
对生成区域注册码没有重新更改。 我还在路由中使用自定义constrant来按请求(系统域或用户站点)中的域类型过滤路由。
这是我的区域注册例如:
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") }
);
}
}
}
答案 3 :(得分:4)
供参考,
在MVC3(不了解MVC2)中,当您只想将根映射到特定区域/控制器时,您可以简单地使用全局路由。 只需记住指定名称空间/区域。
routes.MapRoute(
"CatchRoot", "",
new { controller = "SITEBLOG-CONTROLLER-NAME", action = "Index"}
).DataTokens.Add("area", "SITE-AREA-NAME");