c# - 使用 ModelState 验证 DTO

标签 c# .net-core asp.net-core-webapi

我正在使用 Code First 方法与 Entity Framework 一起创建 .NET Core WEB API 项目。我无法验证请求的输入,因为 ModelState 验证始终为真。

我的应用程序由 3 层组成。

  • 数据访问层
  • 业务逻辑层
  • .NET 核心 API

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; }
}

对应的DTO:

public class GroupDto
{
    public long GroupId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
}

Controller 方法:

[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);
}

据我所知,在当前状态下 ModelState.IsValid 将始终返回 true,因为 GroupDto 没有通过 DataAnnotations 完成任何验证。

应如何验证 DTO?我想避免在两个地方重复相同的验证。是否应该创建额外的自定义 DtoValidator,或者我是否遗漏了一些东西,并且有办法执行这些验证。

最佳答案

模型状态验证将在传入的模型上进行,在您的例子中是 GroupDto。仅仅因为您最终映射到 Group 类与验证的工作方式无关。您将需要在 DTO 中重复验证属性。这确实重复了代码,但也允许您自定义规则,因为您可能希望也可能不希望在 DTO 中设置完全相同的规则。这方面的一个例子是您的主键。对于创建 (POST),您不一定希望 GroupId 成为传递给 Controller ​​的必填字段,因为数据库可能会自动生成该字段(取决于您的设置)。

如果您使用的是 ASP.Net Core 2.1 或更高版本,您现在还可以将 [ApiController] 属性应用于 Controller 类,它会自动应用模型验证规则。这消除了手动检查 ModelState.IsValid 的需要。如果模型无效,系统会自动返回 400 Bad Request。 ( https://learn.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-2.2#annotation-with-apicontroller-attribute )

关于c# - 使用 ModelState 验证 DTO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55425609/

相关文章:

c# - 关闭颁发者验证或修改 IdentityServer4 中的有效颁发者

c# - 如何在 linq c# 中编写下面的 sql 查询,其中某些参数有时会为 null

c# - 如何在代码隐藏中添加 GridView 列?

C# DotNet 核心中间件包装响应

c# - 如何为 {id}/visit 创建有效路线?

c# - 如何在 ASP.NET Core 2.1 出现第一个错误后停止验证

c# - ASP.NET MVC 4 异步 Controller 回调

asp.net-core - 为什么默认的 mvc6 模板针对多个 DNX 版本?

c# - ASP.NET Core2.2 中使用 CancellationToken 取消内部任务

c# - .Net Core Api - 基于请求值的自定义 JSON 解析器