ASP.NET MVC中的ActionFilter是如何执行的?2012-12-03 蒋金楠 在ASP.NET MVC中的四大筛选器(Filter),ActionFilter直接应用在某个Action方法上,它在目标Action方法执行前后对调用进行拦截以执行一些额外的操作。这是一种典型的AOP式的设计,如果我们需要在执行某个Action方法的前后执行一些操作,可以通过定义ActionFilter来实现。本篇文章主要讲述多一个应用到相同Action方法上的ActionFilter的执行机制。一、ActionFilterActionFilter允许我们在目标Action方法执行前后对调用进行拦截以执行一些额外的操作,所有的ActionFilter实现了具有如下定义的接口IActionFilter。
 1: public interface IActionFilter
 2: {
 3: void OnActionExecuting(ActionExecutingContext filterContext);
 4: void OnActionExecuted(ActionExecutedContext filterContext);
 5: }
 6:
 7: public class ActionExecutingContext : ControllerContext
 8: {
 9: public ActionExecutingContext();
10: public ActionExecutingContext(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary<string, object> actionParameters);
11:
12: public virtual ActionDescriptorActionDescriptor { get; set; }
13: public virtual IDictionary<string, object> ActionParameters { get; set; }
14: public ActionResultResult { get; set; }
15: }
16:
17: public class ActionExecutedContext : ControllerContext
18: {
19: public ActionExecutedContext();
20: public ActionExecutedContext(ControllerContext controllerContext, ActionDescriptor actionDescriptor, bool canceled, Exception exception);
21:
22: public virtual ActionDescriptor ActionDescriptor { get; set; }
23: public virtual bool Canceled { get; set; }
24: public virtual ExceptionException { get; set; }
25: public bool ExceptionHandled { get; set; }
26: public ActionResult Result { get; set; }
27: }
如上面的代码片断所示,IActionFilter接口中定义了两个方法OnActionExecuting和OnActionExecuted,这两个方法分别在目标Action方法执行前后被调用,它们的参数类型分别为ActionExecutingContext和ActionExecutedContext。这两个上下文了类型均是ControllerContext的子类。我们可以从ActionExecutingContext对象中获取到用于描述当前Action的ActionDescriptor,以及参数列表。ActionFilter可以在OnActionExecuting方法中对ActionExecutingContext对象的Result属性进行赋值来直接响应当前的请求。一旦ActionExecutingContext的Result属性被成功赋值,将会终止后续ActionFilter和最终目标方法的执行。ActionExecutedContext具有额外的三个属性,Exception表示执行Action方法过程中抛出的异常,而ExceptionHandled是一个表示是否对异常已经做出处理的标记。Canceled属性表示没有完成整个ActionFilter链和目标Action方法的执行而中途被终止。二、ActionFilter的执行机制

当ActionInvoker在执行目标Action方法之前,会根据Order和Scope属性对用于封装ActionFilter的Filter对象进行排序。然后根据当前ControllerContext和ActionDescriptro创建一个ActionExecutingContext对象,并将其作为参数依次调用所有ActionFilter的OnActionExecuting方法。在这之后真正的目标Action方法被执行,ActionInvoker随后执行后续的筛选操作。具体来说,它根据当前ControllerContext、ActionDescriptro以及Action方法执行过程中抛出的异常创建一个ActionExecutedContext对象。该ActionExecutedContext的Cancel属性为False,如果Action方法返回一个ActionResult对象,该对象将会作为该ActionExecutedContext的Result属性。接下来按照相反的次序依次调用ActionFilter对象的OnActionExecuted方法,执行过程中的ActionFilter可以修改ActionExecutedContext的Result属性。当整个ActionFilter链执行结束之后,ActionExecutedContext的Result属性返回的ActionResult将会作为对当前请求的响应。右图基本上反映了连同目标Action在内的整个ActionFilter链的执行过程。