Fork me on GitHub

解说asp.net core MVC 过滤器的执行顺序

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

 

posted @ 2017-08-30 11:33  huanent  阅读(5159)  评论(2编辑  收藏  举报