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

时间:2023-03-08 23:22:50
白话学习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 :
return null; case :
return finalMethods[]; 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 == )
{
//如果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 > ) ? 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 :
return null;
//只有里面有一个合适的Action时才正确返回。
case :
return finalMethods[]; 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 = ; 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 = ; 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 > );
for (int i = ; 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 - ; i >= ; 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 == )
{
// 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 + < methodInfos.Count)
{
//猜测:是将当前索引上层的所有项都移除(即已经筛选出的符合的Action都移除--没有应用特性的)。
//猜想正确,此RemoveFrom是MVC写的一个List<T>的扩展方法,MVC源码的目录 .\src\Common\ 的CollectionExtensions.cs类中
methodInfos.RemoveFrom(i + );
}
//将这个标识设置为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 ;
}
if (x == null)
{
return -;
}
if (y == null)
{
return ;
} // Sort first by order... if (x.Order < y.Order)
{
return -;
}
if (x.Order > y.Order)
{
return ;
} // ...then by scope if (x.Scope < y.Scope)
{
return -;
}
if (x.Scope > y.Scope)
{
return ;
} return ;
}
}
}

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 = ; 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 > )
{
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 - ; i >= ; 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 ;
}
if (x == null)
{
return -;
}
if (y == null)
{
return ;
} // Sort first by order... if (x.Order < y.Order)
{
return -;
}
if (x.Order > y.Order)
{
return ;
} // ...then by scope if (x.Scope < y.Scope)
{
return -;
}
if (x.Scope > y.Scope)
{
return ;
} return ;
}
}
}

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文件中配置)。
白话学习MVC(八)Action的执行二

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(, 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方法的执行是按照一条龙的顺序执行的。

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

此图摘自: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方法。执行流程也是一条龙的方方式!
白话学习MVC(八)Action的执行二

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