ASP.NET Core 2.0 MVC:结合依赖注入用IControllerModelConvention配置授权过滤器
没问题,这个需求在ASP.NET Core 2.0 MVC里完全可以通过IControllerModelConvention结合依赖注入优雅实现,我给你一步步捋清楚:
1. 先定义支持依赖注入的授权过滤器
首先你需要把两种授权过滤器定义成支持构造函数注入的类型,这样它们就能获取到你需要的依赖服务了。比如:
// 给Identity前缀控制器用的专属授权过滤器 public class IdentityAuthorizeFilter : IAuthorizationFilter { private readonly IIdentityAuthService _identityAuthService; // 通过构造函数注入依赖的服务 public IdentityAuthorizeFilter(IIdentityAuthService identityAuthService) { _identityAuthService = identityAuthService; } public void OnAuthorization(AuthorizationFilterContext context) { // 在这里实现你的Identity专属授权逻辑 // 比如验证特定的身份凭证、权限规则等 } } // 给其余控制器用的默认授权过滤器 public class DefaultAuthorizeFilter : IAuthorizationFilter { private readonly IDefaultAuthService _defaultAuthService; public DefaultAuthorizeFilter(IDefaultAuthService defaultAuthService) { _defaultAuthService = defaultAuthService; } public void OnAuthorization(AuthorizationFilterContext context) { // 在这里实现通用的授权逻辑 } }
2. 实现自定义的IControllerModelConvention
接下来创建一个自定义的约定类,用来根据控制器名称前缀批量添加对应的授权过滤器。这里关键是用ServiceFilterAttribute,它能让MVC自动从依赖注入容器中解析过滤器实例,而不是手动new(手动new的话没法注入依赖):
public class ControllerAuthorizationConvention : IControllerModelConvention { public void Apply(ControllerModel controllerModel) { // 判断控制器名称是否以"Identity"开头(忽略大小写,你可以根据实际需求调整) if (controllerModel.ControllerName.StartsWith("Identity", StringComparison.OrdinalIgnoreCase)) { // 添加Identity专属过滤器,用ServiceFilter让DI容器解析实例 controllerModel.Filters.Add(new ServiceFilterAttribute(typeof(IdentityAuthorizeFilter))); } else { // 添加默认授权过滤器 controllerModel.Filters.Add(new ServiceFilterAttribute(typeof(DefaultAuthorizeFilter))); } } }
3. 在Startup中注册服务和约定
最后在Startup.cs的ConfigureServices方法里,把过滤器和约定都注册到DI容器和MVC配置中:
public void ConfigureServices(IServiceCollection services) { // 把两个授权过滤器注册为Scoped服务(也可以根据需求用Transient/Singleton) services.AddScoped<IdentityAuthorizeFilter>(); services.AddScoped<DefaultAuthorizeFilter>(); // 注册自定义的控制器约定到MVC选项中 services.AddMvc(options => { options.Conventions.Add(new ControllerAuthorizationConvention()); }); // 别忘了注册过滤器依赖的其他服务(比如上面示例中的IIdentityAuthService) services.AddScoped<IIdentityAuthService, IdentityAuthService>(); services.AddScoped<IDefaultAuthService, DefaultAuthService>(); }
关键说明
- 使用
ServiceFilterAttribute是核心:它会告知MVC从DI容器中获取指定类型的过滤器实例,这样过滤器构造函数中的依赖就能被正确注入。如果直接new过滤器对象,依赖注入就失效了。 - 控制器名称判断:这里是基于控制器类的名称(比如
IdentityUserController的ControllerName是IdentityUser),如果你的需求是基于路由前缀而不是控制器名称,可以修改Apply方法里的判断逻辑,比如检查controllerModel.Selectors中的路由模板。
内容的提问来源于stack exchange,提问作者darrunategui
相关产品推荐
相关产品推荐

