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); }
我们发现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); }
向下找
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
就到这吧,后面就是通过反射了。
好了,就、这就是请求进入到控制器操作的基本流程了。