• 【踩坑】.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();
    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
    image
    下面是官方文档给的一个简单例子

    using Microsoft.AspNetCore.Diagnostics;
    namespace ErrorHandlingSample
    {
    public class CustomExceptionHandler : IExceptionHandler
    {
    private readonly ILogger logger;
    public CustomExceptionHandler(ILogger 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,就一直搁置了。
    image
    虽然又不是不能用,但是看着难受,开头就介绍了,UseExceptionHandler是启用内置的异常处理中间件的方法,而AddExceptionHandler是用来注册.NET 8.0新引入的IExceptionHandler,这个workaround有点一言难尽...

    最后

    从这个神奇的workaround可以看出,IExceptionHandler这套其实本质也是用的中间件,看起来它的实现和现有的UseExceptionHandler有些冲突,导致注册的时候不伦不类,欢迎踊跃提交PR去fix,先到先得☺

  • 相关阅读:
    TYPE-C HUB(拓展坞)乐得瑞LDR6023A快充方案介绍
    揭露 FileSystem 引起的线上 JVM 内存溢出问题
    Hadoop分布式模式配置
    自动调用构造方法
    怎么将几张图片做成pdf合在一起
    openGauss的索引组织表
    【Pygame实战】强烈推荐:教你用百行代码编写一款《小蜜蜂历险记》不信?来看看(玩儿嗨了~)
    EtherCAT主站SOEM -- 6 -- SOEM之ethercatcoe.h/c(ethercateoe/foe/soe)文件解析
    动手学TCP——CS144实验感想
    虚拟机macos安装brew、llvm并使用cmake构建项目
  • 原文地址:https://www.cnblogs.com/netry/p/18254779/dot-net-iexceptionhandler-not-working