如何在ApiController子类与ExceptionFilterAttribute子类间共享会话变量
解决异常过滤器中获取TokenUser的问题
当然可以!在ASP.NET Web API里,有几种简单的方法能让你的ErrorLogService异常过滤器拿到每个会话的TokenUser对象,下面给你详细讲讲两种常用方案:
方案一:从过滤器上下文获取控制器实例访问TokenUser
你的ErrorLogService继承自ExceptionFilterAttribute,它的OnException方法会接收到HttpActionExecutedContext参数——这个参数就是连接过滤器和当前请求控制器的关键。通过它你可以直接拿到当前请求对应的控制器对象,进而访问TokenUser:
public class ErrorLogService : ExceptionFilterAttribute { public override void OnException(HttpActionExecutedContext context) { // 将上下文的控制器转换为你的目标控制器类型(比如SomeController) var targetController = context.ActionContext.ControllerContext.Controller as SomeController; if (targetController != null) { var tokenUser = targetController.TokenUser; // 现在你可以用tokenUser做日志记录等操作了 } // 记得调用基类方法,保证默认的异常处理逻辑正常执行 base.OnException(context); } }
如果TokenUser是定义在自定义的ApiController基类(比如BaseApiController : ApiController)里,转换成这个基类会更通用,避免和具体的SomeController耦合:
var baseController = context.ActionContext.ControllerContext.Controller as BaseApiController; if (baseController != null) { var tokenUser = baseController.TokenUser; // 你的业务逻辑 }
方案二:将TokenUser存入请求上下文的Properties字典
这种方式更解耦,不需要依赖控制器类型。你可以在ApiController的初始化阶段,把TokenUser存入HttpRequestMessage的Properties集合中,让过滤器直接从请求上下文读取:
首先在你的控制器(或基类控制器)中添加初始化逻辑:
public class SomeController : ApiController { protected override void Initialize(HttpControllerContext controllerContext) { base.Initialize(controllerContext); // 假设你已经获取到TokenUser实例 var tokenUser = TokenUser; // 用一个常量键存入请求Properties,避免硬编码出错 controllerContext.Request.Properties["CurrentTokenUser"] = tokenUser; } // 你的其他控制器方法... }
然后在ErrorLogService中直接读取:
public class ErrorLogService : ExceptionFilterAttribute { private const string TokenUserKey = "CurrentTokenUser"; public override void OnException(HttpActionExecutedContext context) { if (context.Request.Properties.TryGetValue(TokenUserKey, out var tokenUserObj) && tokenUserObj is TokenUser tokenUser) { // 正常使用tokenUser对象 } base.OnException(context); } }
小提示
- 方案一简单直接,但如果
TokenUser是具体控制器的属性,会存在一定耦合;方案二更灵活,适合多控制器共享的场景。 - 一定要确保
TokenUser在过滤器执行前已经完成初始化(比如在控制器Initialize方法、授权过滤器中赋值),避免拿到null。
内容的提问来源于stack exchange,提问作者Benjamin RD
相关产品推荐
相关产品推荐

