Asp.net MVC生命周期

Asp.net 应用程序管道处理用户请求时特别强调 " 时机 " ,对 Asp.net 生命周期的了解多少直接影响我们写页面和控件的效率。因此在 2007 年和 2008 年我在这个话题上各写了一篇文章:

对于Asp.net MVC,我对它的生命周期还是兴趣很浓,于是提出两个问题:

一个HTTP请求从IIS移交到Asp.net运行时,Asp.net MVC是在什么时机获得了控制权并对请求进行处理呢?处理过程又是怎样的?

mvcapp

IIS7asp.net应用程序生命周期为例,下图是来自MSDN的一张HTTP请求处理过程发生事件的简图,后面我列出了一个完整的事件列表。既然Asp.net Mvc还是以Asp.net运行时为基础那么它必然要在Asp.net应用程序的生命周期中对请求进行截获。第一反应当然是去web.config里面去翻翻,我们可以看到UrlRoutingModule的配置节:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> < add name ="UrlRoutingModule" type ="System.Web.Routing.UrlRoutingModule,System.Web.Routing,Version=3.5.0.0,Culture=neutral,PublicKeyToken=31BF3856AD364E35" />

下面要做的就顺理成章了,用Reflector打开这个程序集,可以看到以下代码:

Code
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->protectedvirtualvoidInit(HttpApplicationapplication)
{
application.PostResolveRequestCache
+=newEventHandler(this.OnApplicationPostResolveRequestCache);
application.PostMapRequestHandler
+=newEventHandler(this.OnApplicationPostMapRequestHandler);
}

看到这里我们的第一个问题实际上已经有了答案:时机是在PostResolveRequestCachePostMapRequestHandler.

ResolveRequestCache event
Occurs when ASP.NET finishes an authorization event to let the caching modules serve requests from the cache, bypassing execution of the event handler (for example, a page or an XML Web service).

源文档 <http://msdn.microsoft.com/en-us/library/system.web.httpapplication.resolverequestcache.aspx>

PostMapRequestHandler event
Occurs when ASP.NET has mapped the current request to the appropriate event handler.

源文档 <http://msdn.microsoft.com/en-us/library/system.web.httpapplication.postmaprequesthandler.aspx>

我们使用VS2008Asp.net Mvc模板创建一个Demo完成后续的讨论,当我们访问/Home的时候发生了什么呢?

  1. Request 请求到来
  2. IIS 根据请求特征将处理权移交给 ASP.NET
  3. UrlRoutingModule 将当前请求在 Route Table 中进行匹配
  4. UrlRoutingModule RouteCollection 中查找 Request 匹配的 RouteHandler, 默认是 MvcRouteHandler MvcRouteHandler 创建 MvcHandler 实例 .
  5. MvcHandler 执行 ProcessRequest.
  6. MvcHandler 使用 IControllerFactory 获得实现了 IController 接口的实例 , 找到对应的 HomeController
  7. 根据 Request 触发 HomeController Index 方法
  8. Index 将执行结果存放在 ViewData
  9. HomeController Index 方法返回 ActionResult
  10. Views/Home/Index.aspx ViewData 呈现在页面上
  11. Index.aspx 执行 ProcessRequest 方法
  12. Index.aspx 执行 Render 方法 输出到客户端

通过阅读Asp.net Mvc的源码,我们可以得到更为详细的处理过程,我尽可能的忽略掉枝节,强调请求处理的流程.我们从Global.asax.cs文件切入,下面是一段样例代码,这里初始化了路由表,请特别特别注意注释部分:

