其实这里面配置的都是系统级别的选项,而我们程序里面使用的Web.config文件只是用来配置跟应用程序相关的选项,这样的好处是我们可以在应用程序级别很方便的改变系统的默认配置;
我们找到httpModules配置节,在倒数第二行发现一个name为UrlRoutingModule-4.0的IHttpModule配置,应该就是它了,最关键的是它的type信息是System.Web.Routing.UrlRoutingModule 毋庸置疑了;
现在就好办多了,我们只要顺藤摸瓜就能找到UrlRoutingModule是如何工作的了,不过先不能急,还有些思路并不清晰,我们继续慢慢分析;按照这样的一个思路,基本上我们可以断定UrlRoutingModule就是协调ASP.NETRouting框架的纽带;
图3.1:
此图总结了我们到目前为止的一个基本思路,底层ASP.NET框架处理HTTP的对象化,然后通过ASP.NETRouting Module创建IHttpHandler接口对象,再然后就是执行IHttpHander接口,共三个步骤;
作为应用框架也就是最上层的代码,如何才能决定ASP.NETRouting框架在处理ASP.NET的调用的时候能使用自己的IHttpHander接口对象,这个问题就需要我们深入的看一下ASP.NETRouting路由对象的内部对象模型了;
4.】ASP.NETRouting路由对象模型的内部结构
这里我将使用ASP.NETMVC作为应用框架来讲解本例(目前我并不了解ASP.NETWEBAPI);那么ASP.NETMVC作为应用层框架,是如何让ASP.NETRouting帮助转换IHttpHander接口的呢,这就不得不去分析Routing一些列的对象之间的组成关系及互相作用了;
根据3.】小节,我们已经了解ASP.NETRouting是使用UrlRoutingModuel对象来作为ASP.NET管道的监听者,然后根据一系列的内部处理得出最终的IHttpHander接口对象;那么要想搞清楚UrlRoutingModule是如何具体的协调这一切的,必须得深入的去分析源代码才行,尽管我们只需要了解一个80%那也少不了这个环节;
注意:需要源代码的朋友可以直接去一下站点获取,微软官方开源网站:,开源中国:都可以找到源代码;
4.1】UrlRoutingModule对象内部结构
首当其冲需要搞清楚的就是UrlRoutingModule对象,根据源码指示我们基本上能确定几个基本的原理,首先UrlRoutingModule继承自IHttpModule接口,订阅了Application.PostResolveRequstCache事件,在该事件中主要是通过全局路由对象表RouteTable对象获取提供给上层使用的依赖注入接口IRouteHander接口;
【依赖注入接口】
这里需要解释一下什么叫依赖注入接口,可以简单的将依赖注入接口理解成提供给外界一个具体实现的机会;其实就是设计原则中的“依赖倒置原则”,在RouteData的内部不是直接依赖具体的对象;接口就是契约,提供一个接口就是约定双方之间的契约;这里是约定了Routing框架将使用IRouteHander接口来获取最后的处理IHttpHander接口;
下面我们将对UrlRoutingModule对象进行分析,由于我们分析源代码是想搞清楚对象模型之间的操作流程及关系,所以不可能分析所有的代码,我们的重点是搞清楚他们的执行顺序及原理;由于UrlRoutingModule对象是导火线,它的出现将接二连三的牵连其他的对象出现,我们将分小节进行分析,交界处将一带而过;
根据我们前面的分析思路,我们首先要找到UrlRoutingModule绑定Application事件的地方;
protected virtual void Init (HttpApplication application) { application.PostResolveRequestCache += PostResolveRequestCache; }
在PostResolverRequestCache方法中,我们将看到该方法调用了本地内部的一个同名方法:
void PostResolveRequestCache (object o, EventArgs e) { var app = (HttpApplication) o; PostResolveRequestCache (new HttpContextWrapper (app.Context)); }
然后实例化了一个HttpContextWrapper包装对象,传入该同名方法;
public virtual void PostResolveRequestCache (HttpContextBase context) { var rd = RouteCollection.GetRouteData (context); //(1)匹配RouteData对象,后面分析; var rc = new RequestContext (context, rd); //(2)封装计算出来的RouteData对象和当前HttpRequest对象; IHttpHandler http = rd.RouteHandler.GetHttpHandler (rc); //(3)使用(1)步骤计算出来的当前RouteData对象中的RouteHander属性获取路由处理程序IHttpHander接口 context.Request.RequestContext = rc; context.RemapHandler (http); }
当然我已经省略了部分不太相关的代码,毕竟要想说清楚所有的代码一篇文章显然是不够的;上述代码中我用红色标记出重要的部分;