zoukankan      html  css  js  c++  java
  • [收藏]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的配置节:

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

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

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

      

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

     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>

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

     

    public class MvcApplication : System.Web.HttpApplication
            {
                public static void RegisterRoutes(RouteCollection routes)
                {
                    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
                   
                    //The controller route value is a special value that the System.Web.Mvc.MvcHandler class uses to call into the IControllerFactory interface.
                    //The basic route handler is an instance of IRouteHandler named MvcRouteHandler.
                    //We have complete control and could provide our own implementation of IRouteHandler if we wished.
                    routes.MapRoute(
                        "Default",                                              // Route name
                        "{controller}/{action}/{id}",                           // URL with parameters
                        new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
                    );
                 
        
                }
        
                protected void Application_Start()
                {
                    RegisterRoutes(RouteTable.Routes);
                }
    

      

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

      public virtual void PostResolveRequestCache(HttpContextBase context)
    {
        RouteData routeData = this.RouteCollection.GetRouteData(context);
        if (routeData != null)
        {
            IRouteHandler routeHandler = routeData.RouteHandler;
            if (routeHandler == null)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, RoutingResources.UrlRoutingModule_NoRouteHandler, new object[0]));
            }
            if (!(routeHandler is StopRoutingHandler))
            {
                RequestContext requestContext = new RequestContext(context, routeData);
                IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
                if (httpHandler == null)
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, RoutingResources.UrlRoutingModule_NoHttpHandler, new object[] { routeHandler.GetType() }));
                }
                RequestData data2 = new RequestData();
                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包含两个属性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

    result 

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

    original:http://www.cnblogs.com/me-sa/archive/2009/06/01/MVCLifecycle.html

  • 相关阅读:
    docker 部署aps.net MVC到windows容器
    docker 搭建私有仓库 harbor
    解决关于:Oracle数据库 插入数据中文乱码 显示问号???
    ionic cordova build android error: commamd failed with exit code eacces
    cordova build android Command failed with exit code EACCES
    Xcode 10 iOS12 "A valid provisioning profile for this executable was not found
    使用remix发布部署 发币 智能合约
    区块链: 编译发布智能合约
    mac 下常用命令备忘录
    JQuery fullCalendar 时间差 排序获取距当前最近的时间。
  • 原文地址:https://www.cnblogs.com/mingjia/p/4533095.html
Copyright © 2011-2022 走看看