ASP.NET Core中如何将特定异常映射为验证失败风格的ProblemDetails?
当然可以实现,而且有比CustomizeProblemDetails更优雅的方式——通过自定义ProblemDetailsFactory来直接覆盖异常对应的ProblemDetails创建逻辑,完全满足你提取异常中验证信息、返回400带错误数组的需求。
具体实现步骤
1. 定义承载验证错误的自定义异常(可选,也可复用现有异常)
如果你的业务场景需要传递自定义验证错误集合,可以先定义一个带错误信息的异常类:
public class ValidationFailureException : Exception { public IDictionary<string, string[]> Errors { get; } public ValidationFailureException(IDictionary<string, string[]> errors) : base("存在验证失败项") { Errors = errors; } }
2. 自定义ProblemDetailsFactory,覆盖异常处理逻辑
继承默认的DefaultProblemDetailsFactory,重写CreateExceptionProblemDetails方法,针对目标异常直接生成ValidationProblemDetails(带错误数组的验证失败格式):
public class CustomProblemDetailsFactory : DefaultProblemDetailsFactory { public CustomProblemDetailsFactory(IOptions<ApiBehaviorOptions> options, IOptions<ProblemDetailsOptions> problemDetailsOptions) : base(options, problemDetailsOptions) { } public override ProblemDetails CreateExceptionProblemDetails(HttpContext httpContext, Exception exception, int? statusCode = null, string? title = null, string? type = null, string? detail = null, string? instance = null) { // 匹配自定义的验证失败异常 if (exception is ValidationFailureException validationException) { var validationProblem = new ValidationProblemDetails(validationException.Errors) { Status = StatusCodes.Status400BadRequest, Title = "验证失败", Detail = "提交的内容存在验证错误,请检查后重试", Instance = httpContext.Request.Path }; // 可添加额外扩展字段,比如请求追踪ID validationProblem.Extensions["traceId"] = httpContext.TraceIdentifier; return validationProblem; } // 其他异常沿用默认处理逻辑 return base.CreateExceptionProblemDetails(httpContext, exception, statusCode, title, type, detail, instance); } }
3. 注册自定义Factory到DI容器
在Program.cs中替换默认的ProblemDetailsFactory实现:
builder.Services.AddProblemDetails(); // 用自定义实现替换默认的ProblemDetailsFactory builder.Services.AddSingleton<ProblemDetailsFactory, CustomProblemDetailsFactory>();
补充说明
- 如果你的项目使用了FluentValidation等验证框架,抛出的是框架自带的
ValidationException,可以直接将判断条件改为exception is ValidationException,然后从该异常的Errors属性中提取验证信息。 - 这种方式直接从异常创建对应的
ValidationProblemDetails,无需像CustomizeProblemDetails那样修改已生成的ProblemDetails的多个字段,逻辑更清晰,还能直接映射异常中的错误集合到响应的Errors数组。
内容的提问来源于stack exchange,提问作者SeeNoWeevil
相关产品推荐
相关产品推荐

