我有一个 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()
方法没有这个选项。
您可以将
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...
}
}