之前ASP.NET Web API我们处理异常都是通过过滤器(filter)来处理,但在ASP.NET Core Web API中我们需要通过中间件(middleware)或UseExceptionHandler等方法进行异常处理,本文主要介绍一下ASP.NET Core Web API中进行异常处理的方法及示例代码。

1、使用中间件(middleware)异常处理

1)中间件代码

public class ErrorHandlingMiddleware
{
    private readonly RequestDelegate next;
    public ErrorHandlingMiddleware(RequestDelegate next)
    {
        this.next = next;
    }
    public async Task Invoke(HttpContext context /* other dependencies */)
    {
        try
        {
            await next(context);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(context, ex);
        }
    }
    private static Task HandleExceptionAsync(HttpContext context, Exception ex)
    {
        var code = HttpStatusCode.InternalServerError; // 500 if unexpected
        if      (ex is MyNotFoundException)     code = HttpStatusCode.NotFound;
        else if (ex is MyUnauthorizedException) code = HttpStatusCode.Unauthorized;
        else if (ex is MyException)             code = HttpStatusCode.BadRequest;
        var result = JsonConvert.SerializeObject(new { error = ex.Message });//JsonConvert.SerializeObject(errorObj, opts.Value.SerializerSettings)
        context.Response.ContentType = "application/json";
        context.Response.StatusCode = (int)code;
        return context.Response.WriteAsync(result);
    }
}

2)在Startup.cs注册中间件

注意:要在app.UseMvc();之前注册。

app.UseMiddleware(typeof(ErrorHandlingMiddleware));
app.UseMvc();

2)输出异常信息的JSON格式

{ "error": "Authentication token is not valid." }

2、使用app.UseExceptionHandler()异常处理

app.UseExceptionHandler(a => a.Run(async context =>
{
    var feature = context.Features.Get<IExceptionHandlerPathFeature>();
    var exception = feature.Error;
    var result = JsonConvert.SerializeObject(new { error = exception.Message });
    context.Response.ContentType = "application/json";
    await context.Response.WriteAsync(result);
}));

3、使用Community.AspNetCore.ExceptionHandling异常处理

1)需要引用的Nuget包

ASP.NET Core 2.0Community.AspNetCore.ExceptionHandling.NewtonsoftJson 

ASP.NET Core 2.1+Community.AspNetCore.ExceptionHandling.Mvc

相关文档VS(Visual Studio)中Nuget的使用

2)配置使用示例代码

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddExceptionHandlingPolicies(options =>
    {
        options.For<InitializationException>().Rethrow();
        options.For<SomeTransientException>().Retry(ro => ro.MaxRetryCount = 2).NextPolicy();
        options.For<SomeBadRequestException>()
        .Response(e => 400)
            .Headers((h, e) => h["X-MyCustomHeader"] = e.Message)
            .WithBody((req,sw, exception) =>
                {
                    byte[] array = Encoding.UTF8.GetBytes(exception.ToString());
                    return sw.WriteAsync(array, 0, array.Length);
                })
        .NextPolicy();
        // 确保所有异常类型都通过在末尾添加通用异常的处理程序来处理。
        options.For<Exception>()
        .Log(lo =>
            {
                lo.EventIdFactory = (c, e) => new EventId(123, "UnhandlerException");
                lo.Category = (context, exception) => "MyCategory";
            })
        .Response(null, ResponseAlreadyStartedBehaviour.GoToNextHandler)
            .ClearCacheHeaders()
            .WithObjectResult((r, e) => new { msg = e.Message, path = r.Path })
        .Handled();
    });
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseExceptionHandlingPolicies();
    app.UseMvc();
}