过滤器执行顺序由order值和类型共同决定,同类型默认order=0时后注册的先执行;iauthorizationfilter始终最先运行且可短路后续流程;异步过滤器优先于同步过滤器,且不可混写。

过滤器执行顺序不是靠 Add<t>()</t> 调用先后决定的,而是由 Order 值 + 过滤器类型双重控制;不显式设 Order,同类型过滤器默认都是 0,后注册的反而先执行。
为什么 Add<logfilter>()</logfilter> 和 Add<authfilter>()</authfilter> 的顺序 ≠ 执行顺序
因为 FilterCollection.Add<t>()</t> 内部会给每个过滤器分配默认 Order = 0。当多个同类型过滤器(比如都是 IActionFilter)的 Order 相同时,ASP.NET Core 按“后添加、先执行”处理 —— 这是为支持外层包装逻辑(如日志要包住业务)设计的逆序机制。
- 不设
Order:options.Filters.Add<logfilter>(); options.Filters.Add<authfilter>();</authfilter></logfilter>→AuthFilter.OnActionExecuting先跑,LogFilter.OnActionExecuting后跑 - 想让日志在外层:必须显式指定
Order,例如options.Filters.Add<logfilter>(10); options.Filters.Add<authfilter>(20);</authfilter></logfilter> -
Order只在同类型内比较:一个IAuthorizationFilter(默认Order = -1)永远比IActionFilter(哪怕Order = -100)先执行
全局 / 控制器 / Action 三级过滤器混用时怎么排顺序
三者作用域不同,但同类型过滤器仍受 Order 控制;且特性(Attribute)注册的过滤器默认 Order = -1,天然高于全局注册的同类型过滤器(默认 Order = 0)。
- 控制器上加
[ServiceFilter(typeof(CacheFilter))]→ 默认Order = -1 - 全局注册
options.Filters.Add<logfilter>()</logfilter>→ 默认Order = 0 - 结果:控制器级
CacheFilter.OnActionExecuting在全局LogFilter.OnActionExecuting之前执行 - 若想强制全局日志最外层:给它设
Order = -2,控制器级设Order = -1,Action 级设Order = 0
IAuthorizationFilter 总是第一个,但它能短路后续所有过滤器
授权过滤器在管道最前端运行,一旦调用 context.Result = new UnauthorizedResult() 或抛出异常,整个后续流程(资源、模型绑定、动作、结果过滤器)全部跳过,直接生成响应。
- 它不参与
Order排序竞争,只分“有没有”和“是否短路” - 不要在
IAuthorizationFilter里做耗时操作(如远程鉴权),否则所有请求都卡在这一步 - 如果需要缓存授权结果,建议用
IResourceFilter+OnResourceExecuting阶段介入,在模型绑定前拦截并复用
异步过滤器优先于同步过滤器,且不能混写
一个类如果同时实现了 IAsyncActionFilter 和 IActionFilter,ASP.NET Core 只会调用异步方法(OnActionExecutionAsync),完全忽略同步方法(OnActionExecuting / OnActionExecuted)。
- 别为了“兼容旧代码”在一个类里同时实现两套接口
- 异步方法里必须 await
next(),否则OnActionExecutionAsync会提前返回,导致 action 不执行 - 同步过滤器性能开销小,适合轻量逻辑(如打点);异步过滤器适合 IO 密集场景(如调外部 API、查 Redis)
真正容易被忽略的是:跨类型过滤器之间没有 Order 可比性,而同类型内又默认全为 0 —— 所以只要用了两个以上同类型全局过滤器,就必须显式设 Order,否则执行顺序是反直觉的“后添加先执行”。











