前言
Web API的简单流程就是从请求到执行到Action并最终作出响应,但是在这个过程有一把【筛子】,那就是过滤器Filter,在从请求到Action这整个流程中使用Filter来进行相应的处理从而作出响应,这对于授权以及验证时及其重要的,所以说过滤器应用是Web API框架中非常重要的一种实现方式,我们有必要去探讨其原理。
过滤器及其提供机制
Web API框架提供了一个请求、响应的消息处理管道,并且其框架极具扩展性,通过其扩展可以对执行的流程进行适当的干预,其扩展点就体现在以下三个方面:
-
将自定义的HttpMessageHandler注册到消息处理管道中。
-
将自定义的标准化组件注册到当前的服务容器(ServicesContainer)或者(HttpConfiguration)上。
-
将自定义的过滤器Filter注册到控制器或者Action方法上。
Filter创建原理解析
上一节我们讲到了HttpActionDescriptor,顾名思义是在控制器方法上返回的是对控制器方法的描述类型,它封装了控制器方法的一切信息,而过滤器Filter就是在这个类中初始化和创建的,我们首先来看看这个类中我们会用到的方法及其属性:
1 public abstract class HttpActionDescriptor 2 { 3 // Fields 4 private HttpActionBinding _actionBinding; 5 private HttpConfiguration _configuration; 6 private HttpControllerDescriptor _controllerDescriptor; 7 private IActionResultConverter _converter; 8 private readonly Lazy<Collection<FilterInfo>> _filterPipeline; 9 private readonly ConcurrentDictionary<object, object> _properties; 10 private static readonly ResponseMessageResultConverter _responseMessageResultConverter; 11 private readonly Collection<HttpMethod> _supportedHttpMethods; 12 private static readonly VoidResultConverter _voidResultConverter; 13 14 // Methods 15 static HttpActionDescriptor(); 16 protected HttpActionDescriptor(); 17 protected HttpActionDescriptor(HttpControllerDescriptor controllerDescriptor); 18 private static bool AllowMultiple(object filterInstance); 19 public abstract Task<object> ExecuteAsync(HttpControllerContext controllerContext, IDictionary<string, object> arguments, CancellationToken cancellationToken); 20 public virtual Collection<T> GetCustomAttributes<T>() where T: class; 21 public virtual Collection<FilterInfo> GetFilterPipeline(); 22 public virtual Collection<IFilter> GetFilters(); 23 public abstract Collection<HttpParameterDescriptor> GetParameters(); 24 internal static IActionResultConverter GetResultConverter(Type type); 25 private Collection<FilterInfo> InitializeFilterPipeline(); 26 private static IEnumerable<FilterInfo> RemoveDuplicates(IEnumerable<FilterInfo> filters); 27 }
我们首先看看这个此类的构造函数 protected HttpActionDescriptor();
protected HttpActionDescriptor() { this._properties = new ConcurrentDictionary<object, object>(); this._supportedHttpMethods = new Collection<HttpMethod>(); this._filterPipeline = new Lazy<Collection<FilterInfo>>(new Func<Collection<FilterInfo>>(this.InitializeFilterPipeline)); }
从上知过滤器管道的创建就是在此类的构造函数中进行。首先我们将构造函数进行搁置,我们先来了解过滤器的一些基本的信息。
过滤器接口(IFilter)
1
2
3
4
5
|
public
interface
IFilter
{
// Properties
bool
AllowMultiple {
get
; }
}
|
此接口只有一个只读属性AllowMultiple,它表示多个同类的过滤器类型是否允许指定应用到同一个目标对象上,如果允许指定,则该值为true,否则为false,默认是false。
过滤器特性(FilterAttribute)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited=
true
, AllowMultiple=
true
)]
public
abstract
class
FilterAttribute : Attribute, IFilter
{
// Fields
private
static
readonly
ConcurrentDictionary<Type,
bool
> _attributeUsageCache;
// Methods
static
FilterAttribute();
protected
FilterAttribute();
private
static
bool
AllowsMultiple(Type attributeType);
// Properties
public
virtual
bool
AllowMultiple {
get
; }
}
|
由上知,此过滤器特性类为过滤器的基类,当我们设置 AttributeUsage 中的 AllowMultiple 来指定是否允许多个特性应用到相同的对象上,同时通过其属性AllowMultiple来返回其值,当我们想要实现自定义的过滤器特性类时仅仅继承此类是不够的,因为此特性类只是特性中一个【属性】而已,而过滤器中的行为是通过IActionFilter来提供的。
过滤器行为接口(IActionFilter)
1
2
3
4
5
|
public
interface
IActionFilter : IFilter
{
// Methods
Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation);
}
|
过滤器作用域(FilterScope)
1
2
3
4
5
6
|
public
enum
FilterScope
{
Action = 20,
Controller = 10,
Global = 0
}
|