MVC的控制器的激活过程,我们从MvcHandler开始讲,前面的事情以后再讲

一、从MvcHandler开始(不要觉得是代码,让你看懂才是最重要的)

using Microsoft.Web.Infrastructure.DynamicValidationHelper;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Web.Mvc.Async;
using System.Web.Mvc.Properties;
using System.Web.Routing;
using System.Web.SessionState;
namespace System.Web.Mvc
{
    /// <summary>Selects the controller that will handle an HTTP request.</summary>
    public class MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState
    {
        private static readonly object _processRequestTag = new object();
        internal static readonly string MvcVersion = MvcHandler.GetMvcVersionString();
        /// <summary>Contains the header name of the ASP.NET MVC version.</summary>
        public static readonly string MvcVersionHeaderName = "X-AspNetMvc-Version";
        private ControllerBuilder _controllerBuilder;
        internal ControllerBuilder ControllerBuilder
        {
            get
            {
                if (this._controllerBuilder == null)
                {
                    this._controllerBuilder = ControllerBuilder.Current;
                }
                return this._controllerBuilder;
            }
            set
            {
                this._controllerBuilder = value;
            }
        }
        /// <summary>Gets or sets a value that indicates whether the MVC response header is disabled.</summary>
        /// <returns>true if the MVC response header is disabled; otherwise, false.</returns>
        public static bool DisableMvcResponseHeader
        {
            get;
            set;
        }
        /// <summary>Gets a value that indicates whether another request can use the <see cref="T:System.Web.IHttpHandler" /> instance.</summary>
        /// <returns>true if the <see cref="T:System.Web.IHttpHandler" /> instance is reusable; otherwise, false.</returns>
        protected virtual bool IsReusable
        {
            get
            {
                return false;
            }
        }
        /// <summary>Gets the request context.</summary>
        /// <returns>The request context.</returns>
        public RequestContext RequestContext
        {
            get;
            private set;
        }
        /// <summary>Gets a value that indicates whether another request can use the <see cref="T:System.Web.IHttpHandler" /> instance.</summary>
        /// <returns>true if the <see cref="T:System.Web.IHttpHandler" /> instance is reusable; otherwise, false.</returns>
        bool IHttpHandler.IsReusable
        {
            get
            {
                return this.IsReusable;
            }
        }
        /// <summary>Initializes a new instance of the <see cref="T:System.Web.Mvc.MvcHandler" /> class.</summary>
        /// <param name="requestContext">The request context.</param>
        /// <exception cref="T:System.ArgumentNullException">The <paramref name="requestContext" /> parameter is null.</exception>
        public MvcHandler(RequestContext requestContext)
        {
            if (requestContext == null)
            {
                throw new ArgumentNullException("requestContext");
            }
            this.RequestContext = requestContext;
        }
        /// <summary>Adds the version header by using the specified HTTP context.</summary>
        /// <param name="httpContext">The HTTP context.</param>
        protected internal virtual void AddVersionHeader(HttpContextBase httpContext)
        {
            if (!MvcHandler.DisableMvcResponseHeader)
            {
                httpContext.Response.AppendHeader(MvcHandler.MvcVersionHeaderName, MvcHandler.MvcVersion);
            }
        }
        /// <summary>Called by ASP.NET to begin asynchronous request processing.</summary>
        /// <returns>The status of the asynchronous call.</returns>
        /// <param name="httpContext">The HTTP context.</param>
        /// <param name="callback">The asynchronous callback method.</param>
        /// <param name="state">The state of the asynchronous object.</param>
        protected virtual IAsyncResult BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, object state)
        {
            HttpContextBase httpContext2 = new HttpContextWrapper(httpContext);
            return this.BeginProcessRequest(httpContext2, callback, state);
        }
        /// <summary>Called by ASP.NET to begin asynchronous request processing using the base HTTP context.</summary>
        /// <returns>The status of the asynchronous call.</returns>
        /// <param name="httpContext">The HTTP context.</param>
        /// <param name="callback">The asynchronous callback method.</param>
        /// <param name="state">The state of the asynchronous object.</param>
        protected internal virtual IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state)
        {
            IController controller;
            IControllerFactory factory;
            this.ProcessRequestInit(httpContext, out controller, out factory);
            IAsyncController asyncController = controller as IAsyncController;
            if (asyncController != null)
            {
                BeginInvokeDelegate beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState)
                {
                    IAsyncResult result;
                    try
                    {
                        result = asyncController.BeginExecute(this.RequestContext, asyncCallback, asyncState);
                    }
                    catch
                    {
                        factory.ReleaseController(asyncController);
                        throw;
                    }
                    return result;
                };
                EndInvokeDelegate endDelegate = delegate(IAsyncResult asyncResult)
                {
                    try
                    {
                        asyncController.EndExecute(asyncResult);
                    }
                    finally
                    {
                        factory.ReleaseController(asyncController);
                    }
                };
                SynchronizationContext synchronizationContext = SynchronizationContextUtil.GetSynchronizationContext();
                AsyncCallback callback2 = AsyncUtil.WrapCallbackForSynchronizedExecution(callback, synchronizationContext);
                return AsyncResultWrapper.Begin(callback2, state, beginDelegate, endDelegate, MvcHandler._processRequestTag);
            }
            Action action = delegate
            {
                try
                {
                    controller.Execute(this.RequestContext);
                }
                finally
                {
                    factory.ReleaseController(controller);
                }
            };
            return AsyncResultWrapper.BeginSynchronous(callback, state, action, MvcHandler._processRequestTag);
        }
        /// <summary>Called by ASP.NET when asynchronous request processing has ended.</summary>
        /// <param name="asyncResult">The asynchronous result.</param>
        protected internal virtual void EndProcessRequest(IAsyncResult asyncResult)
        {
            AsyncResultWrapper.End(asyncResult, MvcHandler._processRequestTag);
        }
        private static string GetMvcVersionString()
        {
            return new AssemblyName(typeof(MvcHandler).Assembly.FullName).Version.ToString(2);
        }
        /// <summary>Processes the request by using the specified HTTP request context.</summary>
        /// <param name="httpContext">The HTTP context.</param>
        protected virtual void ProcessRequest(HttpContext httpContext)
        {
            HttpContextBase httpContext2 = new HttpContextWrapper(httpContext);
            this.ProcessRequest(httpContext2);
        }
        /// <summary>Processes the request by using the specified base HTTP request context.</summary>
        /// <param name="httpContext">The HTTP context.</param>
        protected internal virtual void ProcessRequest(HttpContextBase httpContext)
        {
            IController controller;
            IControllerFactory controllerFactory;
            this.ProcessRequestInit(httpContext, out controller, out controllerFactory);
            try
            {
                controller.Execute(this.RequestContext);
            }
            finally
            {
                controllerFactory.ReleaseController(controller);
            }
        }
        private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)
        {
            HttpContext current = HttpContext.Current;
            if (current != null && ValidationUtility.IsValidationEnabled(current) == true)
            {
                ValidationUtility.EnableDynamicValidation(current);
            }
            this.AddVersionHeader(httpContext);
            this.RemoveOptionalRoutingParameters();
            string requiredString = this.RequestContext.RouteData.GetRequiredString("controller");
            factory = this.ControllerBuilder.GetControllerFactory();
            controller = factory.CreateController(this.RequestContext, requiredString);
            if (controller == null)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.ControllerBuilder_FactoryReturnedNull, new object[]
                {
                    factory.GetType(),
                    requiredString
                }));
            }
        }
        private void RemoveOptionalRoutingParameters()
        {
            RouteValueDictionary values = this.RequestContext.RouteData.Values;
            string[] array = (
                from entry in values
                where entry.Value == UrlParameter.Optional
                select entry.Key).ToArray<string>();
            string[] array2 = array;
            for (int i = 0; i < array2.Length; i++)
            {
                string key = array2[i];
                values.Remove(key);
            }
        }
        /// <summary>Enables processing of HTTP Web requests by a custom HTTP handler that implements the <see cref="T:System.Web.IHttpHandler" /> interface.</summary>
        /// <param name="httpContext">An <see cref="T:System.Web.HttpContext" /> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) that are used to service HTTP requests.</param>
        void IHttpHandler.ProcessRequest(HttpContext httpContext)
        {
            this.ProcessRequest(httpContext);
        }
        /// <summary>Called by ASP.NET to begin asynchronous request processing using the base HTTP context.</summary>
        /// <returns>The status of the asynchronous call.</returns>
        /// <param name="context">The HTTP context.</param>
        /// <param name="cb">The asynchronous callback method.</param>
        /// <param name="extraData">The data.</param>
        IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
        {
            return this.BeginProcessRequest(context, cb, extraData);
        }
        /// <summary>Called by ASP.NET when asynchronous request processing has ended.</summary>
        /// <param name="result">The asynchronous result.</param>
        void IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
        {
            this.EndProcessRequest(result);
        }
    }
}
View Code

