【发布时间】:2021-09-28 09:59:03
【问题描述】:
我正在创建一个 ASP.net Core Web API (.net 5) 来为单页应用程序 (SPA) 提供数据。我正在使用 DataAnnotations (System.ComponentModel.DataAnnotations) 在我的 Controller 中以非常标准的方式执行模型状态验证。我想确保我的错误响应以非常一致的方式返回(并且可以在前端进行翻译!)。
MVC 控制器
示例控制器如下:
[ApiController, Route("[controller]")]
public class AgencyController : Controller
{
private readonly IOptions<ApiBehaviorOptions> _apiBehaviorOptions;
public AgencyController(IOptions<ApiBehaviorOptions> apiBehaviorOptions)
{
_apiBehaviorOptions = apiBehaviorOptions;
}
[HttpPost]
[ProducesResponseType(typeof(void), (int) HttpStatusCode.OK)]
[ProducesResponseType(typeof(ProblemDetails), (int) HttpStatusCode.BadRequest)]
public IActionResult Create([FromBody] ExampleCreateModel createModel)
{
// If the email already exists, add the custom error.
var emailExists = EmailAlreadyExists(createModel.Email);
if (emailExists)
{
ModelState.AddModelError("Email", "Email already exists");
return _apiBehaviorOptions.Value.InvalidModelStateResponseFactory(ControllerContext);
}
// Return some relevant status...
return Ok();
}
// Real verification implementation would go here....
private bool EmailAlreadyExists(string email) => true;
}
上面的示例代码演示了一个采用 POCO 模型的控制器(如下所示),如果它通过属性验证,则执行额外的内联验证以确保电子邮件地址不存在(电子邮件的伪代码存在检查)。
样本模型
public class ExampleCreateModel
{
[Required]
public string Name { get; set; } = "";
[Required]
[EmailAddress(ErrorMessage = "Invalid email format")]
public string Email { get; set; } = "";
}
错误响应格式
上面显示的模型的验证失败会产生来自 MVC 应用程序的标准错误对象,格式如下(示例):{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-6b30709ed71b7347afd41e0ed58e1ccb-e3ede2ff7591a24d-00",
"errors": {
"Email": [
"Email already exists"
]
}
}
这种格式对于上面代码中的常规属性验证和自定义内联验证都是一致的
我的问题
使用内置错误的优点是一致性(并遵循标准模式)。但对我来说,不利的一面是我想返回错误代码以及文本作为错误对象的一部分,所以 UI 可以翻译它们,但它似乎并不容易支持,即“电子邮件已经存在”错误可能是 3001 错误,UI 可能会以各种语言显示 3001。是否有任何标准方法可以使用现有的 DataAnnotation 属性来包含附加信息?这样 POCO 模型就会变成这样:
public class ExampleCreateModel
{
[Required(ErrorCode = 3000)]
public string Name { get; set; } = "";
[Required]
[EmailAddress(ErrorMessage = "Invalid email format", ErrorCode = 3001)]
public string Email { get; set; } = "";
}
导致类似这样的错误对象:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-6b30709ed71b7347afd41e0ed58e1ccb-e3ede2ff7591a24d-00",
"errors": {
"Email": [
{ "message": "Email already exists", "errorCode": 3002 }
]
}
}
为了清晰起见,我在这里的目的是让 UI 有机会轻松转换错误代码,同时使用开箱即用的错误响应实现错误一致性。
提前感谢您的任何指点!
【问题讨论】:
-
在errorMessage中添加errorCode怎么样?如
[EmailAddress(ErrorMessage = "[3002]Invalid email format")]。 -
我正在考虑这样做@YiyiYou,但希望有一种更优雅的方法:-)
-
也许您应该从属性类中继承并根据需要覆盖方法。我没有测试,但听起来很合理。
标签: c# asp.net asp.net-core .net-5 modelstate