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的执行过程

  • 相关阅读:
    计时器C#
    MySQL Database Command Line Client
    C#小爬虫,通过URL进行模拟发送接收数据
    C#导入导出Excele数据
    正则表达式动态分隔符
    C#中的枚举
    C#中的ToString格式大全
    C# 序列化与反序列化
    C# 对xml进行操作
    时间标签DateTime
  • 原文地址:https://www.cnblogs.com/humble/p/3794063.html
Copyright © 2011-2022 走看看