我们暂时以MvcHandler为起点,至于前面谁调用了它,大家先自行研究。

系统控制权移交到MvcHandler时,这时候MVC应该说正式上场了,前面我们叫做准备工作吧。

 MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState

IHttpAsyncHandler, IHttpHandler定义 ASP.NET 为使用自定义 HTTP 处理程序,同时开启了session.

 

void IHttpHandler.ProcessRequest(HttpContext httpContext)
        {
            this.ProcessRequest(httpContext);
        }

 

protected virtual void ProcessRequest(HttpContext httpContext)
{
    HttpContextBase httpContext2 = new HttpContextWrapper(httpContext);
    this.ProcessRequest(httpContext2);
}

 

protected internal virtual void ProcessRequest(HttpContextBase httpContext)
{
    IController controller;
    IControllerFactory controllerFactory;
    this.ProcessRequestInit(httpContext, out controller, out controllerFactory);//初始化工作
    try
    {
        controller.Execute(this.RequestContext);//进入主战场了
    }
    finally
    {
        controllerFactory.ReleaseController(controller);
    }
}

二、初始化

private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)
{
    HttpContext current = HttpContext.Current;
    if (current != null && ValidationUtility.IsValidationEnabled(current) == true)
    {
        ValidationUtility.EnableDynamicValidation(current);
    }
    this.AddVersionHeader(httpContext);//httpContext 封装有关个别 HTTP 请求的所有 HTTP 特定的信息
    this.RemoveOptionalRoutingParameters();
    string requiredString = this.RequestContext.RouteData.GetRequiredString("controller");
    factory = this.ControllerBuilder.GetControllerFactory();
    controller = factory.CreateController(this.RequestContext, requiredString);//创建了一个controller 对象if (controller == null)
    {
        throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.ControllerBuilder_FactoryReturnedNull, new object[]
        {
            factory.GetType(),
            requiredString
        }));
    }
}

