如何使从 BadRequest 和验证中引发的 400 响应具有相同的响应格式?

How to have the same response format for 400 response raised from BadRequest and validations?

我有一个 DTO,它是 API 的 POST 端点的输入参数。

DTO 已获得数据注释并自动进行验证。下面是一个例子:

{
    "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
    "title": "One or more validation errors occurred.",
    "status": 400,
    "traceId": "00-f14406a8950b1005234cc79298a79586-77222ebbed97e453-00",
    "errors": {
        "Email": [
            "The Email field is not a valid e-mail address."
        ]
    }
}

但是,当我想从控制器发出 400 响应时,使用以下任一方法:

return BadRequest("some message")

这个returnssome message

其中:return BadRequest(new { message = "some message"}); returns:

{
    "message": "some message"
}

如何确保始终使用相同的格式?是否有任何内置的标准化方法。

按如下方式创建基础 api 控制器:

[ApiController]
public abstract class ApiControllerBase : ControllerBase
{        
    protected virtual IActionResult InvalidModelState() {
        return HttpContext.RequestServices.GetService<IOptions<ApiBehaviorOptions>>()
            .Value.InvalidModelStateResponseFactory(ControllerContext);
    }
}

并从 ApiControllerBase 派生您的 api 控制器。 每当您想添加错误并使用相同格式的验证错误时,只需添加 ModelState.AddModelError("", "Your error message") 然后 return InvalidModelState();.

根据文档 - https://docs.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-6.0#default-badrequest-response

ValidationProblemDetails 类型:

  • 提供一种机器可读的格式,用于指定网络 API 响应中的错误。
  • 符合 RFC 7807 规范。

要使自动响应和自定义响应保持一致,请调用 ValidationProblem 方法而不是 BadRequest

ValidationProblem return 一个 ValidationProblemDetails 对象以及自动响应。

示例:

ModelState.AddModelError("Name", "Invalid name");
return ValidationProblem(ModelState);

您可以在所有响应代码中使用此概念 - 例如 - 而不是 400(ValidationProblem 的默认值),您可以 return 401 通过将最后一行替换为上述代码以下:

return ValidationProblem(modelStateDictionary:ModelState, statusCode:401)

如果您不想使用此响应格式并希望拥有自己的响应格式,则必须禁用负责自动模型验证和 400 响应的中间件

program.cs中:

builder.Services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressModelStateInvalidFilter=true;
    });

现在在控制器中,您必须自己进行验证(例如:检查空值)和 return BadRequest(new {error = "type something here"};