[转载]ASP.NET WebAPI 13 Filter - Barlow Du - 博客园

来源: [转载]ASP.NET WebAPI 13 Filter – Barlow Du – 博客园

Filter(筛选器)是基于AOP(面向方面编程)的设计,它的作用是Actionr的执行注入额外的逻辑,以达到横切注入的目的。

 

IFilter

在WebAPI中所以的Filter都实现了IFilter接口 ,IFilter接口只有一个只读属性AllowMultiple,它表示同类的Filter是否可以应用到同一目标对象上。

 

 

1
2
3
4
5
6
7
public interface IFilter
{
bool AllowMultiple { get; }
 }

 

 

 

 

FilterInfo

在HttpActionDescriptor与HttpControllerDescriptor中也存储了Action使用到的Filter。但 它不是直接以IFilter的形式进行存储,也是以FilterInfo(System.Web.Http.Filters)。

 

1
2
3
4
5
6
7
8
9
10
11
public sealed class FilterInfo
 {
public FilterInfo(IFilter instance, FilterScope scope);
public IFilter Instance { get; }
public FilterScope Scope { get; }
 }

 

 

 

在FilterInfo中有两个属性:Instance,Scope。其中Instance是IFilter对象。在实际对Filter运用中我们应该注意并发的情况,因为对于同一个Filter调用的都是同一个Filter对象。

 

 

 

FilterScope

 

对于FilterInfo类的Scope属性,它表示Filter的域。在WebAPI中Filter有3个域:Global,Controller,Action。

 

1
2
3
4
5
6
7
8
9
10
11
public enum FilterScope
 {
 Global = 0,
 Controller = 10,
 Action = 20,
 }

 

 

 

对于Controller,Action的Filter添加都是采用特性(Attribute)的方式。对于全局Filter是添加在HttpConfiguration的Filter。

 

 

 

FilterProvider

WebAPI提供了IFilterProvider(System.Web.Http.Filters)用于提供不同域下的Filter。

 

1
2
3
4
5
6
7
public interface IFilterProvider
{
IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor);
 }

 

 

 

在WebAPI中FilterProvider也是”标准化组件”,但是它是以multi的形式注入的.WebAPI中IFilter有两个默认实 现: ConfigurationFilterProvider, ActionDescriptorFilterProvider,从命名上我们就可以知道前者是提供全局Filter,后者是提供 Controller,Action的Filter。

 

 

 

 

5类Filter

WebAPI为我们定义了5类Filter。分别如下:

AuthenticationFilter:用于请求认证(IAuthenticationFilter)。

AuthorizationFilter:用于请求授权(IAuthorizationFilter)。

ActionFilter:ActionFilter:注册的操作会在Action执行的前后被调用(IActionFilter)。

ExceptionFilter:当目标Action抛出异常是调用(IExceptionFilter)。

OverrideFilter:用于屏蔽当前域之前的Filter(IOverrideFilter)。

 

本文重点讲后三类Filter,对于前两类,后续再做跟进。对于后三类Filter默认实现是ActionFilterAttribute,ExceptionFilterAttribute,OverrideActionFiltersAttribute。如下:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IFilter
 {
protected ActionFilterAttribute();
public virtual void OnActionExecuted(HttpActionExecutedContext actionExecutedContext);
public virtual Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken);
public virtual void OnActionExecuting(HttpActionContext actionContext);
public virtual Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken);
 }

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public abstract class ExceptionFilterAttribute : FilterAttribute, IExceptionFilter, IFilter
 {
protected ExceptionFilterAttribute();
public virtual void OnException(HttpActionExecutedContext actionExecutedContext);
public virtual Task OnExceptionAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken);
 }

 

 

1
2
3
4
5
6
7
8
9
10
11
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public sealed class OverrideActionFiltersAttribute : Attribute, IOverrideFilter, IFilter
 {
public OverrideActionFiltersAttribute();
public Type FiltersToOverride { get; }
 }

 

 

 

 

 

 

唯一性

因为Filter有三个域,那么在采用特性标示的方式注入Filter的,必定有可能会对同一个Action上注入多个相同的Filter。显然在 使用中一般不会允许这种情况发生。WebAPI中提供了相应的策略用来保证Filter的唯一性。即对FilterAttribute添加 AttributeUsage特性,并将AllowMultiple设置为false.

当然这个设置过后你会发现在三个域上我还是可以添加相同的Filter,那么这个时候WebAPI会为我们筛选出一个Filter去调用。筛选规则如下:

Action>Controller>Global

即FilterScope的值越大,优先级超高。

 

 

ActionFilter

ActionFilterAttribute提供了4个虚方法: OnActionExecuted,OnActionExecutedAsync,OnActionExecuting,OnActionExecutingAsync 其实两个异步方法只是对两个同步的方法的封装,所以我们一般只重写两个同步方法。

 

 

在执行顺序上ActionFilter的规则是:

  1. 不同域:Global>ControllerAction
  2. 相同域:按照注入顺序执行

 

在执行OnActionExecuting的过程中如果给actionContext.Response赋值,那么Filter管道就会做返回处理,不再去做后续操作。

 

 

ExceptionFilter

在执行Action与整个ActionFilter管道中,如果抛出异常,

 

  1. ExpceptionFilter的执行顺序与ActionFilter正好相反
  2. ExceptionFilter管道处理的是整个ActionFilter管道抛出的异常,并不是单纯的Action抛出的异常
  3. 如果在ExceptionFilter管道中抛出异常,那么该ExceptionFilter都不会执行。

 

源码

 

Github: https://github.com/BarlowDu/WebAPI (API_13)

 

OverrideFilter

一个Action的所有Filter是Global,Controller,Action三个域下的Filter的总合,但有些时候我们并想要上一 级域的Filter这个时候就需要用到OverrideFilter。WebAPI的OverrideActionFiltersAttribute只会 屏蔽IActionFilter,并不会对其它的Filter进行屏蔽。

赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