ASP.NET MVC 請求流程:Controller


1.請求進入時,.NET Framework就找出所有的HttpModule,以此調用它們的Init方法,如下圖所示,我們重點關注"UrlRoutingModule-4.0"的HttpModule.

2.我們看看UrlRoutingModule方法中做了哪些操作

.

  繼續往下看

  我們來到了PostResolveRequestCache方法中,我們進入RouteCollection.GetRouteData()方法中看下,如下所示

  看過上節的同學會知道這里的routeData就是System.Web.Mvc.RouteData實例,routeHandler就是System.Web.Mvc.MvcRouteHandler實例,我們來看下它們所包含的值,如下圖所示。

  這次我們進入routeHandler.GetHttpHandler()方法中看看,如下圖所示

  在上圖中,GetHttpHandler方法內主要做了兩步,第一步就是通過獲取當前MVC的會話狀態來設置此次請求的會話狀態模式,第二步就是返回一個MvcHandler實例,通過返回類型我們不難推出MvcHandler是實現了IHttpHandler接口的,據我們所知實現了IHttpHandle接口的類所謂被調用內部的ProcessRequest方法,所以下一步的目標就是System.Web.Mvc.MvcHandler.ProcessRequest方法了。在這里需要注意了,傳入參數requestContext現在包含了兩個實例,一個是HttpContext,另一個就是包含了我們在程序中定義的路由信息的對象——RouteData。

  好了,我們繼續進行,來看看System.Web.Mvc.MvcHandler.ProcessRequest()方法,但是突然發現System.Web.Mvc.MvcHandler.ProcessRequest方法壓根就沒有被調用,這是什么一回事?我們先把System.Web.Mvc.MvcHandler中的內部結構看下,如下:

       public class MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState
        {
            // 省略很多代碼
            public MvcHandler(RequestContext requestContext);
            protected virtual IAsyncResult BeginProcessRequest();
            protected virtual void EndProcessRequest();
            private static string GetMvcVersionString();
            protected virtual void ProcessRequest(HttpContext httpContext);
            private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory);
        }
View Code

  我們發現MvcHandler不止實現的IHttpHandler即接口,還實現了異步的IHttpAsyncHandler接口,那么如果程序不調用同步的ProcessRequest方法,那就一定是使用的異步的BeginProcessRequest方法。

  這是正確的,MVC5使用的異步的BeginProcessRequest方法,接下來我們去BeginProcessRequest方法中看看有哪些秘密吧。

    protected virtual IAsyncResult BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, object state)
    {
        HttpContextBase httpContextBase = new HttpContextWrapper(httpContext);
        return BeginProcessRequest(httpContextBase, callback, state);
    }
View Code

  向下找

protected internal virtual IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state)
    {
        IController controller;
        IControllerFactory factory;
//創建控制器 ProcessRequestInit(httpContext,
out controller, out factory); IAsyncController asyncController = controller as IAsyncController; if (asyncController != null) { // asynchronous controller // Ensure delegates continue to use the C# Compiler static delegate caching optimization. BeginInvokeDelegate<ProcessRequestState> beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState, ProcessRequestState innerState) { try {
// Action
return innerState.AsyncController.BeginExecute(innerState.RequestContext, asyncCallback, asyncState); } catch {
// 釋放控制器 innerState.ReleaseController();
throw; } }; EndInvokeVoidDelegate<ProcessRequestState> endDelegate = delegate(IAsyncResult asyncResult, ProcessRequestState innerState) { try { innerState.AsyncController.EndExecute(asyncResult); } finally { innerState.ReleaseController(); } }; ProcessRequestState outerState = new ProcessRequestState() { AsyncController = asyncController, Factory = factory, RequestContext = RequestContext }; SynchronizationContext callbackSyncContext = SynchronizationContextUtil.GetSynchronizationContext(); return AsyncResultWrapper.Begin(callback, state, beginDelegate, endDelegate, outerState, _processRequestTag, callbackSyncContext: callbackSyncContext); } else { // synchronous controller Action action = delegate { try { controller.Execute(RequestContext); } finally { factory.ReleaseController(controller); } }; return AsyncResultWrapper.BeginSynchronous(callback, state, action, _processRequestTag); } }

  我們先進入System.Web.Mvc.MvcHandler.ProcessRequestInit方法內看看,如下圖所示

  再深入一點,看看factory.CreateController方法

  再看看GetControllerType

  就到這吧,后面就是通過反射了。

  好了,就、這就是請求進入到控制器操作的基本流程了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM