跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

c#如何使用过滤器Filter_c#过滤器Filter深入理解与底层原理

FilterAttribute 是标记接口 IFilterMetadata,其行为由 ActionFilterAttribute 等具体实现类决定,ASP.NET Core 按固定顺序调用其生命周期方法;ServiceFilter 要求类型已注册到 DI 容器;异步过滤器中需 await next() 后才能安全访问 ActionArguments;全局过滤器可能因 IgnoreFilter、提前设置 context.Result 或未启用 MVC 服务而失效。 FilterAttribute 是什么,它在 ASP.NET Core 请求管道中起什么作用 FilterAttribute 不是中间件,也不是 Action 执行前的“钩子函数”,而是一个标记接口(
IFilterMetadata
),它的实际行为由实现类决定。真正起作用的是继承自
ActionFilterAttribute
、
ExceptionFilterAttribute
等的具体过滤器类型。ASP.NET Core 在 Action 执行前后按固定顺序调用它们的生命周期方法,比如
OnActionExecuting
、
OnActionExecuted
。 你写一个类继承
ActionFilterAttribute
并打上
[MyFilter]
标签,框架才会在匹配的 Action 上自动注入并执行——不是靠反射扫描类名,而是靠依赖注入容器 + 过滤器注册机制协同完成。 为什么 [ServiceFilter(typeof(MyFilter))] 有时不生效 常见原因是
MyFilter
没有注册到 DI 容器。ServiceFilter 要求目标类型必须是服务注册过的(Scoped/Transient/Singleton),否则运行时报
InvalidOperationException: No service for type 'MyFilter' has been registered.
必须在
Program.cs
中显式注册:
builder.Services.AddScoped();
[ServiceFilter]
不支持构造函数带非服务参数(如
public MyFilter(string key)
会失败) 若想传参,改用
[TypeFilter(typeof(MyFilter), Arguments = new object[] { "abc" })]
,但此时
MyFilter
必须有对应构造函数且参数类型能被 DI 解析 AsyncFilter 和普通 Filter 的执行顺序差异在哪 ASP.NET Core 5+ 推荐使用
IAsyncActionFilter
替代同步版,因为所有内置过滤器都已异步化。关键区别在于:同步过滤器的
OnActionExecuting
执行完后,才调用
context.ActionArguments
;而异步过滤器中,
await next();
才真正进入 Action,此前
ActionArguments
已可读取且不可变。 C知道 CSDN推出的一款AI技术问答工具 下载 错误写法示例:
public class BadAsyncFilter : IAsyncActionFilter { public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { // ❌ 这里 context.ActionArguments 可能为 null 或未绑定完成 if (context.ActionArguments.TryGetValue("id", out var id)) { ... } await next(); // ✅ 此时模型绑定已完成,参数才可靠 } }
全局 Filter 注册后,为什么某些 Controller 不触发 全局过滤器默认作用于所有 Action,但会被以下方式绕过: Controller 上标注了
[IgnoreFilter]
(需自定义该特性并实现
IFilterFactory
或继承
ActionFilterAttribute
重写
IsReusable
) Action 方法本身加了
[ServiceFilter(typeof(MyFilter), IsReusable = false)]
,且该实例未被复用 过滤器实现中调用了
context.Result = new EmptyResult();
提前终止流程,后续过滤器和 Action 都不会执行 控制器继承自
ControllerBase
但没启用 MVC 服务(比如只注册了
AddControllersWithViews()
却在 Minimal API 模式下跑) 调试建议:在
OnActionExecuting
里加日志,确认是否进得去;再检查
context.Filters
列表长度,看全局 Filter 是否真被注入进来。

相关文章