【踩坑】.NET 8.0 自定义IExceptionHandler不生效
中间件实现异常处理
在ASP.NET Core里,我们可以使用中间件(Middleware)实现全局的异常处理。 如内置的异常处理中间件 UseExceptionHandler
app.UseExceptionHandler(appError => { appError.Run(async context => { context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; context.Response.ContentType = "application/json"; var contextFeature = context.Features.Get<IExceptionHandlerFeature>(); if (contextFeature != null) { logger.LogError($"Something went wrong: {contextFeature.Error}"); await context.Response.WriteAsync(new ErrorDetails() { StatusCode = context.Response.StatusCode, Message = "Internal Server Error." }.ToString()); } }); });
或者如下干脆完全自定义一个中间件
public class ExceptionMiddleware { private readonly RequestDelegate _next; private readonly ILoggerManager _logger; public ExceptionMiddleware(RequestDelegate next, ILoggerManager logger) { _logger = logger; _next = next; } public async Task InvokeAsync(HttpContext httpContext) { try { await _next(httpContext); } catch (Exception ex) { _logger.LogError($"Something went wrong: {ex}"); await HandleExceptionAsync(httpContext, ex); } } private async Task HandleExceptionAsync(HttpContext context, Exception exception) { context.Response.ContentType = "application/json"; context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; await context.Response.WriteAsync(new ErrorDetails() { StatusCode = context.Response.StatusCode, Message = "Internal Server Error from the custom middleware." }.ToString()); } }
当然还可以使用过滤器(Filter)来实现,即IExceptionFilter, 这些都能很方便实现自定义的全局异常处理。
IExceptionHandler 实现异常处理
在.NET 8.0里,微软新引入的IExceptionHandler
也可以实现同样的功能,看官方的异常处理文档,IExceptionHandler
似乎已经是最推荐的异常处理方法。
在微软新开的项目里,IExceptionHandler
正被广泛使用,比如Semantic Kernel
下面是官方文档给的一个简单例子
using Microsoft.AspNetCore.Diagnostics; namespace ErrorHandlingSample { public class CustomExceptionHandler : IExceptionHandler { private readonly ILogger<CustomExceptionHandler> logger; public CustomExceptionHandler(ILogger<CustomExceptionHandler> logger) { this.logger = logger; } public ValueTask<bool> TryHandleAsync( HttpContext httpContext, Exception exception, CancellationToken cancellationToken) { var exceptionMessage = exception.Message; logger.LogError( "Error Message: {exceptionMessage}, Time of occurrence {time}", exceptionMessage, DateTime.UtcNow); // Return false to continue with the default behavior // - or - return true to signal that this exception is handled return ValueTask.FromResult(false); } } }
注册也很简单
builder.Services.AddExceptionHandler<CustomExceptionHandler>();
然而,坑来了,在按照文档实现完之后,你所期待的自定义异常处理并不会生效!这不是你的问题,你必须还要UseExceptionHandler
并且添加一个空的lambda给它,必须是空的lambda,直接app.UseExceptionHandler()
还没用,只有这样AddExceptionHandler
才会生效 😃
app.UseExceptionHandler(o => { });
为什么会这样?请看这个issue https://github.com/dotnet/aspnetcore/issues/51888, 去年下半年就有人发现了,微软尝试去修复了https://github.com/dotnet/aspnetcore/pull/51898, 但是改动有breaking change被自己人给拒了,加上有上面提到的workaround,就一直搁置了。
虽然又不是不能用,但是看着难受,开头就介绍了,UseExceptionHandler
是启用内置的异常处理中间件的方法,而AddExceptionHandler
是用来注册.NET 8.0新引入的IExceptionHandler
,这个workaround有点一言难尽...
最后
从这个神奇的workaround可以看出,IExceptionHandler
这套其实本质也是用的中间件,看起来它的实现和现有的UseExceptionHandler
有些冲突,导致注册的时候不伦不类,欢迎踊跃提交PR去fix,先到先得☺
作者: 马行空的博客
出处: https://www.cnblogs.com/netry/p/18254779/dot-net-iexceptionhandler-not-working
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器