.Net Core WebAPI异常中间件未捕获ActionFilter抛出异常问题咨询
异常无法被捕获的核心原因
问题核心是ActionFilter的方法写法错误:
- 你重写的
OnActionExecuting使用了async void签名,这是异步代码的典型反模式。async void方法不会返回可被等待的Task对象,方法内抛出的异常不会沿着await调用链向上传播,而是会直接抛到当前线程池的未处理异常上下文,外层中间件的try/catch块根本无法拦截到这类逃逸的异常。
如果过滤器写法正确,异常是可以正常传播到外层全局异常中间件的。
中间件与Filter的执行顺序
ASP.NET Core的请求处理分为两层管道,执行逻辑遵循洋葱模型:
- 外层是中间件管道,执行顺序完全按照
Startup.Configure中的注册顺序,请求先进入最早注册的中间件,响应生成后再从后往前依次经过后注册的中间件返回。你注册的全局异常捕获中间件在管道最外层,理论上可以拦截所有后续注册组件抛出的、沿调用链传播的异常。 - 内层是MVC终结点内部的Filter管道,运行在
UseEndpoints注入的终结点中间件内部,请求进入阶段的执行顺序从外到内为:- 授权过滤器(Authorization Filters)
- 资源过滤器(Resource Filters)
- 动作过滤器(Action Filters,即你编写的权限校验过滤器所属类型)
- 异常过滤器(Exception Filters)
- 控制器动作方法执行
响应返回阶段会按照相反顺序依次执行上述过滤器。正常情况下,Filter管道中未被内部异常过滤器处理的异常,会向外抛出到中间件管道,被你写的全局异常中间件捕获。
修复方法
将错误的async void方法签名替换为正确的写法即可,二选一:
- 需要异步逻辑时,重写异步版本的方法,返回
Task:
public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { throw new Exception("test throw error"); await next(); }
- 无异步逻辑时,直接使用同步版本重写,不要加
async关键字:
public override void OnActionExecuting(ActionExecutingContext context) { throw new Exception("test throw error"); base.OnActionExecuting(context); }
修改后重新运行,ActionFilter抛出的异常就可以正常被全局异常中间件捕获。
内容的提问来源于stack exchange,提问作者zhenghao li
相关产品推荐
相关产品推荐

