ASP.NET Core 8 中的全局错误处理

作者:微信公众号:【架构师老卢】
2-6 16:2
28

概述:今天,我想向您_展示一种处理_ ASP.NET Core 8 中异常_的新旧方法_。旧方法:异常处理 Midleware在 ASP.NET Core 中实现异常处理的标准是使用中间件。中间件允许您在执行 HTTP 请求之前或之后引入逻辑。您可以轻松地扩展它以实现异常处理。在中间件中添加语句并返回错误 HTTP 响应。try-catch有 3 种方法可以在 ASP.NET Core 中创建中间件:使用请求委托按约定IMiddleware基于约定的方法要求您定义一个方法。InvokeAsync以下是约定下的定义:ExceptionHandlingMiddlewarepublic class Exc

今天,我想向您_展示一种处理_ ASP.NET Core 8 中异常_的新旧方法_。

旧方法:异常处理 Midleware

在 ASP.NET Core 中实现异常处理的标准是使用中间件。中间件允许您在执行 HTTP 请求之前或之后引入逻辑。您可以轻松地扩展它以实现异常处理。在中间件中添加语句并返回错误 HTTP 响应。try-catch

3 种方法可以在 ASP.NET Core 中创建中间件

基于约定的方法要求您定义一个方法。InvokeAsync

以下是约定下的定义:ExceptionHandlingMiddleware

public class ExceptionHandlingMiddleware  
{  
    private readonly RequestDelegate _next;  
    private readonly ILogger<ExceptionHandlingMiddleware> _logger;  
  
    public ExceptionHandlingMiddleware(  
 RequestDelegate next,  
 ILogger<ExceptionHandlingMiddleware> logger)  
    {  
        _next = next;  
        _logger = logger;  
    }  
  
    public async Task InvokeAsync(HttpContext context)  
    {  
        try  
        {  
            await _next(context);  
        }  
        catch (Exception exception)  
        {  
            _logger.LogError(  
                exception, "Exception occurred: {Message}", exception.Message);  
  
            var problemDetails = new ProblemDetails  
            {  
                Status = StatusCodes.Status500InternalServerError,  
                Title = "Server Error"  
            };  
  
            context.Response.StatusCode =  
                StatusCodes.Status500InternalServerError;  
  
            await context.Response.WriteAsJsonAsync(problemDetails);  
        }  
    }  
}

将捕获任何未处理的异常并返回问题详细信息响应。您可以决定要向呼叫者返回多少信息。在此示例中,我隐藏了异常详细信息。ExceptionHandlingMiddleware

还需要将此中间件添加到 ASP.NET Core 请求管道:

app.UseMiddleware<ExceptionHandlingMiddleware>();

新方式:IExceptionHandler

ASP.NET Core 8 引入了用于管理异常的新抽象。内置的异常处理程序中间件使用实现来处理异常。IExceptionHandlerIExceptionHandler

此接口只有一种方法。TryHandleAsync

TryHandleAsync尝试处理 ASP.NET Core 管道中的指定异常。如果可以处理异常,则应返回 .如果无法处理异常,则应返回 。这允许您为不同的方案实现自定义异常处理逻辑。truefalse

下面是一个实现:GlobalExceptionHandler

internal sealed class GlobalExceptionHandler : IExceptionHandler  
{  
    private readonly ILogger<GlobalExceptionHandler> _logger;  
  
    public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger)  
    {  
        _logger = logger;  
    }  
  
    public async ValueTask<bool> TryHandleAsync(  
 HttpContext httpContext,  
 Exception exception,  
 CancellationToken cancellationToken)  
    {  
        _logger.LogError(  
            exception, "Exception occurred: {Message}", exception.Message);  
  
        var problemDetails = new ProblemDetails  
        {  
            Status = StatusCodes.Status500InternalServerError,  
            Title = "Server error"  
        };  
  
        httpContext.Response.StatusCode = problemDetails.Status.Value;  
  
        await httpContext.Response  
            .WriteAsJsonAsync(problemDetails, cancellationToken);  
  
        return true;  
    }  
}
internal sealed class GlobalExceptionHandler : IExceptionHandler  
{  
    public async ValueTask<bool> TryHandleAsync(  
 HttpContext httpContext,  
 Exception exception,  
 CancellationToken cancellationToken)  
    {  
        // Handle the exception, log errors.  
  
        return true;  
    }  
}