Code
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->publicclassMvcApplication:System.Web.HttpApplication
{
publicstaticvoidRegisterRoutes(RouteCollectionroutes)
{
routes.IgnoreRoute(
"{resource}.axd/{*pathInfo}");

//ThecontrollerroutevalueisaspecialvaluethattheSystem.Web.Mvc.MvcHandlerclassusestocallintotheIControllerFactoryinterface.
//ThebasicroutehandlerisaninstanceofIRouteHandlernamedMvcRouteHandler.
//WehavecompletecontrolandcouldprovideourownimplementationofIRouteHandlerifwewished.
routes.MapRoute(
"Default",//Routename
"{controller}/{action}/{id}",//URLwithparameters
new{controller="Home",action="Index",id=""}//Parameterdefaults
);


}

protectedvoidApplication_Start()
{
RegisterRoutes(RouteTable.Routes);
}

UrlRoutingMoudulePostResolveRequestCache阶段从RouteCollection中获取当前请求的RouteData.RouteData包含了一个请求处理对应的ControllerAction,RouteData这个作用贯穿请求的处理过程.RouteData中提取RouteHandler,这里默认是MvcRouteHandler,MvcRouteHandler获取HttpHandler,这里默认的是MvcHandler.

PostResolveRequestCache
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->publicvirtualvoidPostResolveRequestCache(HttpContextBasecontext)
{
RouteDatarouteData
=this.RouteCollection.GetRouteData(context);
if(routeData!=null)
{
IRouteHandlerrouteHandler
=routeData.RouteHandler;
if(routeHandler==null)
{
thrownewInvalidOperationException(string.Format(CultureInfo.CurrentUICulture,RoutingResources.UrlRoutingModule_NoRouteHandler,newobject[0]));
}

if(!(routeHandlerisStopRoutingHandler))
{
RequestContextrequestContext
=newRequestContext(context,routeData);
IHttpHandlerhttpHandler
=routeHandler.GetHttpHandler(requestContext);
if(httpHandler==null)
{
thrownewInvalidOperationException(string.Format(CultureInfo.CurrentUICulture,RoutingResources.UrlRoutingModule_NoHttpHandler,newobject[]{routeHandler.GetType()}));
}

RequestDatadata2
=newRequestData();
data2.OriginalPath
=context.Request.Path;
data2.HttpHandler
=httpHandler;
context.Items[_requestDataKey]
=data2;
context.RewritePath(
"~/UrlRouting.axd");
}

}

}

rh

MvcHandler.ProcessRequest()中首先使用HttpContextWrapperHttpContext进行封装,封装的目的是为了解耦以获得可测试性.然后从RequestContext.RouteData中提取Controller名称.
ControllerBuilder.GetControllerFactory --> ControllerFactory.CreateController --> IController.Execute

ControllerBase实现了IController接口,Initialize时将RequestContext封装成为ControllerContext,Controller继承自ControllerBase并实现抽象方法ExecuteCore()

mvchttp

ExecuteCore,Controller首先从RouteData中获得ActionName,然后执行ActionInvoker.InvokeAction.

ActionInvoker中我们可以看到各种Filter,这是一种AOP实践:Action方法执行的前后执行若干方法.这里有四种Filter:ActionFilters,ResultFilters,AuthorizationFilters,ExceptionFilters.这四种Filter并不是封闭的,都有对应的接口,这四个只是默认实现.Filter的执行顺序是:AuthorizationFilter--->Action Filter.OnActionExecuting--->Action Method--->ActionFilter.OnActionExecuted.InvokeActionMethodWithFilters返回的结果是ActionExecutedContext,接下来将Controller执行OnResultExecuting 方法.ActionResult执行的结果可以是ViewResult,JsonResult,RedirectResult,ContentResult,或者是自定义的Result类型.

如果返回的类型是ViewResult,我们先看一下ViewReuslt的继承关系:ViewResult-->ViewResultBase-->ActionResult,ViewResult包含两个属性ViewViewEngineCollection,实际上是包含了两个接口的实现:IViewEngine定义了怎么定位View/Partial View.IView定义了如何RenderView.默认的实现时WebFormViewWebFormViewEngine.

Filter OnResultExecuted 最后一步了,可以这里捕获异常.上面我们说过还有ExceptionFilters,如果前面过程中的异常没有被捕获那么最终都会到冒泡到ExceptionFilters.

  • RouteData中获得ActionName
  • ActionInvoker.InvokeAction
  • 通过ControllerContext获取ControllerDescriptor
  • FindAction-获取ActionDescriptor
  • GetFilters
  • ModelBinderRequest中的数据转换成Action方法需要的参数
  • AuthorizationFilter
  • Action Filter.OnActionExecuting
  • Action
  • ActionFilter.OnActionExecuted
  • ResultFilter.OnResultExecuting
  • ActionResult Execution
  • ResultFilter.OnResultExecuted
  • WebFormViewEngine.CreateView
  • WebFormView.Render
  • ResultFilter.OnExecuted

result

控制权归还到HttpApplication完成后续的生命周期.

嗯哼,全文完.

最后跑题一句:要找工作了,有好机会联系我:mailto:[email protected]

坚强2002和你一起回头再说...

你可能感兴趣的:(.net,mvc,Web,asp.net,asp)