zoukankan      html  css  js  c++  java
  • 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的执行过程

  • 相关阅读:
    CodeForces gym Nasta Rabbara lct
    bzoj 4025 二分图 lct
    CodeForces 785E Anton and Permutation
    bzoj 3669 魔法森林
    模板汇总——快读 fread
    bzoj2049 Cave 洞穴勘测 lct
    bzoj 2002 弹飞绵羊 lct裸题
    HDU 6394 Tree 分块 || lct
    HDU 6364 Ringland
    nyoj221_Tree_subsequent_traversal
  • 原文地址:https://www.cnblogs.com/humble/p/3794063.html
Copyright © 2011-2022 走看看