ASP.NET Core 2.0自定义IFilterProvider过滤器属性未执行问题
我之前在实现类似条件过滤器提供者的时候也踩过一模一样的坑,给你几个关键的排查和修复方向:
1. 确保你的IFilterProvider被正确加入到MvcOptions的FilterProviders集合
仅仅把你的Provider注册为单例服务是不够的——ASP.NET Core MVC不会自动发现所有注册的IFilterProvider实例,你需要手动把它加入到MvcOptions.FilterProviders中:
public void ConfigureServices(IServiceCollection services) { // 注册你的过滤器提供者为单例 services.AddSingleton<MyConditionalFilterProvider>(); services.AddMvc(options => { // 从服务容器中获取实例并添加到FilterProviders集合 var provider = services.BuildServiceProvider().GetService<MyConditionalFilterProvider>(); options.FilterProviders.Add(provider); }); }
如果没做这一步,你的Provider的GetFilters方法根本不会被调用,自然只会看到默认提供者的逻辑在运行。
2. 检查GetFilters方法是否正确处理IFilterFactory类型的属性
TypeFilterAttribute本质是一个IFilterFactory,它本身不是实际的过滤器,而是负责创建过滤器实例的工厂。你的条件提供者需要识别这类属性,解析出实际的过滤器后再应用条件判断:
public IEnumerable<FilterItem> GetFilters(FilterProviderContext context) { foreach (var item in context.Results.ToList()) { // 检查是否是FilterFactory类型的包装属性 if (item.Filter is IFilterFactory factory) { // 创建实际的过滤器实例 var actualFilter = factory.CreateInstance(context.ActionContext.HttpContext.RequestServices); // 这里加入你的条件判断逻辑,比如是否要保留这个过滤器 if (!ShouldApplyFilter(actualFilter, context)) { context.Results.Remove(item); } } else { // 处理静态过滤器属性的逻辑(你已经能正常工作的部分) if (!ShouldApplyFilter(item.Filter, context)) { context.Results.Remove(item); } } } return Enumerable.Empty<FilterItem>(); }
如果跳过了对IFilterFactory的解析,你的条件判断只会作用于TypeFilterAttribute本身,而不会影响它创建的实际过滤器,导致过滤器依然会执行(或者你误以为没执行)。
3. 确认Provider的Order属性设置合理
IFilterProvider有一个Order属性,决定了提供者的执行顺序。默认的过滤器提供者(比如DefaultFilterProvider)的Order是0。如果你的Provider Order设置得比默认值大,它会在默认提供者之后执行,这样你才能修改默认提供者已经收集到的过滤器结果;如果Order更小,你处理的时候默认提供者还没收集到TypeFilter的实际过滤器,自然看不到效果。
可以在你的Provider类里设置:
public int Order => 1; // 确保在默认提供者之后执行
4. 调试时重点关注GetFilters方法的执行
你提到调试时只看到OnProvidersExecuting运行,那一定要确认你的GetFilters方法有没有被触发。如果没触发,那肯定是第一步的注册有问题;如果触发了,就一步步看是否正确识别了TypeFilterAttribute,是否正确应用了条件判断,有没有从context.Results中移除不需要的过滤器。
内容的提问来源于stack exchange,提问作者huxelot

