【轉】.net MVC 生命週期

來源:互聯網
上載者:User

標籤:技術分享   engine   http   passing   mvc   eve   四種   rom   occurs   

對於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開啟這個程式集,可以看到以下代碼:

 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);            }

 

UrlRoutingMoudule在PostResolveRequestCache階段從RouteCollection中擷取當前請求的RouteData.RouteData包含了一個請求處理對應的Controller和Action,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");        }    }}

 

 

  

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完成後續的生命週期.

 

控制權歸還到HttpApplication完成後續的生命週期.

【轉】.net MVC 生命週期

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.