You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 6 Web API配置验证错误返回application/problem+json

解决方案

问题原因

返回Content-Type不符合预期、丢失错误详情的核心原因:

  • 直接将ModelState对象传入UnprocessableEntity/UnprocessableEntityObjectResult时,框架会把ModelState的键值对序列化为普通JSON,不会包装为RFC 7807标准的ProblemDetails结构,默认返回application/json类型
  • 无参UnprocessableEntity()不会自动携带模型校验错误信息,必然丢失校验详情
  • 自定义的ValidationFilterAttribute和控制器内手动判断ModelState的逻辑,覆盖了.NET 6 Web API自带的标准校验响应处理逻辑

实现步骤

方法一:使用框架自带的ApiBehavior配置(推荐)

  1. 首先删除控制器中手动判断ModelState.IsValid返回的代码,以及你自定义的ValidationFilterAttribute,避免重复逻辑覆盖默认配置
  2. 在Program.cs中配置控制器服务,自定义模型校验失败的响应工厂,强制返回application/problem+json格式的标准校验响应,同时保留所有错误详情,状态码设为需要的422:
var builder = WebApplication.CreateBuilder(args);

// 其他服务注入逻辑...

builder.Services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        // 自定义模型校验失败的响应逻辑
        options.InvalidModelStateResponseFactory = context =>
        {
            // 将模型校验错误包装为标准ValidationProblemDetails
            var problemDetails = new ValidationProblemDetails(context.ModelState)
            {
                Status = StatusCodes.Status422UnprocessableEntity,
                Title = "参数校验失败",
                Instance = context.HttpContext.Request.Path
            };

            return new UnprocessableEntityObjectResult(problemDetails)
            {
                // 强制指定响应Content-Type为application/problem+json
                ContentTypes = { "application/problem+json" }
            };
        };
    });

// 可选:全局添加ProblemDetails服务,让其他异常场景也返回标准problem+json格式
builder.Services.AddProblemDetails();

var app = builder.Build();
// 其他中间件配置逻辑...
app.Run();

配置完成后,所有标记[ApiController]的接口,在参数校验失败时都会自动返回带完整错误详情的application/problem+json响应,不需要在控制器里写重复判断逻辑。

方法二:保留自定义ValidationFilterAttribute的改法

如果一定要保留自定义过滤器,不要直接将ModelState传入返回结果,而是先包装为ValidationProblemDetails对象,再指定Content-Type:

public class ValidationFilterAttribute : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        if (!context.ModelState.IsValid)
        {
            var problemDetails = new ValidationProblemDetails(context.ModelState)
            {
                Status = StatusCodes.Status422UnprocessableEntity,
                Title = "参数校验失败"
            };
            context.Result = new UnprocessableEntityObjectResult(problemDetails)
            {
                ContentTypes = { "application/problem+json" }
            };                
        }
    }

    public void OnActionExecuted(ActionExecutedContext context) { }
}

如果需要在控制器内手动返回校验错误,也按照同样的写法,不要直接传ModelState:

if (!ModelState.IsValid) 
{
    var problem = new ValidationProblemDetails(ModelState)
    {
        Status = StatusCodes.Status422UnprocessableEntity,
        Title = "参数校验失败"
    };
    return new UnprocessableEntityObjectResult(problem)
    {
        ContentTypes = { "application/problem+json" }
    };
}

效果说明

返回的响应结构为标准RFC 7807格式,errors字段下包含所有字段的校验错误详情,响应头Content-Type为application/problem+json,完全符合需求。

内容的提问来源于stack exchange,提问作者Steve

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 21:51:38