三、主战场

controller.Execute(this.RequestContext);//进入主战场了,controllerIController,但其实一个Controller实例,
而 Controller : ControllerBase
,所以进入ControllerBase里面看看
protected virtual void Execute(RequestContext requestContext)
        {
            if (requestContext == null)
            {
                throw new ArgumentNullException("requestContext");
            }
            if (requestContext.HttpContext == null)
            {
                throw new ArgumentException(MvcResources.ControllerBase_CannotExecuteWithNullHttpContext, "requestContext");
            }
            this.VerifyExecuteCalledOnce();
            this.Initialize(requestContext);
            using (ScopeStorage.CreateTransientScope())
            {
                this.ExecuteCore();//也就是调用了Controller 的ExecuteCore方法
            }
        }

protected override void ExecuteCore()
        {
            this.PossiblyLoadTempData();
            try
            {
                string requiredString = this.RouteData.GetRequiredString("action");
                if (!this.ActionInvoker.InvokeAction(base.ControllerContext, requiredString))
                {
                    this.HandleUnknownAction(requiredString);
                }
            }
            finally
            {
                this.PossiblySaveTempData();
            }
        }
public IActionInvoker ActionInvoker
{
    get
    {
        if (this._actionInvoker == null)
        {
            this._actionInvoker = this.CreateActionInvoker();
        }
        return this._actionInvoker;
    }
    set
    {
        this._actionInvoker = value;
    }
}
protected virtual IActionInvoker CreateActionInvoker()
{
    IAsyncActionInvoker arg_23_0;
    if ((arg_23_0 = this.Resolver.GetService<IAsyncActionInvoker>()) == null)//
   // 没有异步的就看看有没有同步的,没有同步的就直接初始化一个异步的。
//这里牵扯到IOC,但系统默认的如下(DefaultDependencyResolver,把它放到了缓存中提高性能(CacheDependencyResolver )),当然可能用户自己定义。 { arg_23_0
= (this.Resolver.GetService<IActionInvoker>() ?? new AsyncControllerActionInvoker()); } return arg_23_0; }

public interface IAsyncActionInvoker : IActionInvoker
    {

        IAsyncResult BeginInvokeAction(ControllerContext controllerContext, string actionName, AsyncCallback callback, object state);
        bool EndInvokeAction(IAsyncResult asyncResult);
    }

