.NET 7中如何统一错误响应的问题详情格式?
统一.NET 7中NotFound响应格式的方案
方法一:自定义ProblemDetailsFactory(全局统一所有错误响应)
ASP.NET Core 默认通过 ProblemDetailsFactory 生成标准化错误响应,重写这个类可以全局统一所有错误的输出格式,包括NotFound:
- 创建自定义工厂类,继承默认的
ProblemDetailsFactory:
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.Extensions.Options; using System.Diagnostics; public class CustomProblemDetailsFactory : ProblemDetailsFactory { private readonly ApiBehaviorOptions _apiOptions; public CustomProblemDetailsFactory(IOptions<ApiBehaviorOptions> apiOptions) { _apiOptions = apiOptions?.Value ?? throw new ArgumentNullException(nameof(apiOptions)); } public override ProblemDetails CreateProblemDetails( HttpContext httpContext, int? statusCode = null, string? title = null, string? type = null, string? detail = null, string? instance = null) { statusCode ??= 500; var problemDetails = new ProblemDetails { Status = statusCode, Title = title ?? _apiOptions.ClientErrorMapping[statusCode].Title, Type = type ?? _apiOptions.ClientErrorMapping[statusCode].Link, Detail = detail, Instance = instance }; AddCommonExtensions(httpContext, problemDetails, statusCode.Value); return problemDetails; } public override ValidationProblemDetails CreateValidationProblemDetails( HttpContext httpContext, ModelStateDictionary modelStateDictionary, int? statusCode = null, string? title = null, string? type = null, string? detail = null, string? instance = null) { if (modelStateDictionary == null) throw new ArgumentNullException(nameof(modelStateDictionary)); statusCode ??= 400; var problemDetails = new ValidationProblemDetails(modelStateDictionary) { Status = statusCode, Type = type ?? _apiOptions.ClientErrorMapping[statusCode].Link, Detail = detail, Instance = instance }; if (title != null) problemDetails.Title = title; AddCommonExtensions(httpContext, problemDetails, statusCode.Value); return problemDetails; } private void AddCommonExtensions(HttpContext httpContext, ProblemDetails problemDetails, int statusCode) { problemDetails.Status ??= statusCode; if (_apiOptions.ClientErrorMapping.TryGetValue(statusCode, out var errorData)) { problemDetails.Title ??= errorData.Title; problemDetails.Type ??= errorData.Link; } // 添加TraceId便于排查问题 var traceId = Activity.Current?.Id ?? httpContext?.TraceIdentifier; if (traceId != null) problemDetails.Extensions["traceId"] = traceId; // 针对404场景,确保无传入消息时也有默认detail if (problemDetails.Status == 404 && string.IsNullOrEmpty(problemDetails.Detail)) problemDetails.Detail = "请求的资源未找到"; } }
- 在
Program.cs中替换默认的工厂实现:
builder.Services.AddSingleton<ProblemDetailsFactory, CustomProblemDetailsFactory>();
之后不管调用return NotFound()还是return NotFound("用户不存在"),都会返回结构完全一致的响应:
无消息时的响应:
{ "type": "https://tools.ietf.org/html/rfc7231#section-6.5.4", "title": "Not Found", "status": 404, "detail": "请求的资源未找到", "traceId": "00-xxxxxxxxx-xxxxxxxxx-00" }带自定义消息时的响应:
{ "type": "https://tools.ietf.org/html/rfc7231#section-6.5.4", "title": "Not Found", "status": 404, "detail": "用户不存在", "traceId": "00-xxxxxxxxx-xxxxxxxxx-00" }
方法二:自定义UnifiedNotFoundResult(仅针对NotFound场景)
如果只需要统一NotFound的格式,不想影响其他错误响应,可以自定义一个专属的ActionResult:
- 创建自定义结果类:
using Microsoft.AspNetCore.Mvc; public class UnifiedNotFoundResult : ObjectResult { public UnifiedNotFoundResult(string? message = null) : base(new ProblemDetails { Status = StatusCodes.Status404NotFound, Title = "资源不存在", Type = "https://your-docs.com/errors/404", Detail = message ?? "请求的资源未找到" }) { StatusCode = StatusCodes.Status404NotFound; } }
- 在控制器中直接使用:
// 无自定义消息 return new UnifiedNotFoundResult(); // 带自定义消息 return new UnifiedNotFoundResult("指定的商品不存在");
这种方式更轻量化,仅作用于NotFound场景,适合不需要全局统一所有错误格式的场景。
方法三:配置ApiBehaviorOptions(简单统一标题和类型)
如果只需要统一NotFound的标题和类型,不需要修改detail的逻辑,可以直接配置ApiBehaviorOptions:
builder.Services.Configure<ApiBehaviorOptions>(options => { options.ClientErrorMapping[StatusCodes.Status404NotFound] = new ClientErrorData { Title = "资源不存在", Link = "https://your-docs.com/errors/404" }; });
这种方式只能调整默认的标题和类型链接,无法统一detail的存在性,适合需求简单的场景。
内容的提问来源于stack exchange,提问作者Simon Great
相关产品推荐
相关产品推荐

