在 ASP.NET Core UnprocessableEntityResult 中自定义详细信息

问题描述 投票:0回答:1

我有一个 ASP.NET Core 9 Web API 项目,其中包含创建新资源的

POST
操作。

它期望请求正文中有特定类型的对象,并且该对象的属性具有通常的验证属性,例如

[Required]
[MaxLength]

一切都运行良好,如果存在任何验证问题,响应正文看起来像例如

{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "errors": {
    "Surname": [
      "The Surname field is required."
    ],
    "Forename": [
      "The field Forename must be a string or array type with a maximum length of '20'."
    ]
  },
  "traceId": "00-250e7a400ba440a4242639ce55ce4fc9-6ac285dbee25ccb7-00"
}

但是在服务器端,我进行了更多的验证,并且在某些情况下创建可能会失败,即使请求的结构正确。主要的一个是客户端是否请求了数据库中已存在的唯一标识符(用户名),但还有其他几个。

在这种情况下,我返回http 422(无法处理的实体)

return UnprocessableEntity();

但是所有客户端返回的都是这样的

{
  "type": "https://tools.ietf.org/html/rfc4918#section-11.2",
  "title": "Unprocessable Entity",
  "status": 422,
  "traceId": "00-51c4a1bfa660009efcaed400a2dbf100-85b6faeb7047cf4c-00"
}

这里的问题是客户端不知道为什么请求失败。

如何向响应正文添加额外信息?自定义“title”属性中的文本就足够了,但如果我可以手动添加额外的属性,例如 ASP.NET 使用的“errors”数组,那就更理想了。

我注意到

Problem()
方法采用“详细信息”参数,所以如果我这样做

return Problem("My custom message");

然后我明白了

{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.6.1",
  "title": "An error occurred while processing your request.",
  "status": 500,
  "detail": "My custom message",
  "traceId": "00-24e490f7b526b65e4e0747dc4c37b99f-5f2ae15f95791e04-00"
}

但是

UnprocessableEntity()
方法没有这个选项。

asp.net-core-webapi .net-9.0
1个回答
0
投票

您可以将

UnprocessableEntity
与自定义错误消息一起使用,如下所示:

[ApiController]
[Route("[controller]")]
public class TestController : ControllerBase
{
    private ProblemDetailsFactory _problemDetailsFactory;
    
    public TestController (ProblemDetailsFactory problemDetailsFactory)
    {
        _problemDetailsFactory = problemDetailsFactory;
    }
    public IActionResult Post(User model)
    {
        if (_dbContext.Users.Any(u => u.Username == model.Username))
        {
            var problemDetails = _problemDetailsFactory.CreateProblemDetails(HttpContext, 422);
            problemDetails.Detail = "The username is already taken.";
            return UnprocessableEntity(problemDetails);
        }
        //do your stuff...
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.