標籤:style blog http io ar color os 使用 sp
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
就到這吧,後面就是通過反射了。
好了,就、這就是請求進入到控制器操作的基本流程了。
ASP.NET MVC 請求流程:Controller