如何在ASP.NET Core中从ConfigureApplicationPartManager移除单个控制器
如何在ASP.NET Core MVC中移除单个控制器并通过配置控制可用控制器
当然可以仅移除单个控制器,甚至能通过配置文件灵活控制类库中哪些MVC控制器可用,以下是具体实现方案:
1. 配置文件定义允许的控制器
在appsettings.json中添加配置项,指定允许启用的控制器全名(含命名空间):
{ "AllowedControllers": [ "YourLibrary.Controllers.HomeController", "YourLibrary.Controllers.Api.UserController" ] }
2. 实现配置驱动的控制器过滤
根据你的.NET版本,在启动逻辑中拦截MVC的控制器加载过程,结合配置筛选控制器:
.NET 6+ 示例(替换默认特性提供器)
这种方式更灵活,能完全控制哪些类型被识别为控制器:
var builder = WebApplication.CreateBuilder(args); // 读取配置中的允许列表 var allowedControllers = builder.Configuration.GetSection("AllowedControllers").Get<string[]>(); builder.Services.AddControllers() .ConfigureApplicationPartManager(apm => { // 移除默认的控制器特性提供器,替换为自定义实现 var defaultProvider = apm.FeatureProviders.OfType<ControllerFeatureProvider>().First(); apm.FeatureProviders.Remove(defaultProvider); apm.FeatureProviders.Add(new ConfigurableControllerFeatureProvider(allowedControllers)); }); var app = builder.Build(); // 中间件配置... app.Run(); // 自定义控制器特性提供器 public class ConfigurableControllerFeatureProvider : ControllerFeatureProvider { private readonly HashSet<string> _allowedControllers; public ConfigurableControllerFeatureProvider(string[] allowedControllers) { _allowedControllers = new HashSet<string>(allowedControllers ?? Array.Empty<string>(), StringComparer.OrdinalIgnoreCase); } protected override bool IsController(TypeInfo typeInfo) { // 先判断是否符合控制器的基础条件 if (!base.IsController(typeInfo)) return false; // 允许列表为空时默认启用所有控制器,否则仅保留列表内的 if (_allowedControllers.Count == 0) return true; return _allowedControllers.Contains(typeInfo.FullName); } }
简化方案:直接过滤已加载的控制器集合
如果不想替换整个特性提供器,也可以在控制器特性注册后直接修改集合:
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers() .ConfigureApplicationPartManager(apm => { apm.FeatureRegistered += (feature) => { if (feature is ControllerFeature controllerFeature) { var allowedControllers = builder.Configuration.GetSection("AllowedControllers").Get<string[]>(); if (allowedControllers?.Any() == true) { var allowedSet = new HashSet<string>(allowedControllers, StringComparer.OrdinalIgnoreCase); // 移除不在允许列表中的控制器 controllerFeature.Controllers.RemoveAll(ctrl => !allowedSet.Contains(ctrl.FullName)); } } }; }); // 后续启动逻辑...
关键注意事项
- 必须使用控制器的完整命名空间+类名,避免不同命名空间下的同名控制器被误过滤
- 建议保留“允许列表为空时启用所有控制器”的逻辑,防止配置错误导致无控制器可用
- 这种过滤是在MVC加载控制器的早期阶段完成,性能开销极低,比运行时拦截(如ActionFilter)更高效
内容的提问来源于stack exchange,提问作者tris
相关产品推荐
相关产品推荐

