深入理解ASP.NET MVC(4)
DataTokens和Areas机制
到目前为止Route对象只剩下DataTokens属性没有涉及,事实上这个Areas机制的核心。
DataTokens实际上也是一个RouteValueDictionary,在用MapRoute方法构造在Route构造的时候,可以传一个namespaces字符串数组,这个参数会构造成Route对象的DataTokens["Namespaces"],它的值将被MVC框架优先用来在对应的名字空间中查找相应的Controller。 如果在指定的名字空间中能找到Controller,那么,就算在其他名字空间中有相同名字的Controller(大小写敏感)也没关系;如果在指定的 名字空间中没有找到Controller,那么将在所有引用的程序集中查找,此时如果出现重复名字的Controller,那么将出现多个匹配的错误。这 种行为是DefaultControllerFactory实现的,关于DefaultControllerFactory将在以后分析。
Areas机制是这样的一种机制:在不同的Area中可以有相同名字的Controller,也就是说Controller的名字可以重复了!这样 整个web应用程序可以按功能划分成几个模块,每个模块是一个Area,每个Area互相独立,可以独立地由某个开发人员随意定义URL或 Controller而不影响其他Area。
比如:有管理员和用户两个模块,也许需要如下的URL:
Admin/Home/Index
User/Home/Index
于是可以用VS集成的Area生成模板创建两个Area:Admin和User,分别地,由两个开发人员分别负责开发,他们都需要用 HomeController和Index方法,有了Areas机制,HomeController被分别放到两个不同的名字空间中,这就不会有冲突。
讲到这里你也许隐约明白DataTokens和Areas机制的某种关系了。在vs创建Areas的时候到底做了哪些事情呢?
一、首先在每个Area中Controller都将被放置到一个名字空间中,例如:MyAppName.Areas.Admin.Controllers;
二、为每个Area创建一个AreaRegistration的继承类,如果是Admin的Area将是AdminAreaRegistration。在这个类中重写AreaName属性和RegisterArea方法:
|
1
2
3
4
5
6
7
8
|
public override void RegisterArea(AreaRegistrationContext context){ context.MapRoute( "Admin_default", "Admin/{controller}/{action}/{id}", new { action = "Index", id = UrlParameter.Optional } );} |
可以看到在RegisterArea方法中也调用了MapRoute方法注册路由。需要注意的是这个的MapRoute虽然也是操作全局路由表,但是它的实现略有不同:
1.首先设置的URL Pattern是以Area名字开头的,这样做是必要的,毕竟这个URL Pattern最终是放在全局中的;
2.它会将DataTokens["Namespaces"]设置成当前Area的名字空间,比如 MyAppName.Areas.Admin.*。结果是,当一个请求到来是,DefaultControllerFactory会优先到这个名字空间下 查找Controller。而且会增加一个DataTokens["UseNamespaceFallback"],并设置为false,这样当且仅当显示设置的名字空间中有需要的Controller时,才能成功,其他名字空间的的同名Controller将无效;
3.最后,还会添加一个叫DataTokens["area"]的键值,并设置为当前Area名字,这是为了在反向映射(outbounding)URL的时候使用。因此在MVC中"area"键是有特殊用途的,所以不能用于url pattern的参数。
在Areas机制中有一个冲突需要注意。由于路由表只有一张,如果当前的url映射到了"root area"(即在Global域),那么将从当前所有的名字空间中查找Controller,此时很可能找到多个匹配的。解决方案是,在 Globla.asax.cs中设置路由的时候,为DataTokens设置优先名字空间。
进一步扩展
当从深层次了解了路由工作机制后,就进行一些自定义了。
自定义RouteBase
有前面的分析,可以知道,在inbound时Route(继承自RouteBase)需要提供一个RouteData,因此RouteBase定义 了GetRouteData方法,这是我们可以自己实现的;同时,GetVirtualPath方法用于outbound。所以,只要实现了这两个方法就 可以完成一个RouteBase的实现。比如:当想要把一个老的网站改造成新的基于MVC架构的,又不想使原来的url失效,简单的处理方案可以像下面这 样:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
public class LegacyUrlsRoute : RouteBase{ // In practice, you might fetch these from a database // and cache them in memory private static string[] legacyUrls = new string[] { "~/articles/may/zebra-danio-health-tips.html", "~/articles/VelociraptorCalendar.pdf", "~/guides/tim.smith/BuildYourOwnPC_final.asp" }; public override RouteData GetRouteData(HttpContextBase httpContext) { string url = httpContext.Request.AppRelativeCurrentExecutionFilePath; if(legacyUrls.Contains(url, StringComparer.OrdinalIgnoreCase)) { RouteData rd = new RouteData(this, new MvcRouteHandler()); rd.Values.Add("controller", "LegacyContent"); rd.Values.Add("action", "HandleLegacyUrl"); rd.Values.Add("url", url); return rd; } else return null; // Not a legacy URL } public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) { // This route entry never generates outbound URLs return null; }} |
自定义IRouteHandler
通常在MVC框架中IRouteHandler由MvcRouteHandler实现,这个MVC框架的入口。尽管如此,我们还是可以自己定义一个 IRouteHandler。当我们需要对某些请求做优化处理的时候可以考虑这样做。因为,自定义实现IRouteHandler意味着将忽略MVC框 架。比如下面这个实现:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public class HelloWorldHandler : IRouteHandler{ public IHttpHandler GetHttpHandler(RequestContext requestContext) { return new HelloWorldHttpHandler(); } private class HelloWorldHttpHandler : IHttpHandler { public bool IsReusable { get { return false; } } public void ProcessRequest(HttpContext context) { context.Response.Write("Hello, world!"); } }} |
劳动果实,转载请注明出处:http://www.cnblogs.com/P_Chou/archive/2010/11/15/details-asp-net-mvc-04.html
深入理解ASP.NET MVC(4)的更多相关文章
- 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC
系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递 七天学会ASP.NET MVC (三)— ...
- [转载]深入理解ASP.NET MVC之ActionResult
Action全局观 在上一篇最后,我们进行到了Action调用的“门口”: 1 if (!ActionInvoker.InvokeAction(ControllerContext, actionNam ...
- 深入理解ASP.NET MVC Day1
深入理解ASP.NET MVC ASP.NET vs MVC vs WebForms 许多ASP.NET开发人员开始接触MVC认为MVC与ASP.NET完全没有关系,是一个全新的Web开发,事实上 ...
- 七天学会ASP.NET MVC ——深入理解ASP.NET MVC
七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会ASP.NET MVC (二) ...
- 深入理解ASP.NET MVC(6)
系列目录 Action全局观 在上一篇最后,我们进行到了Action调用的“门口”: 1 if (!ActionInvoker.InvokeAction(ControllerContext, acti ...
- 深入理解ASP.NET MVC(5)
系列目录 回顾 系列的前4节深入剖析了ASP.NET URL路由机制,以及MVC在此基础上是如何实现Areas机制的,同时涉及到inbound和outbound很多细节部分.第2节中提到MvcRout ...
- 深入理解ASP.NET MVC(目录)
学ASP.NET MVC2有一段时间了,也针对性的做了个练习.感觉这个框架还是不错的,所以决定要深入系统的学习一下.看到这样一本书: 作者博客:http://blog.stevensanderson. ...
- 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 【转】
http://www.cnblogs.com/powertoolsteam/p/MVC_one.html 系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会A ...
- [转载] ASP.NET MVC (一)——深入理解ASP.NET MVC
个人认为写得比较透彻得Asp.net mvc 文章,所以转载过来,原文链接在最后: ASP.NET vs MVC vs WebForms 许多ASP.NET开发人员开始接触MVC认为MVC与ASP.N ...
- 理解ASP.NET MVC的路由系统
引言 路由,正如其名,是决定消息经由何处被传递到何处的过程.也正如网络设备路由器Router一样,ASP.NET MVC框架处理请求URL的方式,同样依赖于一张预定义的路由表.以该路由表为转发依据,请 ...
随机推荐
- EchoService
dubbo为consumer端的代理对象实现了EchoService接口. 使用示例: <dubbo:reference id="hello" interface=" ...
- jsp el函数库
EL函数库介绍 由于在JSP页面中显示数据时,经常需要对显示的字符串进行处理,所以SUN公司针对一些常见的处理定义了一套EL函数库供开发者使用. 这些EL函数在JSTL开发包中进行描述,因此在JSP页 ...
- [C#]C#彩色扭曲验证码
该验证码生成类集合了网上大部分的验证码生成类的精华,博采众长并多次改进,现在已经形成了可在生产环节中使用的验证码. 该验证码加入了背景噪点,背景噪点曲线和直线,背景噪点文字以及扭曲,调暗,模糊等.完全 ...
- 微信小程序-注册和第一个demo
第一篇 申请帐号 https://mp.weixin.qq.com/cgi-bin/registermidpage?action=index&lang=zh_CN 这里注册帐号,记得选小程序, ...
- 反向-代理 nginx for Mac 的配置以及使用
反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端 ...
- Mysql 时间类型整理
一.date_sub.SUBDATE.date_add select now(), date_sub(now(),interval 1 minute),SUBDATE(now(),interval ...
- IE 11 回车事件代码不起作用但是在chrom可以正常运行解决办法
今天遇到这个问题,搞半天开始以为是代码写错了,后面拿到chrom上执行发现是正常的,就是这段代码 function EnterPress(){ if(event.keyCode == ...
- SharePoint SSS(Security Store Service)服务-PowerShell
1. 获取SSS应用程序的标识 Get-SPServiceApplication 2. 获取指定的SSS应用程序实例 $sss = Get-SPServiceApplication -Identity ...
- TJson.format() 输出错误的CRLF
下面的JSON串: { "a":"x=\"a,b\"" } 通过下面代码输出,多了CRLF: procedure JsonFormatTes ...
- .Net Entity Framework Core 用 HasColumnType 配置浮点数精度
一.前言 前段时间用.Net Entity Framework core搭建框架,需要配置浮点数的精度,发现.Net Entity Framework core 并没有HasPrecision方法.在 ...