经典的ASP.NET应用程序,当我们请求页面时,通常每一个页面请求都会映射到网站中的一个物理页面。
ASP.NET MVC不是以这种方式工作的。当我们请求一个ASP.NET MVC程序的地址时,网站中不一定存在着对应的页面。一般来说,对于ASP.NET MVC网站,我们不会再去请求有着.aspx扩展名的地址,而是请求一个有意义的虚拟地址,ASP.NET MVC通过RouteTable,将这个请求转发到一个叫Controller的类上,Controller负责生成内容并把它发回浏览器。
所以,在ASP.NET MVC中,就用RouteTable来定义各种URL到实际处理程序之间的映射。
具体而言,是由Route类来指定ASP.NET 应用程序中针对虚拟路径请求的处理方法。
你可以为每种URL模式来创建一个Route对象。
而RouteTable的routes属性是Route对象的集合。
创建RouteTable
这里有三个问题需要思考:
(1)何时创建?
(2)在哪里创建?
(3)如何创建?
答案:
(1)何时创建?
在请求处理之前。
(2)在哪里创建?
在Global.asax.cs文件的Application_Start中(注册)。
(3)如何创建?
下面是VS2010新建ASP.NET MVC项目时默认的Global.aspx.cs文件的代码片段:
在此文件中,应用程序默认为路由增加了2个路由对象:
第一个路由是用于忽略特殊请求的路由,这个路由忽略所有扩展名为.axd的请求,这些请求会按照WebForm经典的方式进行处理。
第二个路由由映射任何符合{controller}/{action}/{id}模式是URL到MvcRouteHandler。它还提供了一个默认的参数。
思考:
那么,ASP.NET MVC又是如何通过RouteTable将请求映射到ASP.NET的处理管道中进行处理的呢?
其实,在ASP.NET MVC中,HttpApplication的处理管道并没有发生变化,变化的只有处理程序部分。
在经典方式下,我们会通过请求路径来定位具体的处理程序或者文件,如果找不到则会返回404错误。所以,必须要在HttpApplication寻找处理程序之前,必须设置一个肯定可以找到的处理器的请求路径。
ASP.NET MVC也是如此。
那对于上边的那个思考问题,答案就是:UrlRoutingModule负责解决这个问题。
UrlRoutingModule事件处理
当我们对ASP.NET MVC应用程序发起请求的时候,请求被送入HttpApplication的处理管道,UrlRoutingModule注册了HttpApplication的PostResolveRequestCache事件和PostMapRequestHandler事件。
在HttpApplication寻找处理程序之前,设置一个肯定可以找到的处理器的请求路径。此时,激发了PostResolveRequestCache事件。
当HttpApplication完成处理程序查询,并成功初始化处理程序之后,在通过RouteTable将处理程序设置到HttpApplication中。此时,激发PostMapRequestHandler事件。
下面说一下这两个事件的具体处理步骤:
(1)UrlRoutingModule在PostResolveRequestChche事件中做的第一件事就是包装当前的HttpContext为HttpContextWrapper2。
(2)接着把HttpContextWrapper2传给RouteTable,RouteTable根据参数返回一个匹配的路由对象:RouteData。
(3)如果UrlRoutingModule成功获取到RouteData,则会创建HttpContext对象和RouteData的RouteContext路由对象。
(4)然后把RouteContext路由对象传递给Handler的构造函数,实例化出一个新的HttpHandler;同时把此路由对象RouteContext通过HttpContext对象的Items集合保存起来,以便在PostMapRequestHandler中使用。
(5)最后通过HttpContext的ReWritePath方法,将当前请求路径设置为一个肯定存在的路径。
(6)当PostMapRequestHandler事件触发时,ASP.NET已完成了经典的获取处理程序的操作。UrlRoutingModule将检查通过HttpContext对象的Items保存的路由对象,然后通过路由对象的参数来设置当前的处理程序。