Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【文章推荐】ASP.NET Core 中的正确的异常处理 #758

Closed
gaufung opened this issue Nov 11, 2024 · 1 comment
Closed

【文章推荐】ASP.NET Core 中的正确的异常处理 #758

gaufung opened this issue Nov 11, 2024 · 1 comment

Comments

@gaufung
Copy link
Collaborator

gaufung commented Nov 11, 2024

https://www.youtube.com/watch?v=-TGZypSinpw&ab_channel=NickChapsas

@gaufung
Copy link
Collaborator Author

gaufung commented Dec 23, 2024

RFC 7807 中,规定了可读的响应来避免更多的错误的内容规范。在 ASP.NET Core 的应用程序中可以优雅的方式完成这个要求。

  1. 定义异常

对应不用的业务,可以定制不同的异常类型

[Serializable]
public class ProblemException : Exception
{
    public string Error { get;}
    public string Message { get; }
    public ProblemException(string error, string message) : base(message)
    {
        Error = error;
        Message = message;
    }
}
  1. 定义 ExceptionHandler
public class ProblemExceptionHandler : IExceptionHandler
{

    private readonly IProblemDetailsService _problemDetailsService;

    public ProblemExceptionHandler(IProblemDetailsService problemDetailsService)
    {
        _problemDetailsService = problemDetailsService;
    }

    public async ValueTask<bool> TryHandleAsync(
        HttpContext httpContext,
        Exception exception,
        CancellationToken cancellationToken)
    {
        if (exception is not ProblemException problemException)
        {
            return true;
        }

        var problemDetails = new ProblemDetails();
        problemDetails.Status = StatusCodes.Status400BadRequest;
        problemDetails.Title = problemException.Error;
        problemDetails.Detail = problemException.Message;
        problemDetails.Type = "Bad Request";

        httpContext.Response.StatusCode = StatusCodes.Status400BadRequest;
        return await _problemDetailsService.TryWriteAsync(
            new ProblemDetailsContext()
            {
                HttpContext = httpContext,
                ProblemDetails = problemDetails,
            });
    }
}
  1. 注册服务并且注册中间件
builder.Services.AddExceptionHandler<ProblemExceptionHandler>();
app.UseExceptionHandler();
  1. 添加额外信息
builder.Services.AddProblemDetails(options =>
{
    options.CustomizeProblemDetails = context =>
    {
        context.ProblemDetails.Instance = $"{context.HttpContext.Request.Method} {context.HttpContext.Request.Path}";
        context.ProblemDetails.Extensions.TryAdd("requestId", context.HttpContext.TraceIdentifier);
        var activity = context.HttpContext.Features.Get<IHttpActivityFeature>()?.Activity;
        context.ProblemDetails.Extensions.TryAdd("traceId", activity?.Id);
    };
});

这样在任何需要错误的地方,只需要抛出 ProblemException 即可。

@gaufung gaufung closed this as completed Dec 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant