ASP.Net MVC 中配置Route的时候可以设置一个默认的Route。比如我要在输入http://localhost的时候默认进入http://localhost/home/index。可以在Global.asax中这么配置:
?
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
很简单,对吧。
?
但是如果你想把默认值指向一个Area内部的Controller/Action,要怎么做呢??
模仿上面的例子,我是这么做的:
新建一个叫做MyArea的area,然后配置路由如下:
?
?
routes.MapRoute(
"Default", // Route name
"{area}{controller}/{action}/{id}", // URL with parameters
new {area = "MyArea", controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
添加了一个area的section,应该可以了吧。
?
运行一下看看:
结果是Controller冲突,截图如下:

?
这说明了我们配置的那个{Area}没起作用。原来MVC的route没有对Area进行支持。
来看看MyAreaAreaRegistration的源码中是怎么做的:
public Route MapRoute(string name, string url, object defaults, object constraints, string[] namespaces) {
if (namespaces == null && Namespaces != null) {
namespaces = Namespaces.ToArray();
}
Route route = Routes.MapRoute(name, url, defaults, constraints, namespaces);
route.DataTokens["area"] = AreaName;
// disabling the namespace lookup fallback mechanism keeps this areas from accidentally picking up
// controllers belonging to other areas
bool useNamespaceFallback = (namespaces == null || namespaces.Length == 0);
route.DataTokens["UseNamespaceFallback"] = useNamespaceFallback;
return route;
}
?它在MapRoute的时候加入了一个namespace的约束。那我们也来加上看看。
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new {controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
new[] { "WebArchDemo.Areas.MyArea.*" }
);
?OK,成功了。不过仔细一看。View不对了。它竟然还是去找Area外面的View,而不是这个Area下面的View.
?我们在ViewEngine的源码中找一下原因,关键代码是在寻找View时的下面几句:
string areaName = AreaHelpers.GetAreaName(controllerContext.RouteData); bool usingAreas = !String.IsNullOrEmpty(areaName); List<ViewLocation> viewLocations = GetViewLocations(locations, (usingAreas) ? areaLocations : null);
?ViewEngine会在controllerContext.RouteData中去找AreaName,如果找到的话就用Area中的View,否则用根目录下的View.那这个AreaName是什么时候放如RouteData中的呢?
回头看一下我前面贴出来那段MyAreaAreaRegistration中的源码,关键的一句就是:
route.DataTokens["area"] = AreaName;
就是在注册Area的Route的时候,会把这个AreaName放进去。
?
明白了这一点,我们就可以来继续改造我们注册route的地方:
var route = routes.MapRoute(
"Default", // Route name
