• 白话学习MVC(八)Action的执行二


    一、概述

      上篇博文《白话学习MVC(七)Action的执行一》介绍了ASP.NET MVC中Action的执行的简要流程,并且对TempData的运行机制进行了详细的分析,本篇来分析上一篇中遗留的【3-2、ActionInvoker.InvokeAction(ControllerContext, actionName)】部分的内容,其中包含了Action的执行、过滤器的执行、View的呈现(下节介绍)。

    public abstract class Controller : ControllerBase, IActionFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter
        {protected override void ExecuteCore()
            {
                //获取上次处理过程中没有被使用的TempData
                PossiblyLoadTempData();
                try
                {
                    //从路由数据中获取请求的Action的名字
                    string actionName = RouteData.GetRequiredString("action");
                    if (!ActionInvoker.InvokeAction(ControllerContext, actionName))
                    {
                        HandleUnknownAction(actionName);
                    }
                }
                finally
                {
                    //将TempData保存到Session中。等待之后将Session的key【__ControllerTempData】发送到响应流中!
                    PossiblySaveTempData();
                }
            }
        }    

    二、详细分析

      概述中的红色字体部分,也就是我们上一节中遗留的代码段,它实现了Action的执行。现在我们就来通过MVC源代码分析此段代码所涉及的所有部分。

        public abstract class Controller : ControllerBase, IActionFilter, IAuthenticationFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter, IAsyncController, IAsyncManagerContainer
        {
            private IActionInvoker _actionInvoker;
            
            public IActionInvoker ActionInvoker
            {
                get
                {
                    //ActionInvoker的InvokeAction方法就是执行Action的调用。
                    //可见,此处又有一个扩展点,设置自定义的ActionInvoker(即:在激活Controller后,执行该控制器实例的ActionInvoker属性,为属性赋值即可)。
                    if (_actionInvoker == null)
                    {    
                        _actionInvoker = CreateActionInvoker();
                    }
                    return _actionInvoker;
                }
                set { _actionInvoker = value; }
            }
        
            protected override void ExecuteCore()
            {
                PossiblyLoadTempData();
                try
                {
                    //从路由数据中获取请求的Action的名字(路由系统从请求地址中获取)
                    string actionName = RouteData.GetRequiredString("action");
                    //ActionInvoker是Controller类中的一个属性,该属性默认返回的是一个AsyncControllerActionInvoker对象
                    if (!ActionInvoker.InvokeAction(ControllerContext, actionName))
                    {
                        HandleUnknownAction(actionName);
                    }
                }
                finally
                {
                    PossiblySaveTempData();
                }
            }
            
            protected virtual IActionInvoker CreateActionInvoker()
            {//对于Resolver,只能根据类型反射创建实例,接口和抽象类都是返回null,所以下面的代码返回的是一个AsyncControllerActionInvoker对象!(MVC3中是直接返回一个ControllerActionInvoker)
                //AsyncControllerActionInvoker不只是异步的,他还包括了同步。因为他继承自ControllerActionInvoker类,并实现了IAsyncActionInvoker接口。
                //这里就有疑问了,既然接口和抽象类都不能创建实例且返回null,那为什么还以接口为参数呢?
                return Resolver.GetService<IAsyncActionInvoker>() ?? Resolver.GetService<IActionInvoker>() ?? new AsyncControllerActionInvoker();
            }
        }

       上述代码中,红色字体部分中的ActionInvoker是Controller类的一个属性,该属性返回的是私有IActionInvoker类型的字段_actionInvoker的值,如果_actionInvoker不等于null,则返回字段_actionInvoker的值,否则创建一个 AsyncControllerAtionInvoker对象赋值给_actionInvoker字段并返回。所以,在我们没有设置自定义ActionInvoker时,默认这个ActionInvoker是一个AsyncControllerActonInvoker对象。即:执行AsyncControllerActonInvoker对象的InvokeAction方法来完成Action的执行!

    扩展:此处我们可以创建一个自定义的ActionInvoker,然后使用自定义的ActionInvoker来实现Action的执行!
      1、创建自定义一个ActionInvoker(实现IActionInvoker接口的类或者直接继承AsyncControllerActonInvoker类)。
      2、创建好自定义的ActionInvoker之后,就需要将我们的ActionInvoker设置到系统中,就是通过请求的控制器HomeController的基类Controller的这个ActionInvoker属性来进行设置。所以,我们就需要在HomeController被激活时,直接执行该控制器实例的ActionInvoker属性来设置,而控制器的激活是在一个ControllerActivator的Create方法中完成的,ControllerActivator的选择又是ControllerFactory来做的!

            protected void Application_Start()
            {
                AreaRegistration.RegisterAllAreas();
                RegisterGlobalFilters(GlobalFilters.Filters);
                RegisterRoutes(RouteTable.Routes);
                
                ControllerBuilder controllerBulder = ControllerBuilder.Current;
                controllerBulder.SetControllerFactory(new DefaultControllerFactory(new MyControllerActivator()));
            }
    Global.asax
        public class MyControllerActivator:IControllerActivator
        {
            public IController Create(System.Web.Routing.RequestContext requestContext, Type controllerType)
            {
                Controller con = (Controller)Activator.CreateInstance(controllerType);
                con.ActionInvoker = new MyActionInvoker();
                return con;
            }
        }
    MyControllerActivator.cs
    public class MyActionInvoker : AsyncControllerActionInvoker
        {
            public override bool InvokeAction(System.Web.Mvc.ControllerContext controllerContext, string actionName)
            {
                //自己来实现Action的执行
            }
        }
    MyActionInvoker.cs

       上面指出两部分内容,一、在默认情况下的ActionInvoker(AsyncControllerActonInvoker);二、使用自定义ActionInvoker。我们所提到的ActionInvoker都是泛指实现了IActionInvoker接口的类,而上述两个中情况【默认ActionInvoker(AsyncControllerActonInvoker)】和【自定义ActionInvoker】便是实现了IActionInvoker接口,并实现了该接口中唯一的一个方法InvokeAction,而实现的这个方法中包含了对Action执行的所有操作,下面就来看看默认情况下ActionInvoker(AsyncControllerActonInvoker)的InvokeAction方法中是如何定义的!其实,自定义ActionInvoker的InvokeAction方法也是仿照AsyncControllerActonInvoker类来实现的。

        public class AsyncControllerActionInvoker : ControllerActionInvoker, IAsyncActionInvoker
        {
             //调用父类ControllerActionInvoker中的InvokeAction方法
        }    
    AsyncControllerActionInvoker
    public class ControllerActionInvoker : IActionInvoker
    {
        public virtual bool InvokeAction(ControllerContext controllerContext, string actionName)
        {
            //ControllerDescriptor封装描述控制器的信息,如控制器的名称、类型和操作。
            ControllerDescriptor controllerDescriptor = GetControllerDescriptor(controllerContext);
            //FindAction方法:找到要执行的那么Action,并将该Action的相关信息封装在ActionDescriptor中。
            ActionDescriptor actionDescriptor = FindAction(controllerContext, controllerDescriptor, actionName);
            if (actionDescriptor != null)
            {
                 //GetFilters方法:获取应用在Action上的所有过滤器,并封装到一个FilterInfo对象中。
                FilterInfo filterInfo = GetFilters(controllerContext, actionDescriptor);
    
                try
                {
                    //Authorize授权过滤器需要实现IAuthorizationFilter接口,该接口有一个方法:OnAuthorization
                    
       //循环执行应用在Actio上所有Authorize授权过滤器的OnAuthorization方法,定义如果不满足过滤器条件,则需要创建一个ActionResult复制给Result属性
       //AuthorizeAttribute是MVC封装好的一个授权过滤器,从Cookie中获取信息,检查是否授权成功,可参考定义自己的授权管理器
                    AuthorizationContext authContext = InvokeAuthorizationFilters(controllerContext, filterInfo.AuthorizationFilters, actionDescriptor);
                    if (authContext.Result != null)
                    {
                        //没有通过Authorize授权过滤器,直接根据自定义的ActionResult进行View的呈现!
    //View的呈现(下一节介绍)
    InvokeActionResult(controllerContext, authContext.Result); } else { //ValidateRequest,该值指示是否为此请求启用请求验证 //是否对请求必须验证,默认为true,该属性定义在ControllerBase类中 if (controllerContext.Controller.ValidateRequest) { //ValidateRequest应该是检查XSS威胁之类的,在模型绑定请求中获取值前进行处理。 ValidateRequest(controllerContext); } //获取Action方法参数的值(模型绑定) IDictionary<string, object> parameters = GetParameterValues(controllerContext, actionDescriptor); //执行【方法过滤器】(实现IActionFilter接口)并执行Action内代码 ActionExecutedContext postActionContext = InvokeActionMethodWithFilters(controllerContext, filterInfo.ActionFilters, actionDescriptor, parameters); //执行【结果过滤器】(实现IResultFilter接口),再做View的呈现。 InvokeActionResultWithFilters(controllerContext, filterInfo.ResultFilters, postActionContext.Result); } } catch (ThreadAbortException) { throw; } catch (Exception ex) { //执行异常过滤器 ExceptionContext exceptionContext = InvokeExceptionFilters(controllerContext, filterInfo.ExceptionFilters, ex); if (!exceptionContext.ExceptionHandled) { throw; }
    //根据异常过滤器中定义的ActionResult进行View的呈现 InvokeActionResult(controllerContext, exceptionContext.Result); }
    return true; } // notify controller that no method matched return false; } }

      上述代码中已添加了详细的注释,大致流程为:首先,根据【控制器信息】和【Action的Name】从被请求控制器的众多Action中找到要访问的Action,然后再执行应用在Action上的过滤器,最后根据ActionResult再进行View的呈现(下一节介绍)。

     扩展:此处ControllerActionInvoker是MVC4中的,MVC5中新添加Authorizetion过滤器,并且这个过滤器的执行模式和Authorizetion过滤器是一样。对于Authentic过滤器,它需要实现IAuthenticationFilter接口,该接口中有两个方法:OnAuthentication和OnAuthenticationChallenge,执行顺序为:【Authentic过滤器的OnAuthentication方法】—>【Action过滤器的执行】—>【Action内代码的执行】—>【Authentic过滤器的OnAuthenticationChallenge方法】—>【Result过滤器的执行】—>【View的呈现】,所以就目前看来,通过这个过滤器也就可以在Action执行前且View呈现之前进行一些操作,从而可增强扩展性!

    public class ControllerActionInvoker : IActionInvoker
    {
          public virtual bool InvokeAction(ControllerContext controllerContext, string actionName)
            {
                //ControllerDescriptor封装描述控制器的信息,如控制器的名称、类型和操作。
                ControllerDescriptor controllerDescriptor = GetControllerDescriptor(controllerContext);
                //FindAction方法:找到要执行的那么Action,并将其封装在ActionDescriptor中。
                //ActionDescriptor提供有关操作方法的信息,如操作方法的名称、控制器、参数、特性和筛选器。
                ActionDescriptor actionDescriptor = FindAction(controllerContext, controllerDescriptor, actionName);
                if (actionDescriptor != null)
                {
                    //GetFilters方法:获取应用在Action上的所有过滤器,并封装到一个FilterInfo对象中。
                    FilterInfo filterInfo = GetFilters(controllerContext, actionDescriptor);
                    try
                    {
                    //注意:Authentic过滤器需要实现IAuthenticationFilter接口,此接口有两个方法:OnAuthentication和OnAuthenticationChallenge
    
    //循环执行Action上应用的所有Authentic过滤器的OnAuthentication方法,判定未通过验证,则创建ActionResult对象给Result属性(以此来进行View的呈现)。
                        AuthenticationContext authenticationContext = InvokeAuthenticationFilters(controllerContext, filterInfo.AuthenticationFilters, actionDescriptor);
                //未通过Authentic过滤器的Onauthentication方法
                        if (authenticationContext.Result != null)
                        {     
                  //循环执行所有Authentic过滤器的OnAuthenticationChallenge方法(可以是任何操作,例:对ActionResult进一步处理等)
                            AuthenticationChallengeContext challengeContext = InvokeAuthenticationFiltersChallenge(controllerContext,filterInfo.AuthenticationFilters,AcionDescriptor,authenticationContext.Result);
                            //根据自定义的ActionResult进行View的呈现(没有通过Authentic过滤器,不需再继续执行,直接返回结果)
                            InvokeActionResult(controllerContext, challengeContext.Result ?? authenticationContext.Result);
    
                        }
                        //没有设置认证器或者认证成功
                        else
                        {
                            //Authorize授权过滤器需要实现IAuthorizationFilter接口,该接口有一个方法:OnAuthorization
    //循环执行应用在Actio上所有Authorize授权过滤器的OnAuthorization方法(AuthorizeAttribute是MVC封装好的一个授权过滤器,从Cookie中获取信息,检查是否授权成功,可参考定义自己的授权管理器)
                            AuthorizationContext authorizationContext = InvokeAuthorizationFilters(controllerContext, filterInfo.AuthorizationFilters, actionDescriptor);
                            if (authorizationContext.Result != null)
                            {
                                //没有通过Authorization过滤器,即:OnAuthorization方法中不符合条件
                                //循环执行Authentica过滤器的OnAuthenticationChallenge方法(可以是任何操作,例:对ActionResult进一步处理)!
                                AuthenticationChallengeContext challengeContext = InvokeAuthenticationFiltersChallenge(controllerContext, filterInfo.AuthenticationFilters, actionDescriptor,authorizationContext.Result);
                                //View的呈现
                                InvokeActionResult(controllerContext, challengeContext.Result ?? authorizationContext.Result);
                            }
                            //未设置Authorize过滤器或授权成功
                            else
                            {
                                //ValidateRequest,该值指示是否为此请求启用请求验证
                                //是否对请求必须验证,默认为true,该属性定义在ControllerBase类中
                                if (controllerContext.Controller.ValidateRequest)
                                {
                                    //ValidateRequest应该是检查XSS威胁之类的,在模型绑定请求中获取值前进行处理。
                                    ValidateRequest(controllerContext);
                                }
                                //获取Action参数的值(模型绑定)
                                IDictionary<string, object> parameters = GetParameterValues(controllerContext, actionDescriptor);
                                
                                //执行【方法过滤器】(实现IActionFilter接口)并执行Action内代码
                                ActionExecutedContext postActionContext = InvokeActionMethodWithFilters(controllerContext, filterInfo.ActionFilters, actionDescriptor, parameters);
                                
                                //再一次循环执行认证过滤器的OnAuthenticationChallenge方法(可以是任何操作,例:对ActionResult进一步处理)!
                                AuthenticationChallengeContext challengeContext = InvokeAuthenticationFiltersChallenge(controllerContext, filterInfo.AuthenticationFilters, actionDescriptor,postActionContext.Result);
                                
                                //执行【结果过滤器】(实现IResultFilter接口),再做View的呈现。
                                InvokeActionResultWithFilters(controllerContext, filterInfo.ResultFilters,challengeContext.Result ?? postActionContext.Result);
                            }
                        }
                    }
                    catch (ThreadAbortException)
                    {
                        throw;
                    }
                    catch (Exception ex)
                    {
                        ExceptionContext exceptionContext = InvokeExceptionFilters(controllerContext, filterInfo.ExceptionFilters, ex);
                        if (!exceptionContext.ExceptionHandled)
                        {
                            throw;
                        }
                        InvokeActionResult(controllerContext, exceptionContext.Result);
                    }
    
                    return true;
                }
                return false;
            }
    }
    MVC5:ControllerActionInvoker

    InvokeAction方法解析

    1、ActionDescriptor actionDescriptor = FindAction(controllerContext, controllerDescriptor, actionName);

      在控制器HomeController对象的所有方法中,找到当前请求的Action(控制器对象的一个方法)。

    public class ControllerActionInvoker : IActionInvoker
    {
        private static readonly ControllerDescriptorCache _staticDescriptorCache = new ControllerDescriptorCache();
        private ControllerDescriptorCache _instanceDescriptorCache;
        internal ControllerDescriptorCache DescriptorCache
        {
            get
            {
                if (_instanceDescriptorCache == null)
                {
                    _instanceDescriptorCache = _staticDescriptorCache;
                }
                return _instanceDescriptorCache;
            }
            set { _instanceDescriptorCache = value; }
        }
        
        
        public virtual bool InvokeAction(ControllerContext controllerContext, string actionName)
        {
            //ControllerDescriptor封装描述控制器的信息,如控制器的名称、类型和操作。
            //此处是controllerDescriptor对象是ControllerDescriptor的派生类ReflectedControllerDescriptor的对象。
            ControllerDescriptor controllerDescriptor = GetControllerDescriptor(controllerContext);
            
            //FindAction方法:找到要执行的那么Action,并将该Action的相关信息封装在ActionDescriptor中。
            ActionDescriptor actionDescriptor = FindAction(controllerContext, controllerDescriptor, actionName);
            //省略其他代码
        }
    
        
        protected virtual ControllerDescriptor GetControllerDescriptor(ControllerContext controllerContext)
        {
            //获取Controller的类型
            Type controllerType = controllerContext.Controller.GetType();
            //DescriptorCache是本类的属性,是一个ControllerDescriptorCache实例。
            //GetDescriptor方法的本质是根据controllerType去缓存中获取,如果没有的话,就执行委托(第二个参数)去创建,并做为返回值。再添加到缓存字典表中,以便下次利用。
            //如下,没有缓存的情况下,就执行委托创建一个ReflectedControllerDescriptor对象。即:可以看出所有的ControllerDescriptor都是一个ReflectedControllerDescriptor。
            ControllerDescriptor controllerDescriptor = DescriptorCache.GetDescriptor(controllerType, () => new ReflectedControllerDescriptor(controllerType));
            //返回这个继承自ControllerDescriptor的ReflectedControllerDescriptor对象。
            return controllerDescriptor;
        }
            
        protected virtual ActionDescriptor FindAction(ControllerContext controllerContext, ControllerDescriptor controllerDescriptor, string actionName)
        {
            //执行参数controllerDescriptor(ReflectedControllerDescriptor对象)的FindAction方法
            ActionDescriptor actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);
            return actionDescriptor;
        }
    }
    ControllerActionInvoker
    public class ReflectedControllerDescriptor : ControllerDescriptor
    {
        private readonly Type _controllerType;
        private readonly ActionMethodSelector _selector;
        //构造函数
        public ReflectedControllerDescriptor(Type controllerType)
        {
            if (controllerType == null)
            {
                throw new ArgumentNullException("controllerType");
            }
    
            _controllerType = controllerType;
            _selector = new ActionMethodSelector(_controllerType);
        }
        public override ActionDescriptor FindAction(ControllerContext controllerContext, string actionName)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }
            if (String.IsNullOrEmpty(actionName))
            {
                throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");
            }
            //_selector.FindActionMethod方法,先根据类型找到他的所有方法,然后根据方法名字再去匹配。
            //_selector是在该类的构造函数中创建的ActionMethodSelector对象。
            //获取指定的Action
            MethodInfo matched = _selector.FindActionMethod(controllerContext, actionName);
            if (matched == null)
            {
                return null;
            }
            //将找到的那个Action封装到一个ReflectedActionDescriptor对象(即:ActionDescriptor的派生类)中。
            return new ReflectedActionDescriptor(matched, actionName, this);
        }
    }
    ReflectedControllerDescriptor
    internal sealed class ActionMethodSelector
    {
        //构造函数
        public ActionMethodSelector(Type controllerType)
        {
            ControllerType = controllerType;
            //获取控制HomeController的所有方法
            PopulateLookupTables();
        }
    
        public Type ControllerType { get; private set; }
    
        public MethodInfo[] AliasedMethods { get; private set; }
    
        public ILookup<string, MethodInfo> NonAliasedMethods { get; private set; }
    
        private AmbiguousMatchException CreateAmbiguousMatchException(List<MethodInfo> ambiguousMethods, string actionName)
        {
            StringBuilder exceptionMessageBuilder = new StringBuilder();
            foreach (MethodInfo methodInfo in ambiguousMethods)
            {
                string controllerAction = Convert.ToString(methodInfo, CultureInfo.CurrentCulture);
                string controllerType = methodInfo.DeclaringType.FullName;
                exceptionMessageBuilder.AppendLine();
                exceptionMessageBuilder.AppendFormat(CultureInfo.CurrentCulture, MvcResources.ActionMethodSelector_AmbiguousMatchType, controllerAction, controllerType);
            }
            string message = String.Format(CultureInfo.CurrentCulture, MvcResources.ActionMethodSelector_AmbiguousMatch,
                                           actionName, ControllerType.Name, exceptionMessageBuilder);
            return new AmbiguousMatchException(message);
        }
    
        public MethodInfo FindActionMethod(ControllerContext controllerContext, string actionName)
        {
            //对应用了ActionNameSelectorAttribute特性的Action方法集合处理,获取方法名字是actionName的所有Action方法。
            List<MethodInfo> methodsMatchingName = GetMatchingAliasedMethods(controllerContext, actionName);
            //对没有应用ActionNameSelectorAttribute特性的Action方法集合处理,获取方法名字是actionName的所有方法,并添加集合尾部。
            methodsMatchingName.AddRange(NonAliasedMethods[actionName]);
            //目前为止,methodsMatchingName集合中保存的是HomeController中Action方法的名字等于actionName的方法
            
            //再做一次筛选和处理,处理Action方法上应用了NonAction、AcceptVerbs、HttpGet、HttpPost、HttpDelete、HttpPut特性情况
            List<MethodInfo> finalMethods = RunSelectionFilters(controllerContext, methodsMatchingName);
            
            //只有符合条件的Action方法仅有一个时,才返回。(这就是为何,当我们定义两个方法名相同且参数不同且又都应用HttpGet特性时,会报错)
            switch (finalMethods.Count)
            {
                case 0:
                    return null;
    
                case 1:
                    return finalMethods[0];
    
                default:
                    throw CreateAmbiguousMatchException(finalMethods, actionName);
            }
        }
    
        internal List<MethodInfo> GetMatchingAliasedMethods(ControllerContext controllerContext, string actionName)
        {
            //有一个缓存,保存Action方法的ActionName特性。
            //ReflectedAttributeCache.GetActionNameSelectorAttributes(methodInfo)根据methodInfo去缓存表中找,如果没有的话,就利用methodInfo的GetCustomAttributes方法去获取ActionName属性(一个ActionNameAttribute对象)。
            
            //遍历所有应用了ActionName特性的方法,并筛选得到特性的名字=当前请求的action名称
            //ActionNameAttribute的IsValidName方法,就是根据String.Equals(actionName, Name, StringComparison.OrdinalIgnoreCase)判断的
            var methods = from methodInfo in AliasedMethods
                          let attrs = ReflectedAttributeCache.GetActionNameSelectorAttributes(methodInfo)
                          where attrs.All(attr => attr.IsValidName(controllerContext, actionName, methodInfo))
                          select methodInfo;
            return methods.ToList();
        }
    
        private static bool IsMethodDecoratedWithAliasingAttribute(MethodInfo methodInfo)
        {
            //在派生类中重写时,指示是否 attributeType 的一个或多个实例应用于此成员。
            //第二个参数:指定是否搜索该ActionNameSelectorAttribute的继承链以查找这些特性。
            //返回如果 (ActionNameSelectorAttribute) 的一个或多个实例应用于此成员(包括特性基类),则为 true;否则为 false。
            //也就是该Action上应用了ActionName特性来实现一个别名
            return methodInfo.IsDefined(typeof(ActionNameSelectorAttribute), true /* inherit */);
        }
        
        private static bool IsValidActionMethod(MethodInfo methodInfo)
        {
            //获取定义在自定义的Controller(HomeController)中的方法。过滤掉Controller类中的方法和Controller类的基类中的方法。
            //IsSpecialName表示方法是否具有特殊名称。(如果是HomeController中自己写得方法,则返回false,如果是Controller类或其基类中的方法时,返回true)
            //GetBaseDefinition方法得到该methodInfo被第一次定义的方法,(我们写的Action都是第一次定义在HomeControlelr中,如果在自定格的HomeController中重写基类中的方法,则这个GetBaseDefinition方法得到的就是第一次被创建的那个方法-可能是接口中定义的方法,)
            //DeclaringType属性获取该方法所在的类
            //IsAssignableFrom(typeof(Controller)方法,检查是否该类型可以从Controller的实例分配。
            //如果methodInfo.GetBaseDefinition().DeclaringType得到的 type类型 是Controller类或Controller的基类或Controller实现的接口,则返回true
            return !(methodInfo.IsSpecialName ||
                     methodInfo.GetBaseDefinition().DeclaringType.IsAssignableFrom(typeof(Controller)));
        }
    
        private void PopulateLookupTables()
        {
            //反射得到控制器HomeController的所有方法,包括继承自基类的所有方法
            MethodInfo[] allMethods = ControllerType.GetMethods(BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public);
            //筛选,获取在控制器HomeController中创建的Action方法(依据:循环所有方法,方法是否可利用Controller类实例得到)
            MethodInfo[] actionMethods = Array.FindAll(allMethods, IsValidActionMethod);
            //筛选,获取HomeConroller中应用了ActionNameSelectorAttribute特性的Action方法。(ActionName特性的目的就是为Action设置一个别名)
            AliasedMethods = Array.FindAll(actionMethods, IsMethodDecoratedWithAliasingAttribute);
            //筛选,获取HomeController中除去应用了ActionName特性的方法之外的所有方法。(只要应用了ActionName特性的方法都不在这个集合内)
            NonAliasedMethods = actionMethods.Except(AliasedMethods).ToLookup(method => method.Name, StringComparer.OrdinalIgnoreCase);
        }
    
        private static List<MethodInfo> RunSelectionFilters(ControllerContext controllerContext, List<MethodInfo> methodInfos)
        {
            
            //局部变量,保存应用了NonAction、AcceptVerbs、HttpGet、HttpPost、HttpDelete、HttpPut特性的Action方法(也可以叫做选择特性)
            List<MethodInfo> matchesWithSelectionAttributes = new List<MethodInfo>();
            ////局部变量,保存应用了NonAction、AcceptVerbs、HttpGet、HttpPost、HttpDelete、HttpPut特性的Action方法
            List<MethodInfo> matchesWithoutSelectionAttributes = new List<MethodInfo>();
    
            
            foreach (MethodInfo methodInfo in methodInfos)
            {
                //从缓存中根据methodInfo获取【选择特性】,如果缓存中没有的话,就主动去获取方法的所有特性中【选择特性】,并添加到缓存表中。
                //ActionName特性类继承自ActionNameSelectorAttribute类
                //NonAction、AcceptVerbs、HttpGet、HttpPost、HttpDelete、HttpPut特性类都继承自ActionMethodSelectorAttribute类。
                ICollection<ActionMethodSelectorAttribute> attrs = ReflectedAttributeCache.GetActionMethodSelectorAttributes(methodInfo);
                if (attrs.Count == 0)
                {
                    //如果Action方法上没有应用【选择特性】
                    matchesWithoutSelectionAttributes.Add(methodInfo);
                }
                //检查方法上定义的选择特性 是否 和客户端使用的 HTTP 数据传输方法一致
                //调用应用在方法上的特性的IsValidForRequest方法。(只有那6个继承自ActionMethodSelectorAttribute类的特性,因为IsValidForRequest最开始是在此类中定义抽象方法)
                //对于NonAction特性,IsValidForRequest方法直接返回false
                //All方法:所有元素全部通过则返回true,否则返回false
                else if (attrs.All(attr => attr.IsValidForRequest(controllerContext, methodInfo)))
                {
                    //特性通过验证,也就是和客户端使用的http数据传输方法一直
                    matchesWithSelectionAttributes.Add(methodInfo);
                }
            }
            //如果Action方法上存在应用了【选择特性】且又通过了验证,则返回应用了【选择特性】的Action方法集合,
            //当【选择特性】都未通过验证时,则返回没有应用【选择特性】的Action方法集合(即:Action上没有HttpGet、HttpPost等特性的方法)
            //此处说明了Action方法执行的优先级:应用了正确的HttpGet、HttpPost等特性的Action方法优先于未应用HttpGet、HttpPost等特性的Action方法
            return (matchesWithSelectionAttributes.Count > 0) ? matchesWithSelectionAttributes : matchesWithoutSelectionAttributes;
        }
    }
    
    ActionMethodSelector
    ActionMethodSelector

      上述代码中,其实就是通过HomeController实例利用反射获取到所有的方法(包括父类中的方法),然后就是进行筛选,首先通过判断得到的方法是否是Controller类实例的方法,从而将HomeController父类中的方法过滤掉;之后再根据方法的名字来做判断,从而将方法名字不是请求的actionName的方法过滤掉;再之后判断应用在Action方法上的特性是否和客户端使用的 HTTP 数据传输方法一致,将不符合Http数据传输方法的Action过滤掉;再再之后,当符合条件的Action方法只有一个时,就将该Action方法返回,即:得到了指定的Action。最后将得到的Action方法封装到一个继承自ActionDescriptor类的ReflectedActionDescriptor对象中。

    扩展:由上面介绍可知,其实对Action方法的查找和筛选都是在ActionMethodSelector中进行的,MVC5中的ActionMethodSelector虽然大体上流程是和MVC4相同的,但是具体实现上还是有点差异,有兴趣的可以看一下。

    internal sealed class ActionMethodSelector
    {
        public ActionMethodSelector(Type controllerType)
        {
            ControllerType = controllerType;
            PopulateLookupTables();
        }
    
        public Type ControllerType { get; private set; }
    
        public MethodInfo[] AliasedMethods { get; private set; }
    
        public ILookup<string, MethodInfo> NonAliasedMethods { get; private set; }
    
        private AmbiguousMatchException CreateAmbiguousMatchException(List<MethodInfo> ambiguousMethods, string actionName)
        {
            StringBuilder exceptionMessageBuilder = new StringBuilder();
            foreach (MethodInfo methodInfo in ambiguousMethods)
            {
                string controllerAction = Convert.ToString(methodInfo, CultureInfo.CurrentCulture);
                string controllerType = methodInfo.DeclaringType.FullName;
                exceptionMessageBuilder.AppendLine();
                exceptionMessageBuilder.AppendFormat(CultureInfo.CurrentCulture, MvcResources.ActionMethodSelector_AmbiguousMatchType, controllerAction, controllerType);
            }
            string message = String.Format(CultureInfo.CurrentCulture, MvcResources.ActionMethodSelector_AmbiguousMatch,
                                           actionName, ControllerType.Name, exceptionMessageBuilder);
            return new AmbiguousMatchException(message);
        }
    
        public MethodInfo FindActionMethod(ControllerContext controllerContext, string actionName)
        {
            //断言,成功时什么也不做
            Contract.Assert(controllerContext != null);
    
            if (controllerContext.RouteData != null)
            {
                //尼玛,RouteData的这个GetTargetActionMethod方法在那里呀?
                MethodInfo target = controllerContext.RouteData.GetTargetActionMethod();
                if (target != null)
                {
                    // short circuit the selection process if a direct route was matched.
                    return target;
                }
            }
            //得到所有满足要求的Action,(包括应用了ActionName特性和原Action的名字和请求的Action相同的)
            List<MethodInfo> finalMethods = FindActionMethods(controllerContext, actionName, AliasedMethods, NonAliasedMethods);
            //只有当HomeController中的Action有且只有一个满足请求的,才返回。所以,Controller中不允许Action重复(参数不同可以)
            switch (finalMethods.Count)
            {
                case 0:
                    return null;
                //只有里面有一个合适的Action时才正确返回。
                case 1:
                    return finalMethods[0];
    
                default:
                    throw CreateAmbiguousMatchException(finalMethods, actionName);
            }  
        }
        
    
        internal static List<MethodInfo> FindActionMethods(ControllerContext controllerContext, string actionName, MethodInfo[] aliasedMethods, ILookup<string, MethodInfo> nonAliasedMethods)
        {
            List<MethodInfo> matches = new List<MethodInfo>();
    
            //遍历所有应用了ActionName属性的所有方法。
            for (int i = 0; i < aliasedMethods.Length; i++)
            {
                MethodInfo method = aliasedMethods[i];
                //IsMatchingAliasedMethod方法获取Action上应用的ActionName属性的值,并将该值和请求的Action相比较,如果一致则直接添加到列表。
                if (IsMatchingAliasedMethod(method, controllerContext, actionName))
                {
                    matches.Add(method);
                }
            }
            matches.AddRange(nonAliasedMethods[actionName]);//将所有方法再添加到集合matches的末尾(最后获取Action的时候,是获取索引的第一个。这就是为什么ActionName特性优先于原Action的名字)
           //到现在为止,集合matches中剩下只有和请求的Action相同的 方法(包含Action、应用了ActionName才符合的Action、普通方法)了
           RunSelectionFilters(controllerContext, matches);//筛选Controller中定义的所以方法,是否为Aciton,如果不是,则移除
            return matches;
        }
    
        
        private static bool IsMatchingAliasedMethod(MethodInfo method, ControllerContext controllerContext, string actionName)
        {
    
            //又一个缓存,如果缓存表中没有的话,缓存着Action的ActionName特性(每个Action只能使用一个ActionName属性,这里为什么是个集合呢?不明白)。
            //ReflectedAttributeCache.GetActionNameSelectorAttributes(method)根据method去缓存表中找,如果没有的话,就利用method的GetCustomAttributes方法去获取ActionName属性(一个ActionNameAttribute对象)。
            
            //获取方法上应用了 继承了ActionNameSelectorAttribute 类的特性!
            //只有ActionNameAttribute继承自ActionNameSelectorAttribute类
            ReadOnlyCollection<ActionNameSelectorAttribute> attributes = ReflectedAttributeCache.GetActionNameSelectorAttributes(method);
            // Caching count is faster for ReadOnlyCollection
            int attributeCount = attributes.Count;
            //遍历每个ActionName属性,即ActionNameAttribute对象(在Action上应用该特性时就实例化了ActionNameAttribute,且构造函数的参数就是:Action上定义的Action的别名)。
            for (int i = 0; i < attributeCount; i++)
            {
                //判断特性中设置别名和请求的Action是否一致。
                //ActionNameSelectorAttribute是抽象类,ActionNameAttribute实现IsValidName方法,就是根据名字的String.Equals(actionName, Name, StringComparison.OrdinalIgnoreCase);
                if (!attributes[i].IsValidName(controllerContext, actionName, method))
                {
                    return false;
                }
            }
            return true;
        }
    
        private static bool IsValidMethodSelector(ReadOnlyCollection<ActionMethodSelectorAttribute> attributes, ControllerContext controllerContext, MethodInfo method)
        {
            int attributeCount = attributes.Count;
            Contract.Assert(attributeCount > 0);
            for (int i = 0; i < attributeCount; i++)
            {
                //调用应用在方法上的特性的IsValidForRequest方法。(只有那6个继承自ActionMethodSelectorAttribute类的特性,因为IsValidForRequest最开始是在此类中定义抽象方法)
                //NonAction特性,IsValidForRequest方法直接返回false,括号内就是true,整个方法返回 false
                //AcceptVerbs特性,应用时,AcceptVerbsAttribute构造函数传入的HttpVerbs类型(枚举,有Get、Post、Put、Delete、Head)的参数,并在构造函数内以此参数为参数又创建了一个HttpVerbsValidator实例,HttpVerbsValidator的构造函数中,将httpverbs参数存入到私有的集合变量中,而AcceptVerbs特性的IsValidForRequest方法,内部本质上执行的是HttpVerbsValidator实例的IsValidForRequest方法,这个方法就是检查 保存HttpVerbs的私有变量集合中 是否含有发来的请求的HttpVerbs
                    //其实,AcceptVerbs特性和这些HttpGet、HttpPost、HttpPut、HttpDelete一样,只不过其多了一个Head,这个是什么呢?
                //HttpGet特性,HttpGetAttribute继承自HttpVerbAttribut。执行HttpGetAttribute构造函数时,执行HttpVerbAttribut构造函数并直接给一个参数(HttpVerbs.HttpGet),其构造函数内部也是创建一个参数为HttpGet的HttpVerbsValidator实例,之后同上...
                //HttpPost特性,和HttpGet一样,只不过传入的HttpVerbAttribut构造函数的参数为HttpVerbs.Post
                //HttpDelete特性,同上
                //HttpPut特性,同上
                
                //其实就是 检查方法上定义的特性 是否 和客户端使用的 HTTP 数据传输方法一致。
                //如果一致,则返回 true,括号内为false,整个方法返回true
                //如果不一致,则返回 false,括号内为true,整个方法返回false
                if (!attributes[i].IsValidForRequest(controllerContext, method))
                {
                    return false;
                }
            }
            return true;
        }
        
        private static bool IsMethodDecoratedWithAliasingAttribute(MethodInfo methodInfo)
        {
            //在派生类中重写时,指示是否 attributeType 的一个或多个实例应用于此成员。
            //第二个参数:指定是否搜索该ActionNameSelectorAttribute的继承链以查找这些特性。
            //返回如果 (ActionNameSelectorAttribute) 的一个或多个实例应用于此成员(包括特性基类),则为 true;否则为 false。
            //也就是该Action上应用了ActionName特性来实现一个别名
            return methodInfo.IsDefined(typeof(ActionNameSelectorAttribute), true /* inherit */);
        }
        
        //获取定义在自定义的Controller(HomeController)中的方法。过滤掉Controller类中的方法和Controller类的基类中的方法。
        private static bool IsValidActionMethod(MethodInfo methodInfo)
        {
            //IsSpecialName表示方法是否具有特殊名称。(如果是HomeController中自己写得方法,则返回false,如果是Controller类或其基类中的方法时,返回true)
            //GetBaseDefinition方法得到该methodInfo被第一次定义的方法,(我们写的Action都是第一次定义在HomeControlelr中,如果在自定格的HomeController中重写基类中的方法,则这个GetBaseDefinition方法得到的就是第一次被创建的那个方法-可能是接口中定义的方法,)
            //DeclaringType属性获取该方法所在的类
            //IsAssignableFrom(typeof(Controller)方法,检查是否该类型可以从Controller的实例分配。
            //如果methodInfo.GetBaseDefinition().DeclaringType得到的 type类型 是Controller类或Controller的基类或Controller实现的接口,则返回true
            return !(methodInfo.IsSpecialName ||
                     methodInfo.GetBaseDefinition().DeclaringType.IsAssignableFrom(typeof(Controller)));
        }
    
        private void PopulateLookupTables()
        {
            //根据类型反射所有方法,包括继承自基类的所有方法
            MethodInfo[] allMethods = ControllerType.GetMethods(BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public);
            
            //筛选,得到自定义在Controller中添加的方法。
            //Array的FindAll方法,第二个参数是一个委托
            MethodInfo[] actionMethods = Array.FindAll(allMethods, IsValidActionMethod); //集合、筛选逻辑(委托)
            
            //筛选,获取应用了ActionNameSelectorAttribute特性的Action。ActionName特性的目的就是为Action设置一个别名
            AliasedMethods = Array.FindAll(actionMethods, IsMethodDecoratedWithAliasingAttribute);
            
            //错误=筛选,获取所有的方法(不含别名,但是有有别名的Action的原名在内),并且根据方法名进行分组,且方法名不区分大小写。(Action名字相同,参数不同则分在一组)
            //正确=上述理解错误,这里获取的是除去了应用了ActionName特性的方法之外的所有方法。(只要应用了ActionName特性的方法都不在这个集合内)
            NonAliasedMethods = actionMethods.Except(AliasedMethods).ToLookup(method => method.Name, StringComparer.OrdinalIgnoreCase);
        }
        
        //最后的筛选
        private static void RunSelectionFilters(ControllerContext controllerContext, List<MethodInfo> methodInfos)
        {
            //到现在为止,集合methodInfos中剩下只有和请求的Action相同的 方法(包含:原名符合的Action、应用了ActionName才符合的Action、普通方法)了
            bool hasValidSelectionAttributes = false;
            //遍历目前符合条件的所有方法
            for (int i = methodInfos.Count - 1; i >= 0; i--)
            {
                MethodInfo methodInfo = methodInfos[i];
                //获取方法集合中,是Action的方法。
    
                //如果应用了NonAction特性,attrs.Count=1;
                //如果应用了HttpPut特性,attrs.Count=1
                //如果应用了HttpDelete特性,attrs.Count=1
                //如果应用了HttpPost特性,attrs.Count=1
                //如果应用了HttpGet特性,attrs.Count=1
                //如果应用了ccetpVerbs特性,attrs.Count=1A
                //以上的特性如果共同应用在方法上,那么attrs.Count=2.3.4.5.6.7.8.9...
                
                //如果是应用了ActionName特性才符合的Action,这里attrs.Count=0。ActionName继承自ActionNameSelectorAttribute==== 我们称之为 名称特性
                //只要没有应用以上特性,无论是定义的Action还是普通方法 均为:atters.count=0,即:符合要求
                
                //其实就是获取方法上应用的所有特性(特性是ActionMethodSelectorAttribute类的派生类,我们称之为方法特性)。
                //也只有以上6个特性继承自ActionMethodSelectorAttribute类。(只有ActionNameAttribute继承自ActionNameSelectorAttribute类)
                ReadOnlyCollection<ActionMethodSelectorAttribute> attrs = ReflectedAttributeCache.GetActionMethodSelectorAttributesCollection(methodInfo);
                //如果该方法上没有应用方法特性
                if (attrs.Count == 0)
                {
                    // case 1: this method does not have a MethodSelectionAttribute
                    //第一次进来时hasValidSelectionAttributes是false,不做操作,故:没有应用NonAction特性的方法就通过了。
                    if (hasValidSelectionAttributes)
                    {
                        // if there is already method with a valid selection attribute, remove method without one
                        methodInfos.RemoveAt(i);
                    }
                }
                //其实就是 检查方法上定义的特性 是否 和客户端使用的 HTTP 数据传输方法一致。
                //如果一致,则返回true
                //如果不一致,则返回false
                else if (IsValidMethodSelector(attrs, controllerContext, methodInfo))
                {
                    //客户端使用的Http数据传输方式和 定义在Action上的特性设置的一致
                    if (!hasValidSelectionAttributes) //第一次时,true 可进入
                    {
                        //符合条件的Action集合中,
                        //只有第一个进入到这里(应用了方法特性且Http传输方式一致)或不符合的已删除当前索引位于顶层,不符合i + 1 < methodInfos.Count
                        //当前索引不位于集合的顶层(即:已经有符合条件的Action存在),
                        if (i + 1 < methodInfos.Count)
                        {
                            //猜测:是将当前索引上层的所有项都移除(即已经筛选出的符合的Action都移除--没有应用特性的)。
                            //猜想正确,此RemoveFrom是MVC写的一个List<T>的扩展方法,MVC源码的目录 .srcCommon 的CollectionExtensions.cs类中
                            methodInfos.RemoveFrom(i + 1);
                        }
                        //将这个标识设置为true。
                        //当下次循环的Action没有应用ActionMethodSelectorAttribute特性时,移除。=======所以,应用了ActionMethodSelectorAttribute特性的Action比没有应用的优先级要高!(例:定义两个Action,其中一个应用HttpGet,应用了的优先级高)
                        //当下次循环的Action应用了ActionMethodSelectorAttribute特性,并且和客户端使用的传输方法一致。直接通过...   这就是当定义两个Action,都设置为HttpGet,就会出现:【对控制器类型“HomeController”的操作“Index”的当前请求在下列操作方法之间不明确:】
                        hasValidSelectionAttributes = true;
                    }
                }
                //应用数据传输方法特性,但是请求和Action上设置的不一致。移除该Action
                else
                {
                    methodInfos.RemoveAt(i);
                }
            }
        }
    }
    MVC5:ActionMethodSelector

     2、FilterInfo filterInfo = GetFilters(controllerContext, actionDescriptor);

      获取应用在Action方法上的所有过滤器,并将封装到一个FilterInfo对象中。这些过滤器有:ActionFilter、AuthorizationFilter、ExceptionFilter、ResultFilter,另外在MVC5中又新添加了一个AuthenticationFilter过滤器。

    public class ControllerActionInvoker : IActionInvoker
    {
        private static readonly ControllerDescriptorCache _staticDescriptorCache = new ControllerDescriptorCache();
        //FilterProviders.Providers.GetFilters是有两个参数的方法,该方法就是去获取并筛选过滤器
        //IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
        private Func<ControllerContext, ActionDescriptor, IEnumerable<Filter>> _getFiltersThunk = FilterProviders.Providers.GetFilters;
        public ControllerActionInvoker()
        {
        }
        protected virtual FilterInfo GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
        {
            return new FilterInfo(_getFiltersThunk(controllerContext, actionDescriptor));
        }
        
        public virtual bool InvokeAction(ControllerContext controllerContext, string actionName)
        {
            ControllerDescriptor controllerDescriptor = GetControllerDescriptor(controllerContext);
            ActionDescriptor actionDescriptor = FindAction(controllerContext, controllerDescriptor, actionName);
            if (actionDescriptor != null)
            {
                //过去应用在Action方法上的所有过滤器
                FilterInfo filterInfo = GetFilters(controllerContext, actionDescriptor);
                //省略其他代码
            }
    
        }
    }
    ControllerActionInvoker
    public static class FilterProviders
    {
        //静态构造函数
        static FilterProviders()
        {
            //FilterProviderCollection继承自Collection<IFilterProvider>类
            //实例化FilterProviderCollection时,会先实例化其父类。Collection<IFilterProvider>实例化时,会创建一个List<IFilterProvider>对象items作为私有变量。
            Providers = new FilterProviderCollection();
            //Add方法定义在Collection<IFilterProvider>中,就是将参数添加到私有变量 items 中。
            Providers.Add(GlobalFilters.Filters); //GlobalFilters.Filters属性的值其实就是 new GlobalFilterCollection();
            Providers.Add(new FilterAttributeFilterProvider());
            Providers.Add(new ControllerInstanceFilterProvider());
        }
    
        public static FilterProviderCollection Providers { get; private set; }
    }
    FilterProviders
    public class FilterProviderCollection : Collection<IFilterProvider>
    {
        private static FilterComparer _filterComparer = new FilterComparer();
        private IResolver<IEnumerable<IFilterProvider>> _serviceResolver;
    
        public FilterProviderCollection()
        {
            //Items是父类Collection<IFilterProvider>中的一个属性,该属性得到已添加到该集合中的所有【过滤器】的【提供器】
            //将【过滤器】的【提供器】集合和一个空的Objcect类型集合IEnumerable<object>连接并复制到MultiServiceResolver类中的一个字段中
            //之后MultiServiceResolver对象的Current属性就是获取该集合
            _serviceResolver = new MultiServiceResolver<IFilterProvider>(() => Items);
        }
    
        public FilterProviderCollection(IList<IFilterProvider> providers)
            : base(providers)
        {
            _serviceResolver = new MultiServiceResolver<IFilterProvider>(() => Items);
        }
    
        internal FilterProviderCollection(IResolver<IEnumerable<IFilterProvider>> serviceResolver, params IFilterProvider[] providers)
            : base(providers)
        {
            _serviceResolver = serviceResolver ?? new MultiServiceResolver<IFilterProvider>(() => Items);
        }
    
        private IEnumerable<IFilterProvider> CombinedItems
        {
            //获取【过滤器】的【提供器】集合
            get { return _serviceResolver.Current; }
        }
    
        private static bool AllowMultiple(object filterInstance)
        {
            IMvcFilter mvcFilter = filterInstance as IMvcFilter;
            //过滤器没有直接或间接的实现IMvcFilter接口,FilterAttribute类实现了IMvcFilter接口,也就是说该过滤器是一个普通特性。
            if (mvcFilter == null)
            {
                return true;
            }
            return mvcFilter.AllowMultiple;
        }
    
        public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }
            if (actionDescriptor == null)
            {
                throw new ArgumentNullException("actionDescriptor");
            }
            //遍历【过滤器】的【提供器】,也就是在实例化FilterProviders时候添加的那 3 个对象  【GlobalFilters.Filters(也就是new GlobalFilterCollection())】、【new FilterAttributeFilterProvider()】、【new ControllerInstanceFilterProvider()】
            //执行各【提供器】对象的GetFilters方法,获取相应的过滤器,并根据Scope值排序,最后将过滤器添加到combineFilters集合中
            //全局过滤器:Global = 10
            //Controller上应用的过滤器:Controller = 20,
            //Action上应用的过滤:Action=30
            //其实,控制器本身也是一个过滤器:First=0
            IEnumerable<Filter> combinedFilters =
                CombinedItems.SelectMany(fp => fp.GetFilters(controllerContext, actionDescriptor))
                    .OrderBy(filter => filter, _filterComparer);
            //移除重复的过滤器,允许重复的过滤器不做移除,即:应用了AllowMultiple=true的过滤器即使重复也不移除
            //combinedFilters.Reverse()将集合次序倒转去执行移除,从而使得添加过滤器的位置不同优先级也不同。
            //即:如果过滤器没有定义AllowMultiple属性,则只保留Scope值大的过滤器。
            //如果定义AllowMultiple=true,那么就先执行Scope值小的,再执行Scope值大的过滤器。
            return RemoveDuplicates(combinedFilters.Reverse()).Reverse();
        }
    
        private IEnumerable<Filter> RemoveDuplicates(IEnumerable<Filter> filters)
        {
            HashSet<Type> visitedTypes = new HashSet<Type>();
            //从后向前循环所有的过滤器
            foreach (Filter filter in filters)
            {
                object filterInstance = filter.Instance;
                Type filterInstanceType = filterInstance.GetType();
                //visitedTypes集合中不包含该过滤器
                //AllowMultiple方法:该过滤器如果没有继承FilterAttribute类(该类实现了IMvcFilter接口),返回true;否则返回该过滤器的AllowMultiple属性(默认为false)。
                //即:visitedTypes集合中不包含该过滤器,添加
                //      使用过滤器时定义AllowMultiple属性为true时,添加
                //    该过滤器没有实现IMvcFilter接口,则添加;指的是该特性不是MVC过滤器,即:应用的普通特性,而不是MVC过滤器
                if (!visitedTypes.Contains(filterInstanceType) || AllowMultiple(filterInstance))
                {
                    yield return filter;
                    visitedTypes.Add(filterInstanceType);
                }
            }
        }
    
        private class FilterComparer : IComparer<Filter>
        {
            public int Compare(Filter x, Filter y)
            {
                // Nulls always have to be less than non-nulls
                if (x == null && y == null)
                {
                    return 0;
                }
                if (x == null)
                {
                    return -1;
                }
                if (y == null)
                {
                    return 1;
                }
    
                // Sort first by order...
    
                if (x.Order < y.Order)
                {
                    return -1;
                }
                if (x.Order > y.Order)
                {
                    return 1;
                }
    
                // ...then by scope
    
                if (x.Scope < y.Scope)
                {
                    return -1;
                }
                if (x.Scope > y.Scope)
                {
                    return 1;
                }
    
                return 0;
            }
        }
    }
    FilterProviderCollection
    internal class MultiServiceResolver<TService> : IResolver<IEnumerable<TService>>
        where TService : class
    {
        private Lazy<IEnumerable<TService>> _itemsFromService;
        private Func<IEnumerable<TService>> _itemsThunk;
        private Func<IDependencyResolver> _resolverThunk;
        
        //过滤器时TService=IFilterProvider
        public MultiServiceResolver(Func<IEnumerable<TService>> itemsThunk)
        {
            if (itemsThunk == null)
            {
                throw new ArgumentNullException("itemsThunk");
            }
    
            _itemsThunk = itemsThunk;
            _resolverThunk = () => DependencyResolver.Current;
            //resolver.GetServices<TService>()方法是反射获取实例对象,此处内部执行的是 return Enumerable.Empty<object>(); 也就返回了一个空的Objcect类型集合IEnumerable<object>
            _itemsFromService = new Lazy<IEnumerable<TService>>(() => _resolverThunk().GetServices<TService>());
        }
    
        internal MultiServiceResolver(Func<IEnumerable<TService>> itemsThunk, IDependencyResolver resolver)
            : this(itemsThunk)
        {
            if (resolver != null)
            {
                _resolverThunk = () => resolver;
            }
        }
    
        public IEnumerable<TService> Current
        {
            //Concat方法连接两个序列,是将 【空的IEnumerable<TService>集合】和【原来添加的过滤器提供器的集合】连接起来,并转换为数组类型。(其实还是【过滤器提供器的集合】)
            get { return _itemsFromService.Value.Concat(_itemsThunk()); }
        }
    }
    MultiServiceResolver
    public sealed class GlobalFilterCollection : IEnumerable<Filter>, IFilterProvider
    {
        private List<Filter> _filters = new List<Filter>();
    
        public int Count
        {
            get { return _filters.Count; }
        }
    
        public void Add(object filter)
        {
            AddInternal(filter, order: null);
        }
    
        public void Add(object filter, int order)
        {
            AddInternal(filter, order);
        }
    
        private void AddInternal(object filter, int? order)
        {
            ValidateFilterInstance(filter);
            //将过滤器添加到集合中
            _filters.Add(new Filter(filter, FilterScope.Global, order));
        }
    
        public void Clear()
        {
            _filters.Clear();
        }
    
        public bool Contains(object filter)
        {
            return _filters.Any(f => f.Instance == filter);
        }
    
        public IEnumerator<Filter> GetEnumerator()
        {
            return _filters.GetEnumerator();
        }
        
        //这个的目的是,当将实现了IEnumerable接口的类型的对象 转换为IEnumerable接口才能执行该方法
        //在GlobalFilterCollection中声明了一个只有将对象转换为指定类型IEnumerable才可以访问的方法!
        IEnumerator IEnumerable.GetEnumerator()
        {
            return _filters.GetEnumerator();
        }
        //IFilterProvider.GetFilters的目的是,只有将GlobalFilterCollection实例转换为IFilterProvider接口类型后才能执行该方法。
        //在GlobalFilterCollection中声明了一个只有将对象转换为指定类型IFilterProvider才可以访问的方法!
        IEnumerable<Filter> IFilterProvider.GetFilters(ControllerContext controllerContext,
            ActionDescriptor actionDescriptor)
        {
            //将本类的当前对象返回。
            //因为这个类实现了IEnumerable<Filter>接口。也完成了迭代器的重写(上面的两个方法中_filters.GetEnumerator()),所以Foreach才能遍历_filters变量中的值。
            return this;
        }
    
        public void Remove(object filter)
        {
            _filters.RemoveAll(f => f.Instance == filter);
        }
    
        private static void ValidateFilterInstance(object instance)
        {
            if (instance != null && !(
                instance is IActionFilter ||
                instance is IAuthorizationFilter ||
                instance is IExceptionFilter ||
                instance is IResultFilter ||
                instance is IAuthenticationFilter))
            {
                throw new InvalidOperationException(MvcResources.GlobalFilterCollection_UnsupportedFilterInstance);
            }
        }
    }
    GlobalFilterCollection
    public class FilterAttributeFilterProvider : IFilterProvider
    {
        //构造函数中设置为true
        private readonly bool _cacheAttributeInstances;
    
        public FilterAttributeFilterProvider()
            : this(true)
        {
        }
    
        public FilterAttributeFilterProvider(bool cacheAttributeInstances)
        {
            _cacheAttributeInstances = cacheAttributeInstances;
        }
    
        protected virtual IEnumerable<FilterAttribute> GetActionAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
        {
            //通过Action描述(封装了当前的Action的信息),获取应用在Action上的过滤器
            return actionDescriptor.GetFilterAttributes(_cacheAttributeInstances);
        }
    
        protected virtual IEnumerable<FilterAttribute> GetControllerAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
        {
            //根据Action描述先获取Controller描述(封装了当前的Controller的信息),
            return actionDescriptor.ControllerDescriptor.GetFilterAttributes(_cacheAttributeInstances);
        }
        
        //yield关键字,当遍历此方法GetFilters的返回值IEnumerable<Filter>时,只有循环到来时才执行一次return,延迟执行。(其实是实现每次循环值返回一个Filter对象。而不是一个Filter集合)
        public virtual IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
        {
            // Results are low in number in the common case so use yield return to avoid creating intermediate collections or nested enumerables
            if (controllerContext.Controller != null)
            {
                //遍历获取应用在Controller上的过滤器
                //先执行GetControllerAttributes方法,获取所有应用在Controller上的过滤器。(直接全部得到)
                //然后根据过滤器创建Filter对象。
                foreach (FilterAttribute attr in GetControllerAttributes(controllerContext, actionDescriptor))
                {
                    yield return new Filter(attr, FilterScope.Controller, order: null);
                }
                //遍历获取应用在Action上的过滤器
                foreach (FilterAttribute attr in GetActionAttributes(controllerContext, actionDescriptor))
                {
                    yield return new Filter(attr, FilterScope.Action, order: null);
                }
            }             
        }
    }
    FilterAttributeFilterProvider
    public class ControllerInstanceFilterProvider : IFilterProvider
    {
        public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
        {
            if (controllerContext.Controller != null)
            {
                // Use FilterScope.First and Order of Int32.MinValue to ensure controller instance methods always run first
                yield return new Filter(controllerContext.Controller, FilterScope.First, Int32.MinValue);
            }
        }
    }
    ControllerInstanceFilterProvider
    public class FilterInfo
    {
        private List<IActionFilter> _actionFilters = new List<IActionFilter>();
        private List<IAuthorizationFilter> _authorizationFilters = new List<IAuthorizationFilter>();
        private List<IExceptionFilter> _exceptionFilters = new List<IExceptionFilter>();
        private List<IResultFilter> _resultFilters = new List<IResultFilter>();
    
        public FilterInfo()
        {
        }
    
        public FilterInfo(IEnumerable<Filter> filters)
        {
            // evaluate the 'filters' enumerable only once since the operation can be quite expensive
            var filterInstances = filters.Select(f => f.Instance).ToList();
    
            _actionFilters.AddRange(filterInstances.OfType<IActionFilter>());
            _authorizationFilters.AddRange(filterInstances.OfType<IAuthorizationFilter>());
            _exceptionFilters.AddRange(filterInstances.OfType<IExceptionFilter>());
            _resultFilters.AddRange(filterInstances.OfType<IResultFilter>());
        }
    
        public IList<IActionFilter> ActionFilters
        {
            get { return _actionFilters; }
        }
    
        public IList<IAuthorizationFilter> AuthorizationFilters
        {
            get { return _authorizationFilters; }
        }
    
        public IList<IExceptionFilter> ExceptionFilters
        {
            get { return _exceptionFilters; }
        }
    
        public IList<IResultFilter> ResultFilters
        {
            get { return _resultFilters; }
        }
    }
    FilterInfo

      上述代码中,实现了获取过滤器,而过滤器可以通过4种方式添加:1、Global.asax中的RegisterGlobalFilters方法,Scope=10;2、在控制器HomeController上以特性的方法添加,Scope=20;3、在Action上以特性的方式添加,Scope=30;4、控制器HomeController本身也是过滤器,它实现了各过滤器接口,Scope=0;
      针对以上的4中添加方法,【1】直接通过GlobalFilterCollection集合来获取,应为GlobalFilterCollection实现了IEnumerable接口、【2】【3】通过FilterAttributeFilterProvider对象的GetFilters方法来获取、【4】通过ControllerInstanceFilterProvider对象的GetFilters方法来获取。
      所以,整个流程为:遍历执行各【过滤器的提供器】的GetFilters方法,从而得到所有过滤器且过滤器按照Scope值从小到大排列,然后再从后向前执行来对不允许重复使用的过滤器进行去重(只保留Scope值大的过滤器),如果允许重复使用的话(AllowMutiple=true),表示允许重复使用该过滤器,则不执行去重。最终将得到的过滤器按照过滤器类型(按接口不同)分类封装到FilterInfo对象中。
    更正:
    FilterProviderCollection类的AllowMultiple方法中【if(mvcFilter==null){true}】,也表示该过滤器为控制器本身。因为Controller类只实现了过滤器接口,而没有实现IMvcFilter接口或继承实现了IMvcFilter接口的类。

     扩展:如有兴趣可以看一下MVC5中过获取过滤器代码

    public class FilterProviderCollection : Collection<IFilterProvider>
    {
        private static FilterComparer _filterComparer = new FilterComparer();
        private IFilterProvider[] _combinedItems;
        private IDependencyResolver _dependencyResolver;
    
        //先执行父类Collection<IFilterProvider>的无参数构造函数,创建一个私有变量来保存 【过滤器的提供器】
        public FilterProviderCollection()
        {
        }
    
        public FilterProviderCollection(IList<IFilterProvider> providers)
            : base(providers)
        {
        }
    
        internal FilterProviderCollection(IList<IFilterProvider> list, IDependencyResolver dependencyResolver)
            : base(list)
        {
            _dependencyResolver = dependencyResolver;
        }
        //其实得到的是添加到该集合中的所有【过滤器】的【提供器】。
        internal IFilterProvider[] CombinedItems
        {
            get
            {
                IFilterProvider[] combinedItems = _combinedItems;
                if (combinedItems == null)
                {
                    //Items是父类Collection<IFilterProvider>中的一个属性,得到添加到该集合中的所有【过滤器】的【提供器】。
                    //通过GetCombined方法将 【一个空的IEnumerable<IFilterProvider>集合】 和 【原来的过滤器的提供器集合】连接,并转换为IFilterProvider数组类型,返回。
                    //这里的【一个空的IEnumerable<IFilterProvider>集合】是通过DefaultDependencyResolver的GetServices方法获取的。(原来定义这个的功能是反射创建实例,这里返回空的集合,可能是为下一个版本做扩展而留下的吧)
                    combinedItems = MultiServiceResolver.GetCombined<IFilterProvider>(Items, _dependencyResolver);
                    _combinedItems = combinedItems;
                }
                return combinedItems;
            }
        }
    
        private static bool AllowMultiple(object filterInstance)
        {
            IMvcFilter mvcFilter = filterInstance as IMvcFilter;
            if (mvcFilter == null)
            {
                return true;
            }
    
            return mvcFilter.AllowMultiple;
        }
    
        //获取筛选器
        public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }
            if (actionDescriptor == null)
            {
                throw new ArgumentNullException("actionDescriptor");
            }
            //得到所有的过滤器提供器。(实例化FilterProviders时候添加的那 3 个  【GlobalFilters.Filters(也就是new GlobalFilterCollection())】、【new FilterAttributeFilterProvider()】、【new ControllerInstanceFilterProvider()】)
            IFilterProvider[] providers = CombinedItems;
            
            List<Filter> filters = new List<Filter>();
            for (int i = 0; i < providers.Length; i++)
            {
                //第一个是GlobalFilterCollection对象,其继承自IFilterProvider。(在Global.ascx文件的RegisterGlobalFilters方法中,添加过滤器到此过滤器提供器中)
                //第二个是FilterAttributeFilterProvider对象,也继承自IFilterProvider。
                IFilterProvider provider = providers[i];
                //第一个GlobalFilterCollection,GetFilters方法得到就是当前GlobalFilterCollection对象(它实现了IEnumerable,所以也是集合)。而foreach遍历的是该对象的变量_filters中的值,并将值添加到此方法中声明的局部变量filters中。到===第一个中设计两个知识点:迭代,接口点方法
                //第二个FilterAttributeFilterProvider,GetFilters方法得的是Controller上应用的过滤器和Action上应用的过滤器
                foreach (Filter filter in provider.GetFilters(controllerContext, actionDescriptor))
                {
                    filters.Add(filter);
                }
            }
    
            filters.Sort(_filterComparer);
    
            if (filters.Count > 1)
            {
                RemoveDuplicates(filters);
            }
            return filters;
        }
    
        private static void RemoveDuplicates(List<Filter> filters)
        {
            HashSet<Type> visitedTypes = new HashSet<Type>();
    
            // Remove duplicates from the back forward
            for (int i = filters.Count - 1; i >= 0; i--)
            {
                Filter filter = filters[i];
                object filterInstance = filter.Instance;
                Type filterInstanceType = filterInstance.GetType();
    
                if (!visitedTypes.Contains(filterInstanceType) || AllowMultiple(filterInstance))
                {
                    visitedTypes.Add(filterInstanceType);
                }
                else
                {
                    filters.RemoveAt(i);                        
                }
            }
        }
    
        protected override void ClearItems()
        {
            _combinedItems = null;
            base.ClearItems();
        }
    
        protected override void InsertItem(int index, IFilterProvider item)
        {
            _combinedItems = null;
            base.InsertItem(index, item);
        }
    
        protected override void RemoveItem(int index)
        {
            _combinedItems = null;
            base.RemoveItem(index);
        }
    
        protected override void SetItem(int index, IFilterProvider item)
        {
            _combinedItems = null;
            base.SetItem(index, item);
        }
    
        private class FilterComparer : IComparer<Filter>
        {
            public int Compare(Filter x, Filter y)
            {
                // Nulls always have to be less than non-nulls
                if (x == null && y == null)
                {
                    return 0;
                }
                if (x == null)
                {
                    return -1;
                }
                if (y == null)
                {
                    return 1;
                }
    
                // Sort first by order...
    
                if (x.Order < y.Order)
                {
                    return -1;
                }
                if (x.Order > y.Order)
                {
                    return 1;
                }
    
                // ...then by scope
    
                if (x.Scope < y.Scope)
                {
                    return -1;
                }
                if (x.Scope > y.Scope)
                {
                    return 1;
                }
    
                return 0;
            }
        }
    }
    MVC5:FilterProviderCollection
    internal static class MultiServiceResolver        
    {
        //过滤器时TService=IFilterProvider
        internal static TService[] GetCombined<TService>(IList<TService> items, IDependencyResolver resolver = null) where TService : class
        {           
            if (resolver == null)
            {
                resolver = DependencyResolver.Current;
            }
            //resolver.GetServices<TService>()方法内部执行 return Enumerable.Empty<object>(); ,也就返回了一个空的Objcect类型集合IEnumerable<object> 。
            IEnumerable<TService> services = resolver.GetServices<TService>();
            //Concat方法连接两个序列,应该是将 【空的IEnumerable<TService>集合】和【原来添加的过滤器提供器的集合】连接起来,并转换为数组类型。(其实还是【过滤器提供器的集合】)
            return services.Concat(items).ToArray();
        } 
    }
    MVC5:MultiServiceResolver

     3、AuthorizationContext authContext = InvokeAuthorizationFilters(controllerContext, filterInfo.AuthorizationFilters, actionDescriptor);

       执行Authorize授权过滤器,其实就是执过滤器的OnAuthorization方法。AuthorizeAttribute是一个MVC的授权过滤器,可参考定义自己的授权过滤器。授权过滤器本质上是去读取cookie,检查cookie中相应的值是否和授权过滤器中设置的一致(可以用来做登录之后才能访问某页面的功能)。

    public class ControllerActionInvoker : IActionInvoker
    {
        public virtual bool InvokeAction(ControllerContext controllerContext, string actionName)
        {
            ControllerDescriptor controllerDescriptor = GetControllerDescriptor(controllerContext);
            ActionDescriptor actionDescriptor = FindAction(controllerContext, controllerDescriptor, actionName);
            if (actionDescriptor != null)
            {
                FilterInfo filterInfo = GetFilters(controllerContext, actionDescriptor);
                try
                {
                    //执行Authorize过滤器
                    AuthorizationContext authContext = InvokeAuthorizationFilters(controllerContext, filterInfo.AuthorizationFilters, actionDescriptor);
                    if (authContext.Result != null)
                    {
                        //没有通过过滤器,按照自定义的ActionResult直接进行View的呈现
                        //View的呈现
                        InvokeActionResult(controllerContext, authContext.Result);
                    }
                    //省略其他代码
                }
    
                return true;
            }
            return false;
        }
    
        protected virtual AuthorizationContext InvokeAuthorizationFilters(ControllerContext controllerContext, IList<IAuthorizationFilter> filters, ActionDescriptor actionDescriptor)
        {
            AuthorizationContext context = new AuthorizationContext(controllerContext, actionDescriptor);
            foreach (IAuthorizationFilter filter in filters)
            {
                //当没有通过Authorize过滤器时,OnAuthorization方法中会创建一个ActionResult对象并赋值给Result属性
                filter.OnAuthorization(context);
                
                if (context.Result != null)
                {
                    //如果有任意Authorize过滤器未通过,则跳出循环不再继续执行其他Authorize过滤器
                    break;
                }
            }
            return context;
        }
    }
    ControllerActionInvoker

      上述代码中,遍历所有的Authorize授权过滤器并执行其OnAuthorization方法,在OnAuthorization方法中,如果请求不满足条件,则创建一个ActionResult对象并赋值给AuthorizationContext对象的Result属性,之后直接使用该ActionResult进行View的呈现。
      在MVC中,AuthorizeAttribute是微软定义的一个授权过滤器,它的OnAuthorization方法中规定,如果不满足条件的话,就跳转到登录页面(在WebConfig文件中配置)。

     

    4、IDictionary<string, object> parameters = GetParameterValues(controllerContext, actionDescriptor);

      模型绑定,获取Action方法参数对象的实参。详细请看:白话学习MVC(六)模型绑定

     5、ActionExecutedContext postActionContext = InvokeActionMethodWithFilters(controllerContext, filterInfo.ActionFilters, actionDescriptor, parameters);

      执行【方法过滤器】(实现IActionFilter接口)并执行Action方法内的代码

    public class ControllerActionInvoker : IActionInvoker
    {
        public virtual bool InvokeAction(ControllerContext controllerContext, string actionName)
        {
            ControllerDescriptor controllerDescriptor = GetControllerDescriptor(controllerContext);
            ActionDescriptor actionDescriptor = FindAction(controllerContext, controllerDescriptor, actionName);
            if (actionDescriptor != null)
            {
                FilterInfo filterInfo = GetFilters(controllerContext, actionDescriptor);
    
                try
                {
                    AuthorizationContext authContext = InvokeAuthorizationFilters(controllerContext, filterInfo.AuthorizationFilters, actionDescriptor);
                    if (authContext.Result != null)
                    {
                        InvokeActionResult(controllerContext, authContext.Result);
                    }
                    else
                    {
                        if (controllerContext.Controller.ValidateRequest)
                        {
                            ValidateRequest(controllerContext);
                        }
                        IDictionary<string, object> parameters = GetParameterValues(controllerContext, actionDescriptor);
                        //执行【方法过滤器】(实现IActionFilter接口)并执行Action方法内的代码
                        ActionExecutedContext postActionContext = InvokeActionMethodWithFilters(controllerContext, filterInfo.ActionFilters, actionDescriptor, parameters);
                        
                        InvokeActionResultWithFilters(controllerContext, filterInfo.ResultFilters, postActionContext.Result);
                    }
                }
                catch (ThreadAbortException)
                {
                    // This type of exception occurs as a result of Response.Redirect(), but we special-case so that
                    // the filters don't see this as an error.
                    throw;
                }
                catch (Exception ex)
                {
                    // something blew up, so execute the exception filters
                    ExceptionContext exceptionContext = InvokeExceptionFilters(controllerContext, filterInfo.ExceptionFilters, ex);
                    if (!exceptionContext.ExceptionHandled)
                    {
                        throw;
                    }
                    InvokeActionResult(controllerContext, exceptionContext.Result);
                }
    
                return true;
            }
    
            // notify controller that no method matched
            return false;
        }
        
        protected virtual ActionExecutedContext InvokeActionMethodWithFilters(ControllerContext controllerContext, IList<IActionFilter> filters, ActionDescriptor actionDescriptor, IDictionary<string, object> parameters)
        {
            ////创建Executing上下文,其中封装了请求上下文、当前Controller,当前Action,当前Action的参数
            ActionExecutingContext preContext = new ActionExecutingContext(controllerContext, actionDescriptor, parameters);
            //将【Action内代码的执行】添加到委托中
            Func<ActionExecutedContext> continuation = () =>
                                                       new ActionExecutedContext(controllerContext, actionDescriptor, false /* canceled */, null /* exception */)
                                                       {
                                                           //InvokeActionMethod执行Action方法内的代码,并返回方法的返回值。
                                                           Result = InvokeActionMethod(controllerContext, actionDescriptor, parameters)
                                                       };
    
            //------------------调炸天的一句代码------------------
            //代码的实现是在InvokeActionMethodFilter方法中,
            //此句代码保证了在InvokeActionMethodFilter方法中,先循环执行所有的【方法过滤器】的ActionExecting方法,然后再执行Action方法内的代码,最后再循环执行所有的【方法过滤器】的ActionExected方法
            Func<ActionExecutedContext> thunk = filters.Reverse().Aggregate(continuation,
                                                                            (next, filter) => () => InvokeActionMethodFilter(filter, preContext, next));
            return thunk();
        }
        
        //执行Action内的代码,并获取返回值!
        protected virtual ActionResult InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary<string, object> parameters)
        {
            //执行Action方法内的代码。
            //actionDescriptor是一个ReflectedActionDescriptor对象
            object returnValue = actionDescriptor.Execute(controllerContext, parameters);
            ActionResult result = CreateActionResult(controllerContext, actionDescriptor, returnValue);
            return result;
        }
        
        internal static ActionExecutedContext InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func<ActionExecutedContext> continuation)
        {
            //代码的实现是在InvokeActionMethodFilter方法中
            //首先,循环执行应用在Action上的所有过滤器的ActionExecuting,如果没有通过,则按照定义在ActionExecuting方法中创建的ActionResult(Result=New ActionResult())去执行view的呈现,不在继续执行!
            //如果通过(则Result==null,默认),那么执行Action方法内的代码,并将Action方法的返回值设置给上下文对象的Result属性!
            //如果Action内的方法的执行出现异常,那么不再去执行过滤器的ActionExecuted。否则,继续执行过滤器的ActionExecuted
            //执行ActionExecuted,参数为Action上下文(Result=Action方法内的返回值)。
            //如果没有通过ActionExecuted,那么就更改上下文中的Result为自己定义的ActionReuslt,并设置到上下文中。
            //返回这个上下文,view的呈现时,便使用这个ActionResult作为返回值。
        
        
            //执行Action过滤器的ActionExecuting方法
            filter.OnActionExecuting(preContext);
            //过滤器是否通过的判断为:是否在方法中定义了返回结果
            if (preContext.Result != null)
            {
                //没有通过
                return new ActionExecutedContext(preContext, preContext.ActionDescriptor, true /* canceled */, null /* exception */)
                {
                    Result = preContext.Result
                };
            }
            //通过了ActionExecuting
            bool wasError = false;
            ActionExecutedContext postContext = null;
            //以上代码循环所有的filter,全部执行一次!之后再继续执行...
            
            
            //执行Action方法内的代码
            try
            {
                //执行InvokeActionMethodWithFilters方法中的continuation委托。==也就是执行Action方法内的代码
                postContext = continuation();
            }
            catch (ThreadAbortException)
            {
                // This type of exception occurs as a result of Response.Redirect(), but we special-case so that
                // the filters don't see this as an error.
                postContext = new ActionExecutedContext(preContext, preContext.ActionDescriptor, false /* canceled */, null /* exception */);
                filter.OnActionExecuted(postContext);
                throw;
            }
            catch (Exception ex)
            {
                wasError = true;
                postContext = new ActionExecutedContext(preContext, preContext.ActionDescriptor, false /* canceled */, ex);
                filter.OnActionExecuted(postContext);
                if (!postContext.ExceptionHandled)
                {
                    throw;
                }
            }
            
            //循环执行所有的ActionExecuted
            //在循环所有的filter执行循环的时候return之前的!
            if (!wasError)
            {
                filter.OnActionExecuted(postContext);
            }
            
            //最终返回
            return postContext;
        }
    }
    ControllerActionInvoker

      上述代码,首先循环执行所有Action过滤器的ActionExecuting方法,然后执行Action方法内的代码,最后再循环执行所有的Action过滤器的ActionExecuted方法。此过程的过滤器中,如果不满足过滤器的要求,则直接利用自定义的ActionResult对象进行View的呈现!
      在执行Action方法内部代码时,那些返回值:return Content()、return View()、return Json()等,其实都是执行Controller类的方法,这些方法内创建继承自ActionResult类的ContentResult、ViewResult、JsonResult的对象并返回。

    public abstract class Controller : ControllerBase, IActionFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter, IAsyncController, IAsyncManagerContainer
    {
        //仅列举部分方法
        protected internal FileContentResult File(byte[] fileContents, string contentType)
        {
            return File(fileContents, contentType, null /* fileDownloadName */);
        }
    
        protected internal virtual FileContentResult File(byte[] fileContents, string contentType, string fileDownloadName)
        {
            return new FileContentResult(fileContents, contentType) { FileDownloadName = fileDownloadName };
        }
    
        protected internal FileStreamResult File(Stream fileStream, string contentType)
        {
            return File(fileStream, contentType, null /* fileDownloadName */);
        }
    
        protected internal virtual FileStreamResult File(Stream fileStream, string contentType, string fileDownloadName)
        {
            return new FileStreamResult(fileStream, contentType) { FileDownloadName = fileDownloadName };
        }
    
        protected internal FilePathResult File(string fileName, string contentType)
        {
            return File(fileName, contentType, null /* fileDownloadName */);
        }
    
        protected internal virtual FilePathResult File(string fileName, string contentType, string fileDownloadName)
        {
            return new FilePathResult(fileName, contentType) { FileDownloadName = fileDownloadName };
        }
    
        protected virtual void HandleUnknownAction(string actionName)
        {
            throw new HttpException(404, String.Format(CultureInfo.CurrentCulture,
                                                       MvcResources.Controller_UnknownAction, actionName, GetType().FullName));
        }
    
        protected internal HttpNotFoundResult HttpNotFound()
        {
            return HttpNotFound(null);
        }
    
        protected internal virtual HttpNotFoundResult HttpNotFound(string statusDescription)
        {
            return new HttpNotFoundResult(statusDescription);
        }
    
        protected internal virtual JavaScriptResult JavaScript(string script)
        {
            return new JavaScriptResult { Script = script };
        }
    
        protected internal JsonResult Json(object data)
        {
            return Json(data, null /* contentType */, null /* contentEncoding */, JsonRequestBehavior.DenyGet);
        }
    
        protected internal JsonResult Json(object data, string contentType)
        {
            return Json(data, contentType, null /* contentEncoding */, JsonRequestBehavior.DenyGet);
        }
    
        protected internal virtual JsonResult Json(object data, string contentType, Encoding contentEncoding)
        {
            return Json(data, contentType, contentEncoding, JsonRequestBehavior.DenyGet);
        }
    
        protected internal JsonResult Json(object data, JsonRequestBehavior behavior)
        {
            return Json(data, null /* contentType */, null /* contentEncoding */, behavior);
        }
    
        protected internal JsonResult Json(object data, string contentType, JsonRequestBehavior behavior)
        {
            return Json(data, contentType, null /* contentEncoding */, behavior);
        }
    
        protected internal virtual JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior)
        {
            return new JsonResult
            {
                Data = data,
                ContentType = contentType,
                ContentEncoding = contentEncoding,
                JsonRequestBehavior = behavior
            };
        }
    }
    Controller

    补充:过滤器的ActionExecuting方法和ActionExecuted方法的执行是按照一条龙的顺序执行的。


    此图摘自:http://www.cnblogs.com/artech/archive/2012/08/06/action-filter.html

    重要:InvokeActionMethodWithFilters方法中的那句碉堡的代码实现了一条龙的方式去【OnActionExecuting】和【OnActionExecuted】方法,必须要好好学习下!!!

    6、InvokeActionResultWithFilters(controllerContext, filterInfo.ResultFilters, postActionContext.Result);

      执行【结果过滤器】(实现IResultFilter接口),再做View的呈现。

    public class ControllerActionInvoker : IActionInvoker
    {
        public virtual bool InvokeAction(ControllerContext controllerContext, string actionName)
        {
            
            ControllerDescriptor controllerDescriptor = GetControllerDescriptor(controllerContext);
            ActionDescriptor actionDescriptor = FindAction(controllerContext, controllerDescriptor, actionName);
            if (actionDescriptor != null)
            {
                FilterInfo filterInfo = GetFilters(controllerContext, actionDescriptor);
    
                try
                {
                    AuthorizationContext authContext = InvokeAuthorizationFilters(controllerContext, filterInfo.AuthorizationFilters, actionDescriptor);
                    if (authContext.Result != null)
                    {
                        InvokeActionResult(controllerContext, authContext.Result);
                    }
                    else
                    {
                        if (controllerContext.Controller.ValidateRequest)
                        {
                            ValidateRequest(controllerContext);
                        }
                        IDictionary<string, object> parameters = GetParameterValues(controllerContext, actionDescriptor);
                        ActionExecutedContext postActionContext = InvokeActionMethodWithFilters(controllerContext, filterInfo.ActionFilters, actionDescriptor, parameters);
                         //执行【结果过滤器】(实现IResultFilter接口),再做View的呈现。(执行的模式和上一句代码的执行模式相同!)
                        InvokeActionResultWithFilters(controllerContext, filterInfo.ResultFilters, postActionContext.Result);
                    }
                }
                catch (ThreadAbortException)
                {
                    // This type of exception occurs as a result of Response.Redirect(), but we special-case so that
                    // the filters don't see this as an error.
                    throw;
                }
                catch (Exception ex)
                {
                    // something blew up, so execute the exception filters
                    ExceptionContext exceptionContext = InvokeExceptionFilters(controllerContext, filterInfo.ExceptionFilters, ex);
                    if (!exceptionContext.ExceptionHandled)
                    {
                        throw;
                    }
                    InvokeActionResult(controllerContext, exceptionContext.Result);
                }
    
                return true;
            }
    
            // notify controller that no method matched
            return false;
        }
        protected virtual ResultExecutedContext InvokeActionResultWithFilters(ControllerContext controllerContext, IList<IResultFilter> filters, ActionResult actionResult)
        {
            ResultExecutingContext preContext = new ResultExecutingContext(controllerContext, actionResult);
            //将View的呈现加入到委托链中
            Func<ResultExecutedContext> continuation = delegate
            {
                //执行View的呈现
                InvokeActionResult(controllerContext, actionResult);
                return new ResultExecutedContext(controllerContext, actionResult, false /* canceled */, null /* exception */);
            };
    
            //先循环执行所有的Result过滤器的OnResultExecuting方法,然后执行View的呈现,再循环执行所有的Result过滤器的OnResultExecuted方法
            //执行过滤器方法时候还是一条龙的方式
            Func<ResultExecutedContext> thunk = filters.Reverse().Aggregate(continuation,
                                                                            (next, filter) => () => InvokeActionResultFilter(filter, preContext, next));
            return thunk();
        }
        internal static ResultExecutedContext InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func<ResultExecutedContext> continuation)
        {
            //循环执行所有的Result过滤器的OnResultExecuting方法
            filter.OnResultExecuting(preContext);
            if (preContext.Cancel)
            {
                return new ResultExecutedContext(preContext, preContext.Result, true /* canceled */, null /* exception */);
            }
    
            bool wasError = false;
            ResultExecutedContext postContext = null;
            try
            {
                //执行委托,委托链中的InvokeActionResult方法进行View的呈现!
                postContext = continuation();
            }
            catch (ThreadAbortException)
            {
                // This type of exception occurs as a result of Response.Redirect(), but we special-case so that
                // the filters don't see this as an error.
                postContext = new ResultExecutedContext(preContext, preContext.Result, false /* canceled */, null /* exception */);
                filter.OnResultExecuted(postContext);
                throw;
            }
            catch (Exception ex)
            {
                wasError = true;
                postContext = new ResultExecutedContext(preContext, preContext.Result, false /* canceled */, ex);
                filter.OnResultExecuted(postContext);
                if (!postContext.ExceptionHandled)
                {
                    throw;
                }
            }
            if (!wasError)
            {
                //循环执行所有的Result过滤器的OnResultExecuted方法
                //扩展:由于过滤器的此方法是在View的呈现之后,所以可以利用Result过滤器的OnResultExecuted在此生成静态页
                filter.OnResultExecuted(postContext);
            }
            return postContext;
        }
    
    }
    ControllerActionInvoker

       上述代码中,先循环执行所有的Result过滤器的OnResultExecuting方法,然后执行View的呈现,再循环执行所有的Result过滤器的OnResultExecuted方法。执行流程也是一条龙的方方式!

       以上所有就是Action执行的全部,如果不符之处,请指正!由以上的执行可知【View的呈现】是通过ControllerActionInvoker类的InvokeActionResult方法来实现的,下一篇就来详细分析View的呈现相关的知识!

  • 相关阅读:
    学习也好,科研也罢,都有内在规律。任何事物,只消抓住规律,就等于牵住牛鼻子
    赵伟国:陆资无法进入台湾紫光要到WTO控告(芯片是为了经济安全,高通找的人不是很聪明)
    小米新旗舰“翻车” 冲击中高端凸显品控短板(小米的缺点还真不少:电商、性价比、爆款、粉丝经济,说到底也都只是商业上的创新)
    WinRarHelper帮助类
    Window7下安装Ubuntu 14.04 64bit
    Kafka基本原理
    Abot爬虫和visjs
    CLR垃圾回收的设计
    NET Core全新的配置管理
    Github Atom
  • 原文地址:https://www.cnblogs.com/wupeiqi/p/3405170.html
Copyright © 2020-2023  润新知