private sealed class CacheDependencyResolver : IDependencyResolver
{
    private readonly ConcurrentDictionary<Type, object> _cache = new ConcurrentDictionary<Type, object>();
    private readonly ConcurrentDictionary<Type, IEnumerable<object>> _cacheMultiple = new ConcurrentDictionary<Type, IEnumerable<object>>();
    private readonly IDependencyResolver _resolver;
    public CacheDependencyResolver(IDependencyResolver resolver)
    {
        this._resolver = resolver;
    }
    public object GetService(Type serviceType)
    {
        return this._cache.GetOrAdd(serviceType, new Func<Type, object>(this._resolver.GetService));
    }
    public IEnumerable<object> GetServices(Type serviceType)
    {
        return this._cacheMultiple.GetOrAdd(serviceType, new Func<Type, IEnumerable<object>>(this._resolver.GetServices));
    }
}
this.InnerSetResolver(new DependencyResolver.DefaultDependencyResolver());
private class DefaultDependencyResolver : IDependencyResolver
{
    public object GetService(Type serviceType)
    {
        if (serviceType.IsInterface || serviceType.IsAbstract)
        {
            return null;
        }
        object result;
        try
        {
            result = Activator.CreateInstance(serviceType);
        }
        catch
        {
            result = null;
        }
        return result;
    }
    public IEnumerable<object> GetServices(Type serviceType)
    {
        return Enumerable.Empty<object>();
    }
}

private sealed class CacheDependencyResolver : IDependencyResolver
        {
            private readonly ConcurrentDictionary<Type, object> _cache = new ConcurrentDictionary<Type, object>();
            private readonly ConcurrentDictionary<Type, IEnumerable<object>> _cacheMultiple = new ConcurrentDictionary<Type, IEnumerable<object>>();
            private readonly IDependencyResolver _resolver;
            public CacheDependencyResolver(IDependencyResolver resolver)
            {
                this._resolver = resolver;
            }
            public object GetService(Type serviceType)
            {
                return this._cache.GetOrAdd(serviceType, new Func<Type, object>(this._resolver.GetService));
            }
            public IEnumerable<object> GetServices(Type serviceType)
            {
                return this._cacheMultiple.GetOrAdd(serviceType, new Func<Type, IEnumerable<object>>(this._resolver.GetServices));
            }
    
 
IActionInvoker,系统采用IOC创建了一个IActionInvoker对应的实例,我们不知道是什么类型,但无非AsyncControllerActionInvoker : ControllerActionInvoker
这两个(当然前者还是继承了后者)
,此处我们以
ControllerActionInvoker作为讨论对象。其中的方法如下
public virtual bool InvokeAction(ControllerContext controllerContext, string actionName)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }
            if (string.IsNullOrEmpty(actionName))
            {
                throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");
            }
            ControllerDescriptor controllerDescriptor = this.GetControllerDescriptor(controllerContext);
            ActionDescriptor actionDescriptor = this.FindAction(controllerContext, controllerDescriptor, actionName);
            if (actionDescriptor != null)
            {
                FilterInfo filters = this.GetFilters(controllerContext, actionDescriptor);
                try
                {
                    AuthorizationContext authorizationContext = this.InvokeAuthorizationFilters(controllerContext, filters.AuthorizationFilters, actionDescriptor);
                    if (authorizationContext.Result != null)
                    {
                        this.InvokeActionResult(controllerContext, authorizationContext.Result);
                    }
                    else
                    {
                        if (controllerContext.Controller.ValidateRequest)
                        {
                            ControllerActionInvoker.ValidateRequest(controllerContext);
                        }
                        IDictionary<string, object> parameterValues = this.GetParameterValues(controllerContext, actionDescriptor);
                        ActionExecutedContext actionExecutedContext = this.InvokeActionMethodWithFilters(controllerContext, filters.ActionFilters, actionDescriptor, parameterValues);
                        this.InvokeActionResultWithFilters(controllerContext, filters.ResultFilters, actionExecutedContext.Result);
                    }
                }
                catch (ThreadAbortException)
                {
                    throw;
                }
                catch (Exception exception)
                {
                    ExceptionContext exceptionContext = this.InvokeExceptionFilters(controllerContext, filters.ExceptionFilters, exception);
                    if (!exceptionContext.ExceptionHandled)
                    {
                        throw;
                    }
                    this.InvokeActionResult(controllerContext, exceptionContext.Result);
                }
                return true;
            }
            return false;
        }

 ControllerDescriptor

封装描述控制器的信息,如控制器的名称、类型和操作 以及一些元数据等


 System.Object 
  System.Web.Mvc.ControllerDescriptor
    System.Web.Mvc.Async.ReflectedAsyncControllerDescriptor
    System.Web.Mvc.ReflectedControllerDescriptor





下一章我们接着讲Action的执行过程

MVC的控制器的激活过程,我们从MvcHandler开始讲,前面的事情以后再讲,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。