ban*_*neh 1 c# .net-core asp.net-core-webapi
我正在使用代码优先方法与实体框架一起创建 .NET Core WEB API 项目。我无法验证来自请求的输入,因为 ModelState 验证始终为真。
我的应用程序由 3 层组成。
DAL 中的示例数据模型:
public class Group
{
[Key]
[Required]
public long GroupId { get; set; }
[Required]
public string Name { get; set; }
[Required(AllowEmptyStrings = false)]
public string Description { get; set; }
public DateTime CreationDate { get; set; }
public bool IsActive { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
对应的 DTO:
public class GroupDto
{
public long GroupId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
控制器方法:
[HttpPost]
public IActionResult Post([FromBody] GroupDto groupDto)
{
Group group = _mapper.Map<Group>(groupDto);
if (!ModelState.IsValid)
{
return BadRequest();
}
_groupService.Add(group);
groupDto = _mapper.Map<GroupDto>(group);
return Ok(groupDto);
}
Run Code Online (Sandbox Code Playgroud)
据我了解,在当前状态下 ModelState.IsValid 将始终返回 true,因为 GroupDto 没有通过 DataAnnotations 完成任何验证。
应如何验证 DTO?我想避免在两个地方重复相同的验证。是否应该创建额外的自定义 DtoValidator 或者我是否缺少一些东西,并且有办法执行这些验证。
模型状态验证将发生在传入的模型上,在您的情况下是 GroupDto。仅仅因为您最终映射到 Group 类与验证如何工作无关。您将需要在 DTO 中重复验证属性。这确实会复制代码,但也允许您自定义规则,因为您可能希望也可能不希望 DTO 中的设置完全相同。这方面的一个例子是您的主键。对于创建 (POST),您不一定希望 GroupId 成为传递给控制器的必填字段,因为数据库可能会自动生成该字段(取决于您的设置)。
如果您使用的是 ASP.Net Core 2.1 或更高版本,您现在还可以将 [ApiController] 属性应用于控制器类,它会自动应用模型验证规则。这消除了手动检查 ModelState.IsValid 的需要。如果模型无效,系统将自动返回 400 Bad Request。(https://docs.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-2.2#annotation-with-apicontroller-attribute)