首页 > 解决方案 > ASP.NET Core 3 中的全局异常处理程序中间件

问题描述

上下文:我正在尝试找到一种方法来在我的 ASP.NET Core 3.0 Webapi 中添加一个全局异常处理程序中间件,该中间件可以捕获任何未处理的异常,记录它们并返回一个 ProblemDetails 响应。

这是我到目前为止在我的 Startup.cs 中得到的:(仅包括相关代码)

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseExceptionHandler(new ExceptionHandlerOptions
    {
        ExceptionHandler = ProblemDetailsExceptionHandler
    });
    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
}

private async Task ProblemDetailsExceptionHandler(HttpContext context)
{
    var requestServiceProvider = context.RequestServices;
    var problemDetailsFactory = requestServiceProvider?.GetRequiredService<ProblemDetailsFactory>();
    if (problemDetailsFactory == null) return;

    if (context.Response.HasStarted)
    {
        // Log
        return;
    }

    var problemDetails = problemDetailsFactory.CreateProblemDetails(context,
        StatusCodes.Status500InternalServerError,
        detail: "An error occurred");
    context.Response.Headers.Add("Content-type", new StringValues("application/problem+json"));
    await context.Response.WriteAsync(JsonSerializer.Serialize(problemDetails), Encoding.UTF8);
}

我所追求的:

  1. 如何访问异常对象以记录详细信息?
  2. 在我的异常处理程序委托 (ProblemDetailsExceptionHandler) 中,我是否需要检查响应是否已开始?
  3. 我还想捕获 404 并返回 ProblemDetails 响应。我怎样才能做到这一点?

标签: asp.net-core

解决方案


您可以使用自定义异常过滤器属性,如下所示

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CustomExceptionFilterAttribute : ExceptionFilterAttribute
{
    public override void OnException(ExceptionContext context)
    {
        // if you want to do something special with specific exceptions type
        if (context.Exception is TypeOfException)
        {
            // do something custom
            context.HttpContext.Response.ContentType = "application/json";
            context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
            context.Result = new JsonResult(
                ((ValidationException)context.Exception).Failures);

            return;
        }



        var code = HttpStatusCode.InternalServerError;
        context.HttpContext.Response.ContentType = "application/json";
        context.HttpContext.Response.StatusCode = (int)code;
        context.Result = new JsonResult(new
        {
            error = new[] { context.Exception.Message },
            stackTrace = context.Exception.StackTrace
        });
    }
}

然后注册进去Startup.cs

services.AddControllersWithViews(options => options.Filters.Add(typeof(CustomExceptionFilterAttribute)))

推荐阅读