在ASP.NET Core 3.0中,可以使用中间件来实现全局异常处理,将Web API和MVC的异常处理分离。下面是一个包含代码示例的解决方法:
首先,创建一个自定义的异常处理中间件,用于处理异常并返回统一的错误响应。可以创建一个名为"ExceptionHandlerMiddleware.cs"的文件,并添加以下代码:
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Net;
using System.Threading.Tasks;
public class ExceptionHandlerMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
public ExceptionHandlerMiddleware(RequestDelegate next, ILogger logger)
{
_next = next;
_logger = logger;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "An unhandled exception occurred.");
await HandleExceptionAsync(context, ex);
}
}
private static Task HandleExceptionAsync(HttpContext context, Exception exception)
{
var code = HttpStatusCode.InternalServerError; // 默认返回500错误
var result = JsonConvert.SerializeObject(new { error = exception.Message });
if (exception is UnauthorizedAccessException)
{
code = HttpStatusCode.Unauthorized;
}
else if (exception is NotFoundException)
{
code = HttpStatusCode.NotFound;
}
else if (exception is MyCustomException)
{
code = HttpStatusCode.BadRequest;
}
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)code;
return context.Response.WriteAsync(result);
}
}
然后,在Startup.cs文件的Configure方法中,将自定义的异常处理中间件添加到Web API和MVC的管道中。示例如下:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseMiddleware(); // 添加自定义异常处理中间件
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
}
最后,可以在控制器、API控制器或Razor页面中引发异常,然后触发全局异常处理中间件。例如,在一个API控制器中:
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
[HttpGet("{id}")]
public ActionResult Get(int id)
{
if (id == 0)
{
throw new MyCustomException("Invalid ID");
}
return "value";
}
}
这样,当发生异常时,全局异常处理中间件将拦截异常,并返回统一的错误响应。