详解ASP.NET MVC的筛选器

在ActionInvoker对Action的执行过程中,除了通过利用ActionDescriptor对Action方法的执行,以及之前进行的Model绑定与验证之外,还具有一个重要的工作,那就是对相关筛选器(Filter)的执行。ASP.NET MVC的筛选器是一种基于AOP(面向方面编程)的设计,我们将一些非业务的逻辑实现在相应的筛选器中,然后以一种横切(Crosscutting)的方式应用到对应的Action方法。当Action方法执行前后,这些筛选器会自动执行。ASP.NET MVC提供了四种类型的筛选器(AuthorizationFilter、ActionFilter、ResultFilter和ExceptionFilter),它们对应着相应的筛选器接口(IAuthorizationFilter、IActionFilter、IResultFilter和IExceptionFilter)。[本文已经同步到《How ASP.NET MVC Works?》中]

目录

一、Filter

二、FilterProvider

三、FilterAttribute与FilterAttributeFilterProvider

四、Controller与ControllerInstanceFilterProvider

五、GlobalFilterCollection

六、实例演示:验证Filter的提供机制和执行顺序

一、Filter

虽然ASP.NET MVC提供的四种类型的筛选器具有各自实现的接口,但是对于筛选器的提供体系来说所有的筛选器都通过具有如下定义的Filter类型表示。Filter的核心是Instance属性,因为它代表真正实施筛选功能的对象,该对象实现了一个或者多个基于上述四种筛选器类型的接口。

public class Filter { public const int DefaultOrder = -1; public Filter(object instance, FilterScope scope, int? order); public object Instance { get; protected set; } public int Order { get; protected set; } public FilterScope Scope { get; protected set; } } public enum FilterScope { Action = 30, Controller = 20, First = 0, Global = 10, Last = 100 }

注:由于System.Web.Mvc.Filter和实现了IAuthorizationFilter、IActionFilter、IResultFilter和IExceptionFilter的类型均可以被称为“筛选器”,为了不至于造成混淆,在没有做明确说明的情况下,我们使用英文“Filter”和中文“筛选器”分别来表示它们。

Filter的Order和Scope属性最终决定了筛选器的执行顺序。Order属性对应数值越小,执行的优先级越高,该属性的默认值为-1(对应着Filter中定义的常量DefaultOrder)。如果两个Filter具有相同的Order属性值,那么Scope属性最终决定哪个被优先执行。Filter的Scope属性类型是一个类型为FilterScope的枚举。该枚举表示应用Filter的范围,Action和Controller代表Action方法和Controller类级别;First和Last意味着希望被作为第一个和最后一个Filter来执行;Global代表一个全局的Filter。

通过上面的代码片断我们可以看到FilterScope的5个枚举选项均被设置了一个值,这个值决定了Filter的执行顺序,具有更小的枚举值会被优先执行。从FilterScope的定义可以得到这样的结论:对于具有相同Order属性值的多个Filter,应用在Controller上的Filter比应用在Action方法上的Filter具有更高的执行优先级,而一个全局的Filter的执行优先级又高于基于Action的Filter。

二、FilterProvider

Filter的提供机制与之前我们介绍的基于ModelBinder和ModelValidator的提供机制比较类似,均是通过相应的Provider来提供的。提供筛选器的FilterProvider实现了接口IFilterProvider,如下面的代码片断所示,该接口定义了唯一的方法GetFilters根据指定的Controller上下文和用于描述目标Action的ActionDescriptor对象获取一个Filter对象集合。

public interface IFilterProvider { IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor); }

我们可以通过静态类型FilterProviders注册或者获取当前应用使用的FilterProvider。如下面的代码片断所示,FilterProviders具有一个类型为FilterProviderCollection的只读属性Providers,表示基于整个Web应用范围内被使用的FilterProvider列表。FilterProviderCollection是元素类型为IFilterProvider的集合,GetFilters方法用于或者该集合中所有FilterProvider对象提供的Filter对象。

public static class FilterProviders { public static FilterProviderCollection Providers { get; } } public class FilterProviderCollection : Collection<IFilterProvider> { //其他成员 public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor); }

ASP.NET MVC提供了三种原生的FilterProvider,分别是FilterAttributeFilterProvider、ControllerInstanceFilterProvider和GlobalFilterCollection,接下来我们对它们进行单独介绍。

三、FilterAttribute与FilterAttributeFilterProvider

我们通常将筛选器定义成特性以声明的方式应用到Controller类型或者Action方法上,而抽象类型FilterAttribute是所有筛选器的基类。如下面的代码片断所示,FilterAttribute特性实现了IMvcFilter接口,该接口定义了Order和AllowMultiple两个只读属性,分别用于控制筛选器的执行顺序以及多个同类的筛选器能够同时应用到同一个目标元素(类或者方法)。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wjywzd.html