ASP.NET WebAPI 13 Filter


Filter(篩選器)是基於AOP(面向方面編程)的設計,它的作用是Actionr的執行注入額外的邏輯,以達到橫切注入的目的。

 

IFilter

在WebAPI中所以的Filter都實現了IFilter接口 ,IFilter接口只有一個只讀屬性AllowMultiple,它表示同類的Filter是否可以應用到同一目標對象上。

 

 

public interface IFilter

{ 

bool AllowMultiple { get; } 

 }

 

 

 

 

FilterInfo

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

 

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。

 

public enum FilterScope

 { 

 Global = 0, 

 Controller = 10, 

 Action = 20, 

 }

 

 

 

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

 

 

 

FilterProvider

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

 

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,OverrideActionFilterAttribute。如下:

 

[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); 

 }

 

 

 

[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); 

 }

 

 

[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都不會執行。

 

 

OverrideFilter

一個Action的所有Filter是Global,Controller,Action三個域下的Filter的總合,但有些時候我們並想要上一級域的Filter這個時候就需要用到OverrideFilter。WebAPI的OverrideActionFiltersAttribute只會屏蔽IActionFilter,並不會對其它的Filter進行屏蔽。

 

源碼

 

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM