.NET 6中如何从ExceptionFilterAttribute获取Controller实例
.NET 6中ExceptionFilterAttribute获取控制器实例的方法
我正在将一个.NET Framework 4.7.2项目迁移至.NET 6。原项目通过ExceptionFilterAttribute调用抛出异常的控制器上的方法,目前仅需先完成迁移,后续再做重构优化。
原.NET Framework中的代码逻辑是通过HttpActionExecutedContext获取控制器实例,转换为ILoggingController后调用指定方法:
public override void OnException(HttpActionExecutedContext actionExecutedContext) { LoggingController = actionExecutedContext.ActionContext.ControllerContext.Controller as ILoggingController; if (LoggingController == null) { throw new InvalidOperationException($"{GetType().Name} can only be used on controllers that implement ILoggingController"); } LoggingController.MethodToCall(); // 其他逻辑 }
迁移到.NET 6后,原获取控制器实例的方式失效,当前代码只能拿到ControllerActionDescriptor,不清楚如何获取实际的控制器实例:
using Microsoft.AspNetCore.Mvc.Filters; public class ExcFilterAttribute : ExceptionFilterAttribute { public override void OnException(ExceptionContext context) { var controller = context.ControllerContext.Controller; // 无法正常工作 var endpoint = context.HttpContext.GetEndpoint(); var controllerActionDescriptor = endpoint?.Metadata.GetMetadata<ControllerActionDescriptor>(); base.OnException(context); } }
解决方案
在.NET 6的ExceptionContext中,控制器实例直接存储在context.Controller属性中,不需要通过ControllerContext间接获取。修正后的代码如下:
using Microsoft.AspNetCore.Mvc.Filters; public class ExcFilterAttribute : ExceptionFilterAttribute { public override void OnException(ExceptionContext context) { // 直接从context获取控制器实例 var loggingController = context.Controller as ILoggingController; if (loggingController == null) { throw new InvalidOperationException($"{GetType().Name} can only be used on controllers that implement ILoggingController"); } // 调用控制器上的方法 loggingController.MethodToCall(); // 保留基础异常处理逻辑 base.OnException(context); } }
说明
- .NET Core/.NET 6的
ExceptionContext提供了直接的Controller属性,对应当前执行的控制器实例 - 类型转换逻辑和原项目保持一致,确保只有实现了
ILoggingController的控制器才能使用该过滤器 - 若不需要额外元数据(如控制器/方法名称),无需通过
HttpContext.GetEndpoint()获取ControllerActionDescriptor
内容的提问来源于stack exchange,提问作者I Bowyer
相关产品推荐
相关产品推荐

