【发布时间】:2018-08-28 05:38:05
【问题描述】:
测试我的 Web API(nuget 包 Microsoft.AspNetCoreAll 2.0.5)我在使用注释进行模型验证时遇到了奇怪的问题。
我有(例如)这个控制器:
[HttpPost]
public IActionResult Create([FromBody] RequestModel request)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
// create
request.Name.DoSomething();
return Created(...);
}
我将我的 RequestModel 定义如下:
public class RequestModel
{
[Required]
public string Name {get; set};
}
我的问题虽然我将 RequestModel.Name 定义为 [Required],但它为 null(如果 Name 不存在于正文中的 json 中。我认为这不应该发生,因为它被标记为 [Required] 并自动显示为模型状态错误。
鉴于this link to the specs,他们使用 Bind(....)。
所以我的问题? 我是否必须每次都启用它,还是应该开箱即用,或者它打算如何使用?
如果我用 [Required] 对其进行注释,我会假设至少 ModelState.IsValid 如果不存在则返回 false。
在我有多个对象相互嵌套的情况下,在链接中使用 Bind 对我来说似乎有点复杂。
编辑 1:创建 MVC 数据验证测试平台 为了更好地形象化我的意思,以便每个人都可以轻松地自己进行实验,我在 GitHub 上创建了一个小演示 .NET Core MVC data validation test bed。
您可以下载代码,使用 VS 2017 启动它,然后使用 swagger ui 自己尝试一下。
拥有这个模型:
public class StringTestModel2
{
[Required]
public string RequiredStringValue { get; set; }
}
并使用该控制器对其进行测试:
[HttpPost("stringValidationTest2")]
[SwaggerOperation("StringValidationTest2")]
public IActionResult StringValidationTest2([FromBody] StringTestModel2 request)
{
LogRequestModel("StringValidationTest2", request);
if (!ModelState.IsValid)
{
LogBadRequest(ModelState);
return BadRequest(ModelState);
}
LogPassedModelValidation("StringValidationTest2");
return Ok(request);
}
结果与预期相差甚远:
- 允许给出 null(不是字符串“null”)并返回 200 OK
- 允许提供 int 并返回 200 OK(它被转换为字符串)
- 允许提供双精度并返回 200 OK(如果可能,它会转换为字符串,如果不可转换(混合点和分号返回 400 Bad Request)
- 如果您只是发送空的大括号并将RequiredStringValue 保留为未定义,则它通过并返回200 OK(字符串为空)。
让我(现在)得出以下结论之一:
- 两种 MVC 数据验证都不能开箱即用
- 其中任何一个都无法按预期工作(如果有人根据需要标记属性,则应确保它存在)
- 任何一个 MVC 数据验证被破坏
- 任何一种 MVC 数据验证都完全没用
- 我们遗漏了一些重要的点(例如 Bind[])
【问题讨论】:
-
它应该开箱即用。你不需要激活任何东西。如果您不想在每个控制器操作中检查模型状态,您可以使用操作过滤器。
-
如果它应该开箱即用,那么所需的名称如何为空并且验证不会自动抛出错误?
-
您确定该字符串不包含空格还是可能发生任何类似的事情。
-
实际上,如果它只包含空格,它甚至应该可以工作。你能用上面添加的模型重现这个问题吗?还是只发生在具有嵌套对象的模型上?
-
嗯,空值不在任何嵌套类中,而是在“根”中。我目前正在构建一个专用的测试应用程序。希望明天完成。
标签: c# asp.net-core asp.net-core-mvc asp.net-core-2.0 asp.net-core-webapi