asp.net core MVC 過濾器會在請求管道的各個階段觸發。同一階段又可以注冊多個范圍的過濾器,例如Global范圍,controller范圍等。以ActionFilter為例,我們來看看過濾器的觸發順序。
過濾器可注冊范圍
- 全局:將作用於所有請求的action
- controller:將作用於這個controller下的所有action
- action:作用於單個action
定義過濾器
全局
public class GlobalActionFilter : IAsyncActionFilter { public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { var factory = context.HttpContext.RequestServices.GetService<ILoggerFactory>(); var logger = factory.CreateLogger<GlobalActionFilter>(); logger.LogWarning("全局ActionFilter執行之前"); await next(); logger.LogWarning("全局ActionFilter執行之后"); } }
controller(分為注解方式和重寫方式)
注解方式:
public class ControllerActionFilter : ActionFilterAttribute { public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { var factory = context.HttpContext.RequestServices.GetService<ILoggerFactory>(); var logger = factory.CreateLogger<GlobalActionFilter>(); logger.LogWarning("ControllerActionFilter執行之前"); await next(); logger.LogWarning("ControllerActionFilter執行之后"); } }
重寫方式(在controller內重寫OnActionExecutionAsync)
public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { var logger = _factory.CreateLogger<ValuesController>(); logger.LogWarning("Controller內部重寫的actionFinter執行前"); await next(); logger.LogWarning("Controller內部重寫的actionFinter執行后"); }
應用過濾器
全局(在Startup中修改)
public void ConfigureServices(IServiceCollection services) { services.AddMvc(o => { o.Filters.Add<GlobalActionFilter>(); }); }
controller(重寫方式直接可用不用操作)
[ControllerActionFilter] public class ValuesController : Controller
Action
[HttpGet] [ActionActionFilter] public IEnumerable<string> Get()
執行結果
從結果可以看出,Controller重寫 > 全局 > Controller > Action
自定義過濾器執行順序
過濾器的執行順序不是一成不變的,aspNet Core 通過靈活的設計讓我們可以手動自定義過濾器的執行順序。要實現自定義過濾器執行順序則需要實現IOrderedFilter接口,該接口定義一個int類型的Order屬性,這個屬性越大則執行順序越滯后。
實現IOrderedFilter接口
public class GlobalActionFilter : IAsyncActionFilter,IOrderedFilter { public int Order => 0;
繼承Attribute方式直接傳入參數
[ControllerActionFilter(Order =-1)] public class ValuesController : Controller {
[HttpGet] [ActionActionFilter(Order =-2)] public IEnumerable<string> Get() {
結果
此時的執行順序:controller內部重寫 > Action > controller > global