ASP.NET 8 中的 ExceptionHandler【转】

Intro

ASP.NET 8 中引入了 IExceptionHandler,我们可以针对某一类的 exception 做单独的处理,
可以将不同类型的异常有不一样的逻辑做不同的处理,异常处理可以变得更加灵活

Sample

来看一个简单的示例:
我们可以实现 IExceptionHandler 来处理异常:

file sealed class ArgumentExceptionHandler : IExceptionHandler
{
    public async ValueTask<bool> TryHandleAsync(HttpContext httpContext, Exception exception, CancellationToken cancellationToken)
    {
        httpContext.RequestServices.GetRequiredService<ILogger<ArgumentExceptionHandler>>()
            .LogError(exception, "Exception handled");
        if (exception is not ArgumentException) return false;

        httpContext.Response.StatusCode = 400;
        await httpContext.Response.WriteAsJsonAsync(new
        {
            exception.Message
        }, cancellationToken);
        return true;
    }
}

只需要实现 TryHandleAsync 方法即可,返回值是 true 代表已经已经处理 ,无需后面的 exception handle 逻辑再处理,false 则需要后面的逻辑进行处理

完整的 web app 示例如下:

通过 AddExceptionHandler() 来注册我们自定义的异常处理,可以注册多个,如果有多个要注意注册顺序,像中间件一样,先注册的 handler 会先执行

另外需要通过 UseExceptionHandler() 注册 ExceptionHandler 中间件

需要指定一下 exception handler 未处理的情况下的 exception 路由 ExceptionHandlingPath 或者 exception 处理逻辑 ExceptionHandler

var builder = WebApplication.CreateSlimBuilder(args);
builder.Services.AddExceptionHandler<ArgumentExceptionHandler>();
var app = builder.Build();

app.UseExceptionHandler(new ExceptionHandlerOptions()
{
    // ExceptionHandlingPath = "/",
    ExceptionHandler = context =>
    {
        context.Response.StatusCode = 500;
        context.Response.WriteAsJsonAsync(new
        {
            title = "Internal Error",
            traceId = context.TraceIdentifier
        });
        return Task.CompletedTask;
    }
});
app.MapGet("/", () => "Hello .NET 8!");
app.MapGet("/exception", () =>
{
    throw new InvalidOperationException("Oh no...");
});
app.MapGet("/argument-exception", () =>
{
    throw new ArgumentException("Oh no...");
});
await app.RunAsync();

我们在示例中添加了三种效果,没有异常、InvalidOperationException/ArgumentException

这样我们可以把 exception 分层处理,不同的处理逻辑放在不同的 exception handler 中,不需要定义在一个地方,这样就灵活了许多,相当于中间件里套了一层中间件,套娃,嘿嘿

posted @   .Neterr  阅读(105)  评论(0编辑  收藏  举报

喜欢请打赏

扫描二维码打赏

了解更多

点击右上角即可分享
微信分享提示