白话学习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源码的目录 .\src\Common\ 的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的呈现相关的知识!

 

 

 

posted @ 2013-11-21 18:52  武沛齐  阅读(2581)  评论(2编辑  收藏  举报