1、使用微软官方推荐的做法:UseExceptionHandler
using System;
using System.Linq;
using System.Text.Json;
using Yibi.Core;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace Yibi.Hosting
{
public static class IApplicationBuilderExtensions
{
public static IApplicationBuilder UseCustomExceptionHandler(this IApplicationBuilder app, IHostEnvironment env, ILogger logger)
{
if (app == null) throw new ArgumentNullException(nameof(app));
app.UseExceptionHandler(exceptionHandlerApp =>
{
exceptionHandlerApp.Run(async context =>
{
var ex = context.Features.Get<IExceptionHandlerFeature>()?.Error;
if (ex is null) return;
context.Response.ContentType = "application/json; charset=utf-8";
if (ex is AccessTokenException)
{
await context.Response.WriteAsync(JsonSerializer.Serialize(new ResponseResult { ResCode = ResCodeOptions.AccessTokenInvalidError, Message = ex.Message }));
}
else if (ex is CustomException)
{
await context.Response.WriteAsync(JsonSerializer.Serialize(new ResponseResult { ResCode = ResCodeOptions.Failed, Message = ex.Message }));
}
else
{
if (env.IsProduction())
{
logger.LogError(ex.Message);
if (EnvironmentHelper.ValidErrorTypes.Any(i => ex.Source.StartsWith(i)))
{
await context.Response.WriteAsync(JsonSerializer.Serialize(new ResponseResult { ResCode = ResCodeOptions.Failed, Message = SM.SystemError }));
return;
}
}
await context.Response.WriteAsync(JsonSerializer.Serialize(new ResponseResult { ResCode = ResCodeOptions.Failed, Message = $"{ex.Message}--{ex.InnerException?.Message}" }));
}
});
});
return app;
}
}
}
Startup.cs:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
{
app.UseCustomExceptionHandler(env, logger);
}
2、使用微软官方推荐的做法:UseExceptionHandler的自定义类中写代码:
CustomExceptionHandler.cs:
namespace Yibi.Hosting
{
public class CustomExceptionHandler
{
private readonly IHostEnvironment _env;
private readonly ILogger<CustomExceptionHandler> _logger;
public CustomExceptionHandler(IHostEnvironment env, ILogger<CustomExceptionHandler> logger)
{
_env = env ?? throw new ArgumentNullException(nameof(env));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task InvokeAsync(HttpContext context)
{
var ex = context.Features.Get<IExceptionHandlerFeature>()?.Error;
if (ex == null)
{
return;
}
context.Response.ContentType = "application/json; charset=utf-8";
if (ex is AccessTokenException)
{
await context.Response.WriteAsync(JsonSerializer.Serialize(new ResponseResult { ResCode = ResCodeOptions.AccessTokenInvalidError, Message = ex.Message }));
}
else if (ex is CustomException)
{
await context.Response.WriteAsync(JsonSerializer.Serialize(new ResponseResult { ResCode = ResCodeOptions.Failed, Message = ex.Message }));
}
else
{
if (_env.IsProduction())
{
_logger.LogError(ex.Message);
if (EnvironmentHelper.ValidErrorTypes.Any(i => ex.Source.StartsWith(i)))
{
await context.Response.WriteAsync(JsonSerializer.Serialize(new ResponseResult { ResCode = ResCodeOptions.Failed, Message = SM.SystemError }));
return;
}
}
await context.Response.WriteAsync(JsonSerializer.Serialize(new ResponseResult { ResCode = ResCodeOptions.Failed, Message = $"{ex.Message}--{ex.InnerException?.Message}" }));
}
}
}
}
Startup.cs:
app.UseExceptionHandler(new ExceptionHandlerOptions
{
ExceptionHandler = new CustomExceptionHandler(env, logger).InvokeAsync
});
3、使用中间件Middleware:
namespace Yibi.Hosting
{
public class CustomExceptionHandlerMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<CustomExceptionHandlerMiddleware> _logger;
public CustomExceptionHandlerMiddleware(RequestDelegate next, ILogger<CustomExceptionHandlerMiddleware> logger)
{
_next = next ?? throw new ArgumentNullException(nameof(next));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
context.Response.ContentType = "application/json; charset=utf-8";
if (ex is AccessTokenException)
{
await context.Response.WriteAsync(JsonSerializer.Serialize(new ResponseResult { ResCode = ResCodeOptions.AccessTokenInvalidError, Message = ex.Message }));
}
else if (ex is CustomException)
{
await context.Response.WriteAsync(JsonSerializer.Serialize(new ResponseResult { ResCode = ResCodeOptions.Failed, Message = ex.Message }));
}
else
{
if (_env.IsProduction())
{
_logger.LogError(ex.Message);
if (EnvironmentHelper.ValidErrorTypes.Any(i => ex.Source.StartsWith(i)))
{
await context.Response.WriteAsync(JsonSerializer.Serialize(new ResponseResult { ResCode = ResCodeOptions.Failed, Message = SM.SystemError }));
return;
}
}
await context.Response.WriteAsync(JsonSerializer.Serialize(new ResponseResult { ResCode = ResCodeOptions.Failed, Message = $"{ex.Message}--{ex.InnerException?.Message}" }));
}
}
}
}
}
namespace Yibi.Hosting
{
public static class IApplicationBuilderExtensions
{
public static IApplicationBuilder UseCustomExceptionHandlerMiddleware(this IApplicationBuilder app)
{
if (app == null) throw new ArgumentNullException(nameof(app));
return app.UseMiddleware<CustomExceptionHandlerMiddleware>();
}
}
}
Startup.cs:
app.UseCustomExceptionHandlerMiddleware();