asp.net应用程序管道处理用户请求时特别强调"时机",对asp.net生命周期的了解多少直接影响我们写页面和控件的效率。对于asp.net mvc,我对它的生命周期兴趣很浓,于是对ASP.NET MVC生命周期提出两个问题:

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

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

< add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

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

  1. protected virtual void Init(HttpApplication application)
  2. {
  3. application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);
  4. application.PostMapRequestHandler += new EventHandler(this.OnApplicationPostMapRequestHandler);
  5. }

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

我们使用VS2008中asp.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文件切入,下面是一段样例代码,这里初始化了路由表,请特别特别注意注释部分:

  1. public class mvcApplication : System.Web.HttpApplication
  2. {
  3. public static void RegisterRoutes(RouteCollection routes)
  4. {
  5. routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
  6. //The controller route value is a special value that the System.Web.mvc.mvcHandler class uses to call into the IControllerFactory interface.
  7. //The basic route handler is an instance of IRouteHandler named mvcRouteHandler.
  8. //We have complete control and could provide our own implementation of IRouteHandler if we wished.
  9. routes.MapRoute(
  10. "Default",                                              // Route name
  11. "{controller}/{action}/{id}",                           // URL with parameters
  12. new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
  13. );
  14. }
  15. protected void Application_Start()
  16. {
  17. RegisterRoutes(RouteTable.Routes);
  18. }

UrlRoutingMoudule在PostResolveRequestCache阶段从RouteCollection中获取当前请求的RouteData.RouteData包含了一个请求处理对应的Controller和Action,RouteData这个作用贯穿请求的处理过程.RouteData中提取RouteHandler,这里默认是mvcRouteHandler,mvcRouteHandler获取HttpHandler,这里默认的是mvcHandler.

  1. PostResolveRequestCache
  2. public virtual void PostResolveRequestCache(HttpContextBase context)
  3. {
  4. RouteData routeData = this.RouteCollection.GetRouteData(context);
  5. if (routeData != null)
  6. {
  7. IRouteHandler routeHandler = routeData.RouteHandler;
  8. if (routeHandler == null)
  9. {
  10. throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, RoutingResources.UrlRoutingModule_NoRouteHandler, new object[0]));
  11. }
  12. if (!(routeHandler is StopRoutingHandler))
  13. {
  14. RequestContext requestContext = new RequestContext(context, routeData);
  15. IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
  16. if (httpHandler == null)
  17. {
  18. throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, RoutingResources.UrlRoutingModule_NoHttpHandler, new object[] { routeHandler.GetType() }));
  19. }
  20. RequestData data2 = new RequestData();
  21. data2.OriginalPath = context.Request.Path;
  22. data2.HttpHandler = httpHandler;
  23. context.Items[_requestDataKey] = data2;
  24. context.RewritePath("~/UrlRouting.axd");
  25. }
  26. }
  27. }

mvcHandler.ProcessRequest()中首先使用HttpContextWrapper对HttpContext进行封装,封装的目的是为了解耦以获得可测试性.然后从RequestContext.RouteData中提取Controller名称.

ControllerBuilder.GetControllerFactory --> ControllerFactory.CreateController --> IController.Execute

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

在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包含两个属性View和ViewEngineCollection,实际上是包含了两个接口的实现:IViewEngine定义了怎么定位View/Partial View.IView定义了如何RenderView.默认的实现时WebFormView和WebFormViewEngine.

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

RouteData中获得ActionName

ActionInvoker.InvokeAction

通过ControllerContext获取ControllerDescriptor

FindAction-获取ActionDescriptor

GetFilters

ModelBinder把Request中的数据转换成Action方法需要的参数

AuthorizationFilter

Action Filter.OnActionExecuting

Action

ActionFilter.OnActionExecuted

ResultFilter.OnResultExecuting

ActionResult Execution

ResultFilter.OnResultExecuted

WebFormViewEngine.CreateView

WebFormView.Render

ResultFilter.OnExecuted

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

原文:http://developer.51cto.com/art/200907/138884.htm

转载于:https://www.cnblogs.com/zhaozhan/archive/2010/07/20/1781798.html

