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

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

MVC的控制器的激活过程,我们从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的执行过程

你可能感兴趣的:(handler)