.NET中如何获取控制器方法上已应用的UserAuthFilter实例?
问题描述
我定义了如下自定义过滤器:
public class UserAuthFilter : ActionFilterAttribute, IActionFilter { public bool AllowAnonymous { get; set; } = false; public string Name { get; set; }; public UserAuthFilter(bool allowAnonymous = false, string name = "") { this.AllowAnonymous = allowAnonymous; this.Name = name; } public async override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { // some actions await next(); } }
并将其应用在控制器的方法上:
[HttpPost] [UserAuthFilter] public async Task<IActionResult> Create(CreateDataRequest request) { // // 此处希望获取当前应用的UserAuthFilter实例 // return service.Create(request); }
请问是否可以在上述注释位置获取到已应用的过滤器实例?我曾尝试将属性设为静态变量,通过UserAuthFilter.AllowAnonymous静态访问,但该方案并不合适。
解决方案
可以获取到,推荐两种可靠的实现方式:
方式一:通过HttpContext传递过滤器实例
修改过滤器的OnActionExecutionAsync方法,将当前实例存入请求的HttpContext.Items集合,控制器方法即可直接读取:
public async override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { // 将当前过滤器实例存入HttpContext context.HttpContext.Items["CurrentUserAuthFilter"] = this; await next(); }
控制器方法中读取:
[HttpPost] [UserAuthFilter] public async Task<IActionResult> Create(CreateDataRequest request) { if (HttpContext.Items.TryGetValue("CurrentUserAuthFilter", out var filterObj) && filterObj is UserAuthFilter filter) { // 成功获取当前过滤器实例,可访问其属性 var isAllowAnonymous = filter.AllowAnonymous; var filterName = filter.Name; } return service.Create(request); }
方式二:从ActionDescriptor中筛选过滤器实例
通过ControllerContext获取当前Action的描述符,从中筛选出目标过滤器实例:
[HttpPost] [UserAuthFilter] public async Task<IActionResult> Create(CreateDataRequest request) { var filter = ControllerContext.ActionDescriptor.FilterDescriptors .Select(descriptor => descriptor.Filter) .OfType<UserAuthFilter>() .FirstOrDefault(); if (filter != null) { // 成功获取过滤器实例 var filterName = filter.Name; } return service.Create(request); }
关键说明
- 方式一能确保拿到当前请求对应的过滤器实例,因为默认情况下
ActionFilterAttribute会为每个请求创建新实例(除非配置了复用策略); - 方式二若过滤器应用在控制器级别,需扩展筛选逻辑,同时检查控制器的过滤器集合;
- 静态变量方案不可取,全局共享的静态变量会在多请求并发时出现数据错乱问题。
内容的提问来源于stack exchange,提问作者honneq
相关产品推荐
相关产品推荐

