在ASP.Net MVC 中,如何在Global.asax中配置一个指向Area内部的默认Route
2013-06-18 14:07
357 查看
ASP.Net MVC 中配置Route的时候可以设置一个默认的Route。
比如我要在输入http://localhost的时候默认进入http://localhost/home/index。可以在Global.asax中这么配置:
C#代码
很简单,对吧。
但是如果你想把默认值指向一个Area内部的Controller/Action,要怎么做呢?
模仿上面的例子,我是这么做的:
新建一个叫做MyArea的area,然后配置路由如下:
C#代码
添加了一个area的section,应该可以了吧。
运行一下看看:
结果是Controller冲突,截图如下:
这说明了我们配置的那个{Area}没起作用。原来MVC的route没有对Area进行支持。
来看看MyAreaAreaRegistration的源码中是怎么做的:
C#代码
它在MapRoute的时候加入了一个namespace的约束。那我们也来加上看看。
C#代码
OK,成功了。不过仔细一看。View不对了。它竟然还是去找Area外面的View,而不是这个Area下面的View.
我们在ViewEngine的源码中找一下原因,关键代码是在寻找View时的下面几句:
C#代码
ViewEngine会在controllerContext.RouteData中去找AreaName,如果找到的话就用Area中的View,否则用根目录下的View.那这个AreaName是什么时候放如RouteData中的呢?
回头看一下我前面贴出来那段MyAreaAreaRegistration中的源码,关键的一句就是:
C#代码
就是在注册Area的Route的时候,会把这个AreaName放进去。
明白了这一点,我们就可以来继续改造我们注册route的地方:
C#代码
测试一下,完全正确。
在实际的项目中,可能直接把默认route指向Area内部的一个Action的几率比较小。不过还是有一些特殊场景。
我们通过尝试来实现这么一种特殊场景,分析了AreaRegistration的工作原理,也窥探了一下Route和ViewEngine是如何处理Area的。
我们可以看到,MVC在尽可能少地侵入框架的情况下,实现了一套Area机制。
比如我要在输入http://localhost的时候默认进入http://localhost/home/index。可以在Global.asax中这么配置:
C#代码
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,然后配置路由如下:
C#代码
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的源码中是怎么做的:
C#代码
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的约束。那我们也来加上看看。
C#代码
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时的下面几句:
C#代码
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中的源码,关键的一句就是:
C#代码
route.DataTokens["area"] = AreaName;
就是在注册Area的Route的时候,会把这个AreaName放进去。
明白了这一点,我们就可以来继续改造我们注册route的地方:
C#代码
var route = 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.*" } ); route.DataTokens["area"] = "MyArea";
测试一下,完全正确。
在实际的项目中,可能直接把默认route指向Area内部的一个Action的几率比较小。不过还是有一些特殊场景。
我们通过尝试来实现这么一种特殊场景,分析了AreaRegistration的工作原理,也窥探了一下Route和ViewEngine是如何处理Area的。
我们可以看到,MVC在尽可能少地侵入框架的情况下,实现了一套Area机制。
相关文章推荐
- 通过一个模拟程序让你明白ASP.NET MVC是如何运行的
- 如何将一个 ASP.NET MVC 4 和 Web API 项目升级到 ASP.NET MVC 5 和 Web API 2
- 通过一个模拟程序让你明白ASP.NET MVC是如何运行的
- 主攻ASP.NET.3.5.MVC3.0架构之重生:MVC在Global.asax.定义定时处理程序
- [ASP.NET MVC 专题] 如何为Route构造相关的自定义Configuration
- asp.net mvc 错误 global.asax
- ASP.NET Core中使用默认MVC路由的配置
- c#ASP.NET MVC 4 Web应用程序创建以及默认起始页配置的由来
- asp.net mvc中配置路由默认值(Area中)
- 如何配置Visual Studio 2010中的ASP.NET MVC的单元测试的代码覆盖率
- 如何做一个基于ASP.NET MVC 网站(六)
- ASP.NET MVC 如何在一个同步方法(非async)方法中等待async方法
- Asp.net Mvc 请求是如何到达 MvcHandler的——UrlRoutingModule、MvcRouteHandler分析,并造个轮子
- 在 ASP.NET 2.0 中,Global.asax 文件没有后置代码,如何将Globa.asax中的页面移到代码文件中
- 使用XML文件来动态配置ASP.NET MVC的Route规则 【转】
- 使用XML文件来动态配置ASP.NET MVC的Route规则
- ASP.NET没有魔法——ASP.NET MVC使用Area开发一个管理模块
- asp.net mvc 如何将controller 里一个action 返回值为list<>的值输出到view
- ASP.NET MVC中的Global.asax文件
- asp.net mvc 3.0详细笔记__07__项目文件结构详解_Global.asax