使用ControllerFeatureProvider禁用特定ASP.NET Core控制器时意外禁用全部控制器的问题排查
我来帮你排查这个问题!首先看你的自定义ControllerFeatureProvider的注册方式——你是用Add把它追加到了FeatureProviders列表里,但默认的ControllerFeatureProvider还在列表中,这就会导致关键问题,再结合路由配置的细节,我们一步步解决:
默认的ControllerFeatureProvider会先扫描所有符合条件的控制器(包括AdminController和JsonController),并把它们都添加到ControllerFeature中。而你的自定义Provider只是不会重复添加控制器,但无法移除默认Provider已经添加的项。同时路由配置的细节也可能导致你误以为控制器被禁用。
1. 替换默认的ControllerFeatureProvider(核心修复)
要真正过滤掉AdminController,你需要替换掉默认的Provider,而不是添加新的。修改你的AddControllers配置:
services.AddControllers() .ConfigureApplicationPartManager(manager => { // 移除默认的ControllerFeatureProvider var defaultProvider = manager.FeatureProviders.FirstOrDefault(f => f is ControllerFeatureProvider); if (defaultProvider != null) { manager.FeatureProviders.Remove(defaultProvider); } // 添加我们自定义的Provider manager.FeatureProviders.Add(new CustomControllerFeatureProvider()); }) // 其他原有配置保持不变...
这样就只有你的自定义Provider来决定哪些类型是控制器,确保AdminController被排除,JsonController被保留。
2. 检查路由与控制器Action的配置
你提到两个控制器都无法访问,除了Provider的问题,还要确认路由是否正确:
- 对于
JsonController:你的路由模板是pattern: "json",但只指定了controller = "json",如果Action没有路由属性,访问/json会返回404。可以给控制器或Action添加路由标记:[Route("json")] public class JsonController : ControllerBase { [HttpGet] public IActionResult GetData() { return Ok(new { message = "Hello from JsonController" }); } } - 对于保留
AdminController的实例:确保它有对应的路由配置,比如添加[Route("admin")]属性,或者在UseEndpoints中补充对应的路由模板。
3. 验证IsController逻辑(可选但建议)
虽然你说已经确认返回值正确,但可以加日志再次验证,确保过滤逻辑生效:
protected override bool IsController(TypeInfo typeInfo) { var baseResult = base.IsController(typeInfo); if (baseResult) { var isAllowed = typeInfo.Name != nameof(AdminController); // 用日志框架记录:$"检查控制器 {typeInfo.Name} => 是否允许:{isAllowed}" return isAllowed; } return false; }
如果你的自定义Provider是添加而非替换,理论上默认Provider已经把两个控制器都加入到Feature中,不应该都无法访问。除非你的base.IsController对两个控制器都返回了false——比如控制器是抽象类、静态类,或者类名未以Controller结尾(但你说JsonController继承自ControllerBase,应该符合条件)。替换默认Provider后,就能确保只有你的逻辑在生效,避免冲突。
内容的提问来源于stack exchange,提问作者James