【转】ASP.NET MVC生命周期介绍相关推荐

  1. ASP.NET页生命周期介绍:阶段,事件及其他

    ASP.NET页生命周期介绍:阶段,事件及其他 本文概述了asp.net的页生命周期.在页生命周期的每个阶段中,页将引发可运行您自己的代码进行处理的事件. asp.net 页运行时,此页将经历一个生命 ...

  2. Asp.net MVC生命周期

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

  3. 路由网址这是mvc时代系列之三:网络路由与ASP.NET MVC生命周期(上)路由网址

    首先声明,我是一个菜鸟.一下文章中出现技术误导情况盖不负责 网络 路由途用是定决ASP.NET MVC应该以种哪方法输出网址并且返回给浏览器 .一般来说,跳转址地或者在View中表现超级链接时,都须要 ...

  4. .NET与java的MVC模式(3):ASP.NET 页生命周期概述

    ASP.NET 页生命周期概述 来源:MSDN ASP.NET 页运行时,此页将经历一个生命周期,在生命周期中将执行一系列处理步骤.这些步骤包括初始化.实例化控件.还原和维护状态.运行事件处理程序代码 ...

  5. [译] ASP.NET 生命周期 – ASP.NET 应用生命周期(一)

    概述 ASP.NET 平台定义了两个非常重要的生命周期.第一个是 应用生命周期  (application life cycle),用来追踪应用从启动的那一刻到终止的那一刻.另一个就是 请求生命周期 ...

  6. [译] ASP.NET 生命周期 – ASP.NET 请求生命周期(二)

    ASP.NET 请求生命周期 全局应用类也可以用来跟踪每个独立请求的生命周期,包括请求从 ASP.NET 平台传递到 MVC 框架.ASP.NET 框架会创建一个定义在 Global.asax 文件中 ...

  7. 记不住ASP.NET页面生命周期的苦恼

    介绍 对于ASP.NET开发者,理解ASP.NET的页面生命周期是非常重要的.主要是为了搞明白在哪里放置特定的方法和在何时设置各种页面属性.但是记忆和理解页面生命周期里提供的事件处理方法(method ...

  8. 【转】Asp.net的生命周期之应用程序生命周期

    参考:http://msdn.microsoft.com/zh-cn/library/ms178473(v=vs.100).aspx 参考:http://www.cnblogs.com/JimmyZh ...

  9. Asp.net的生命周期之应用程序生命周期

    参考:http://msdn.microsoft.com/zh-cn/library/ms178473(v=vs.100).aspx 参考:http://www.cnblogs.com/JimmyZh ...

最新文章

  1. springmvc + springboot + mybatis java b2b2c电子商城系统源码...
  2. 市面上常见的TCP/IP以太网一卡通设备硬件产品电路拆解分析
  3. abap视图字段限制_在 Laravel 控制器中进行表单请求字段验证
  4. centOS配置国内镜像
  5. android UI进阶之实现listview的分页加载
  6. SpringMVC教程下篇
  7. hdu 4421(枚举+2-sat)
  8. error:Microsoft Visual C++ 14.0 is required.
  9. bean的生命周期——Spring对bean的管理(三)
  10. 恒星播放器 for Mac(万能视频播放器)
  11. vulnhub靶机-Pwned
  12. 阿里云存储oss依赖报错解决方法
  13. 用Python生成马赛克画
  14. 阿里云同步gcr.io的镜像
  15. PCL法线计算及原理
  16. ​Podman Desktop: 一款超高颜值和功能强大的 Podman 桌面管理工具
  17. 相关系数与协方差间的转换
  18. 宏定义 定义一年多少秒
  19. Android开发读取通讯录信息
  20. 验证码图片显示不出文字

热门文章

  1. nodejs实践录:我的nodejs编码风格
  2. 一个STM32编译Makefile模板
  3. 解决ubuntu系统udev多网卡名称变化的问题
  4. 更新wordpress遇到prepare警告问题的解决
  5. 【kafka】java使用jmx 监控Kafka
  6. spark学习-65-源代码:schedulerBackend和taskScheduler的创建(3)-local-cluster
  7. spark学习-67-源代码:schedulerBackend和taskScheduler的总结
  8. 【Java】indexOf 方法区分大小写
  9. Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the class
  10. 记一次MySQL数据库恢复(附方案)