自定义中间件中IExceptionHandlerFeature始终返回null的解决方法
IExceptionHandlerFeature 不是HttpContext默认内置的特性,ASP.NET Core只有内置的UseExceptionHandler异常处理中间件,在捕获到下游组件抛出的异常后,才会主动创建该特性实例、填充异常信息后写入HttpContext.Features集合。
你自己写的自定义异常中间件没有实现往Features集合写入这个特性的逻辑,调用Get<IExceptionHandlerFeature>()返回null是正常表现。
根据你的使用场景选下面任意一种即可:
方案1:直接使用catch块捕获的异常对象(最简单,优先用)
你在catch块里已经拿到了Exception ex实例,这个就是Action/下游中间件抛出的原始异常,包含完整的异常类型、堆栈、错误信息,完全不需要绕路从Features里取:
public async Task InvokeAsync(HttpContext httpContext) { try { await _next(httpContext); } catch (Exception ex) { // 直接操作ex即可获取所有异常信息 var exceptionType = ex.GetType(); var errorMsg = ex.Message; // 编写你的自定义异常返回逻辑,比如统一返回结构化错误 httpContext.Response.StatusCode = StatusCodes.Status500InternalServerError; httpContext.Response.ContentType = "application/json"; await httpContext.Response.WriteAsJsonAsync(new { code = 500, msg = errorMsg, data = exceptionType.Name }); } }
注意:自定义异常处理中间件必须在Program.cs中最早注册(放在路由、控制器、Swagger等所有其他中间件注册之前),否则无法捕获后续中间件抛出的异常。
方案2:手动写入IExceptionHandlerFeature特性(兼容依赖该特性的逻辑)
如果你的项目里有其他组件、后续逻辑需要从HttpContext.Features读取IExceptionHandlerFeature,可以在catch块捕获到异常后,手动实例化特性并写入Features集合:
catch (Exception ex) { var errorFeature = new ExceptionHandlerFeature { Error = ex, Path = httpContext.Request.Path.Value }; httpContext.Features.Set<IExceptionHandlerFeature>(errorFeature); // 此时再调用Get方法就能正常拿到异常实例 var error = httpContext.Features.Get<IExceptionHandlerFeature>(); // 后续处理逻辑 }
注:使用
ExceptionHandlerFeature类型需要先引入Microsoft.AspNetCore.Diagnostics命名空间。
内置UseExceptionHandler中间件之所以能正常取到值,是因为它内部的执行逻辑就是捕获异常后,先把IExceptionHandlerFeature写入Features集合,再重定向请求到你配置的错误处理端点,错误处理端点执行时自然能读到提前写入的异常数据。
内容的提问来源于stack exchange,提问作者snDev

