ASP.NET Core 3中的全局异常处理程序中间件

时间:2019-10-23 08:29:38

标签: asp.net-core

上下文: 我正在尝试找到一种在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响应。我该怎么办?

1 个答案:

答案 0 :(得分:1)

您可以使用这样的自定义异常过滤器属性

[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)))