ASP.NET ExceptionFilter
最后修改于 2025 年 4 月 3 日
在本文中,我们将探讨 ASP.NET 8 中的异常过滤器。异常过滤器提供了一种集中且一致的方式来处理异常。
ASP.NET 是一个跨平台、高性能的框架,用于构建现代 Web 应用程序。异常过滤器有助于跨控制器管理错误处理。
基本定义
ASP.NET 中的异常过滤器是实现 IExceptionFilter 或 IAsyncExceptionFilter 接口的特性。它们会捕获控制器中未处理的异常。
当异常发生在操作执行期间时,异常过滤器可以在异常到达客户端之前拦截它。它们允许自定义错误响应和日志记录。
异常过滤器可以在不同级别应用:全局、控制器范围或特定操作。它们比传统的 try-catch 块提供了更多的控制。
ASP.NET ExceptionFilter 示例
以下示例演示了如何创建和使用自定义异常过滤器。
Program.cs
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(options => { options.Filters.Add<CustomExceptionFilter>(); }); var app = builder.Build(); app.MapControllers(); app.Run();
这会将我们的 CustomExceptionFilter 全局注册到所有控制器。该过滤器将处理应用程序中的所有未处理异常。
Filters/CustomExceptionFilter.cs
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using System.Net; public class CustomExceptionFilter : IExceptionFilter { private readonly ILogger<CustomExceptionFilter> _logger; public CustomExceptionFilter(ILogger<CustomExceptionFilter> logger) { _logger = logger; } public void OnException(ExceptionContext context) { _logger.LogError(context.Exception, "An unhandled exception occurred"); var problemDetails = new ProblemDetails { Title = "An error occurred", Status = (int)HttpStatusCode.InternalServerError, Detail = context.Exception.Message, Instance = context.HttpContext.Request.Path }; if (context.Exception is ArgumentException) { problemDetails.Status = (int)HttpStatusCode.BadRequest; problemDetails.Title = "Invalid argument"; } else if (context.Exception is KeyNotFoundException) { problemDetails.Status = (int)HttpStatusCode.NotFound; problemDetails.Title = "Resource not found"; } context.Result = new ObjectResult(problemDetails) { StatusCode = problemDetails.Status }; context.ExceptionHandled = true; } }
此过滤器记录异常并将它们转换为标准化的 ProblemDetails 响应。不同的异常类型会导致不同的 HTTP 状态码。
Controllers/ProductsController.cs
using Microsoft.AspNetCore.Mvc; [ApiController] [Route("api/[controller]")] public class ProductsController : ControllerBase { private static List<Product> _products = new() { new Product(1, "Laptop", 999.99m), new Product(2, "Mouse", 19.99m), new Product(3, "Keyboard", 49.99m) }; [HttpGet("{id}")] public IActionResult GetProductById(int id) { var product = _products.FirstOrDefault(p => p.Id == id); if (product == null) { throw new KeyNotFoundException($"Product with ID {id} not found"); } return Ok(product); } [HttpPost] public IActionResult CreateProduct([FromBody] Product product) { if (product.Price <= 0) { throw new ArgumentException("Price must be greater than zero"); } _products.Add(product); return CreatedAtAction(nameof(GetProductById), new { id = product.Id }, product); } } public record Product(int Id, string Name, decimal Price);
控制器会抛出会被我们的过滤器捕获的异常。该过滤器会将这些异常转换为带有 ProblemDetails 的适当 HTTP 响应。
当抛出 KeyNotFoundException 时,过滤器返回 404 状态。对于 ArgumentException,它返回 400。所有其他异常都导致 500 响应。
这种方法集中了错误处理逻辑,同时保持了控制器的代码整洁。该过滤器确保了整个 API 的一致错误响应。
来源
在本文中,我们探讨了 ASP.NET 8 中的异常过滤器。这些强大的过滤器有助于创建具有一致错误处理模式的健壮 API。