配置 IExceptionHandler 实现

要将实现添加到 ASP.NET Core 请求管道,需要两件事:IExceptionHandler

  1. 使用依赖项注入注册服务IExceptionHandler
  2. 向请求管道注册ExceptionHandlerMiddleware

调用该方法以将其注册为服务。它注册了单例生存期。因此,在注入具有不同生存期的服务时要小心。AddExceptionHandlerGlobalExceptionHandler

我还调用为常见异常生成问题详细信息响应。AddProblemDetails

builder.Services.AddExceptionHandler<GlobalExceptionHandler>();  
builder.Services.AddProblemDetails();

您还需要调用以将 添加到请求管道:

UseExceptionHandlerExceptionHandlerMiddleware
app.UseExceptionHandler();

链接异常处理程序

您可以添加多个实现,并按照注册顺序调用它们。一个可能的用例是使用异常进行流量控制。IExceptionHandler

您可以定义自定义例外,例如 和 。它们与您将从 API 返回的 HTTP 状态代码相对应。BadRequestExceptionNotFoundException

下面是一个实现:BadRequestExceptionHandler

internal sealed class BadRequestExceptionHandler : IExceptionHandler  
{  
    private readonly ILogger<BadRequestExceptionHandler> _logger;  
  
    public BadRequestExceptionHandler(ILogger<BadRequestExceptionHandler> logger)  
    {  
        _logger = logger;  
    }  
  
    public async ValueTask<bool> TryHandleAsync(  
 HttpContext httpContext,  
 Exception exception,  
 CancellationToken cancellationToken)  
    {  
        if (exception is not BadRequestException badRequestException)  
        {  
            return false;  
        }  
  
        _logger.LogError(  
            badRequestException,  
            "Exception occurred: {Message}",  
            badRequestException.Message);  
  
        var problemDetails = new ProblemDetails  
        {  
            Status = StatusCodes.Status400BadRequest,  
            Title = "Bad Request",  
            Detail = badRequestException.Message  
        };  
  
        httpContext.Response.StatusCode = problemDetails.Status.Value;  
  
        await httpContext.Response  
            .WriteAsJsonAsync(problemDetails, cancellationToken);  
  
        return true;  
    }  
}

下面是一个实现:NotFoundExceptionHandler

internal sealed class NotFoundExceptionHandler : IExceptionHandler  
{  
    private readonly ILogger<NotFoundExceptionHandler> _logger;  
  
    public NotFoundExceptionHandler(ILogger<NotFoundExceptionHandler> logger)  
    {  
        _logger = logger;  
    }  
  
    public async ValueTask<bool> TryHandleAsync(  
 HttpContext httpContext,  
 Exception exception,  
 CancellationToken cancellationToken)  
    {  
        if (exception is not NotFoundException notFoundException)  
        {  
            return false;  
        }  
  
        _logger.LogError(  
            notFoundException,  
            "Exception occurred: {Message}",  
            notFoundException.Message);  
  
        var problemDetails = new ProblemDetails  
        {  
            Status = StatusCodes.Status404NotFound,  
            Title = "Not Found",  
            Detail = notFoundException.Message  
        };  
  
        httpContext.Response.StatusCode = problemDetails.Status.Value;  
  
        await httpContext.Response  
            .WriteAsJsonAsync(problemDetails, cancellationToken);  
  
        return true;  
    }  
}

您还需要通过调用以下命令来注册这两个异常处理程序:AddExceptionHandler

builder.Services.AddExceptionHandler<BadRequestExceptionHandler>();  
builder.Services.AddExceptionHandler<NotFoundExceptionHandler>();

将首先执行并尝试处理异常。如果未处理异常,则接下来将执行并尝试处理异常。BadRequestExceptionHandlerNotFoundExceptionHandler

带走

在 ASP.NET Core 中使用中间件进行异常处理是一个很好的解决方案。但是,使用该界面的新选项真是太好了。我将在 Core 8 项目中使用 ASP.NET 新方法。IExceptionHandler

相关留言评论
昵称:
邮箱:
阅读排行