1、概要当我们新建一个MVC项目时,打开他的Web.Config文件可以发现 <httpModules> <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> 我们知道ScriptModule 类就是管理用于 ASP.NET 中 AJAX 功能的 HTTP 模块,在此我们不做介绍 <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> //这个UrlRoutingModule类才是重点 </httpModules> 这个HttpModule,拦截所有请求,对请求进行处理,最终创建和执行合适的处理请求的HttpHandler(MVC3之后,这个UrlRoutingModule集成到MVC程序集中了)。
当客户端在本地浏览器上输入网址来请求咱们的一个MVC程序时,服务端接收到请求.....此处省略N个字(和asp.net处理一样)..... HttpApplication的事件注册,即将 UrlRoutingModule 注册到HttpApplication的事件中 public class UrlRoutingModule : IHttpModule { protected virtual void Init(HttpApplication application) { //开始只是把要执行的具体方法注册到事件中,等待事件被触发时,在执行已被注册的方法。 application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache); application.PostMapRequestHandler += new EventHandler(this.OnApplicationPostMapRequestHandler); } } 注册完事件之后,那么就要开始执行HttpApplication事件。 1、执行Global.asax文件中Application_Start方法。 protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RegisterRoutes(RouteTable.Routes); } public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Default", // 路由名称 "{controller}/{action}/{id}", // 带有参数的 URL new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 参数默认值 ); //在路由表里添加一条路由规则 } 2、依次执行HttpApplication的事件。BeginRequest
AuthenticateRequest
PostAuthenticateRequest
AuthorizeRequest
PostAuthorizeRequest
ResolveRequestCache
PostResolveRequestCache 在UrlRoutingModule类中,在此事件中注册了一个执行方法,即:OnApplicationPostResolveRequestCache
PostMapRequestHandler OnApplicationPostMapRequestHandler
AcquireRequestState
PostAcquireRequestState
PreRequesHandlerExecute
PostRequeshandlerExecute
ReleaseRequesState
PostReleaseRequestState
UpdateRequestCache
PostUpdateRequestCach
LogRequest
PostLogRequest
EndRequest
OnApplicationPostResolveRequestCache方法
private void OnApplicationPostResolveRequestCache(object sender, EventArgs e) { HttpContextBase context = new HttpContextWrapper(((HttpApplication) sender).Context); this.PostResolveRequestCache(context); } //这里用HttpContextWrapper类包装当前的HttpContext,实质上也是一个请求的上下文。他可以使用诸如Typemock Isolator或Rhino Mocks的Mock对象框进行模拟变得更简单。 //并把这个包装之后的上下文作为PostResolveRequestCache的参数 ------------------------------------------------------------------------------------------------------------------ public virtual void PostResolveRequestCache(HttpContextBase context) { RouteData routeData = this.RouteCollection.GetRouteData(context); //GetRouteData方法内部遍历路由集合中的每个路由对象去和上下文中指定的请求URL去匹配。如成功,就返回当前的路由对象RouteData,如不成功,返回null //this.RouteCollection就是RouteTable.Routes,即:路由集合。 if (routeData != null)----这里便是判断是否匹配成功 { IRouteHandler routeHandler = routeData.RouteHandler;----//获取一个处理当前匹配成功的路由的对象 MvcRouteHandler
if (httpHandler == null) { throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, RoutingResources.UrlRoutingModule_NoHttpHandler, new object[] { routeHandler.GetType() })); } //RequestData类是UrlRoutingModule类中嵌套的一个私有类,把处理请求的类和当前请求的虚拟路径 RequestData data2 = new RequestData { OriginalPath = context.Request.Path, HttpHandler = httpHandler }; context.Items[_requestDataKey] = data2; //把封装的处理类MvcHandler和请求的虚拟路径,赋值到 HttpContextWrapper类中。(这样在用到处理类时,就需要实例化,直接取值即可) //HttpContextWrapper类包装当前的HttpContext,实质上也是一个请求的上下文。 context.RewritePath("~/UrlRouting.axd"); context.RemapHandler(httpHandler);//博客是里这里是这么一句,但是我反编译没找到,可能是版本的问题吧! } } }
OnApplicationPostMapRequestHandler方法 View Code
上文中得到了一个MvcHandler类实例,MvcHandler继承实现了IHttpAsyncHandler, IHttpHandler,
IRequiresSessionState三个接口。而这三个接口如果都实现了,在MVC框架下是不是任何http请求就可以通吃了吗?从MSDN我们
得知,事实不是这样的:注意,即使 MvcHandler 实现 IHttpHandler,也不能将其映射为处理程序(例如.mvc 文件扩展名),因为该类不支持无参数构造函数。 (它唯一的构造函数需要一个 RequestContext 对象) 如你所知,MvcHttpHandler可以“弥补”MvcHandler的不足,为什么这样说呢?因为MvcHandler没有无参的构造函数,因此即使MvcHandler实现了 IHttpHandler接口,在IIS中也不能将其映射为某类文件扩展名的处理程序,而MvcHttpHandler就提供了不通过路由模块的情况下直接处理映射的处理程序。
3、HttpApplication事件继续执行BeginRequest
AuthenticateRequest
PostAuthenticateRequest
AuthorizeRequest
PostAuthorizeRequest
ResolveRequestCache
PostResolveRequestCache
PostMapRequestHandler
AcquireRequestState
PostAcquireRequestState
PreRequesHandlerExecute
PostRequeshandlerExecute
ReleaseRequesState
PostReleaseRequestState
UpdateRequestCache
PostUpdateRequestCach
LogRequest
PostLogRequest
EndRequest
在11-12个事件的时候拿到第7个事件的时候创建的MVCHandler对象执行他的ProcessRequest方法。 public class MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState { protected virtual void ProcessRequest(HttpContext httpContext) { //使用HttpContextWrapper对HttpContext进行封装,封装的目的是为了解耦以获得可测试性.然后从RequestContext.RouteData中提取Controller名称. HttpContextBase httpContext2 = new HttpContextWrapper(httpContext); this.ProcessRequest(httpContext2); } protected internal virtual void ProcessRequest(HttpContextBase httpContext) { IController controller; IControllerFactory controllerFactory; this.ProcessRequestInit(httpContext, out controller, out controllerFactory); //获取到Controler实例 ----下节详细介绍 try { controller.Execute(this.RequestContext); //当前Controler对象的Action的创建与执行 ----下节详细介绍 流程如下图,MvcHandler实例来处理请求,他做为处理的主干,当完成之后,释放当前的Controler实例,继续执行HttpApplication事件 此图摘自:http://www.cnblogs.com/terrysun/archive/2010/03/19/1690052.html |
|