【问题标题】:How to validate only a part of Model State in asp.net core 2 web api如何在asp.net core 2 web api中仅验证模型状态的一部分
【发布时间】:2019-03-16 05:48:00
【问题描述】:

我们在 2 个不同的项目中使用了 Usermaster DTO。

public class UserMaster : BaseProperties
{      

    [BsonElement]
    [BsonRequired]
    [Required]
    public string FirstName { get; set; }

    [BsonElement]
    [BsonRequired]
    [Required]
    public string LastName { get; set; }

    [BsonElement]
    [BsonRequired]
    [EmailAddress]
    [Required]
    public string EmailId { get; set; }

    [BsonElement]
    [BsonRequired]
    [DataType(DataType.Password)]
    [Required]
    public string Password { get; set; }

    [BsonIgnore]
    [DataType(DataType.Password)]
    [Required]
    public string NewPassword { get; set; }        
}

现在我们在 2 个不同的项目中使用这个 DTO。
项目 1 在 asp.net MVC 5.0 中是 Admin,我们可以使用 ModelState.IsValidField 来验证整个模型的一部分。
Project 2 是在 asp.net core 2 中构建的 Web Api。我找不到任何只能验证电子邮件和密码以用于登录目的的解决方案。

基本上我在 asp.net core 2 web api 中遇到问题,我无法指定只能验证的确切数据成员。我必须在其他 [Required] 字段上传递任何内容来验证请求。同样是 ModelState.IsValidField

有什么解决办法吗??

【问题讨论】:

  • 不要在两个项目中使用相同的 DTO。如果您有不同的验证要求,则表明您需要不同的 DTO。此外,Model 是为 View 服务的。如果它有 anything 阻止它这样做,则不应将它用作 that 视图的模型。
  • 在我看来你想把 this 分成两个类,因为目的不同
  • 创建一个适合视图的新模型,并使用 AutoMapper 等将现有 DTO 映射到它。
  • @PanagiotisKanavos,我们使用 mongoDb 作为与 DTO 强绑定的后端。我们选择这种方式来减少维护工作。否则我们需要在项目中更新每一点更改
  • @Arjun 这就是为什么你不应该使用那个 DTO。它是您的 服务层 DTO,而不是您的 ViewModel。它在 99.99999% 的时间里都不能满足视图的需求。将其映射到适当的 ViewModel 模型。当您需要添加密码强度指示器时,您会怎么做?

标签: c# asp.net asp.net-web-api2 asp.net-core-2.0


【解决方案1】:

在你的 DTO 中实现 IValidatableObject

public class UserMaster : BaseProperties, IValidatableObject
{      

    [BsonElement]
    [BsonRequired]
    [Required]
    public string FirstName { get; set; }

    [BsonElement]
    [BsonRequired]
    [Required]
    public string LastName { get; set; }

    [BsonElement]
    [BsonRequired]
    [EmailAddress]
    [Required]
    public string EmailId { get; set; }

    [BsonElement]
    [BsonRequired]
    [DataType(DataType.Password)]
    [Required]
    public string Password { get; set; }

    [BsonIgnore]
    [DataType(DataType.Password)]
    [Required]
    public string NewPassword { get; set; }      

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
    //you custom validation here...
    }  
}

因此,如果您可以检测到它正在使用的上下文,那么您就在路上...

【讨论】:

  • 不是两个项目都适用吗?
  • public class NewUserMaster : IValidatableObject { [Required] public string EmailId { get; set; } [Required] public string Password { get; set; } IEnumerable&lt;ValidationResult&gt; IValidatableObject.Validate(ValidationContext validationContext) { if (string.IsNullOrEmpty(EmailId)) yield return new ValidationResult("Email is required"); } }
  • 查看上面的示例类(在更好的文本编辑器中),我只发布了电子邮件值,但它也会引发“需要密码”错误。那么如何跳过验证密码字段??
【解决方案2】:

如果您有两个不同的验证要求,那么您应该有两个不同的视图模型/DTO。视图模型/ DTO的整个观点是处理特定的使用场景。在这里,您有两组不同的请求数据,因此您的问题完全在于尝试使用相同的类来满足两者,而这两者并不相同。

如果您想减少代码重复,只需继续使用继承即可:

public class UserLogin : BaseProperties
{
    [BsonElement]
    [BsonRequired]
    [EmailAddress]
    [Required]
    public string EmailId { get; set; }

    [BsonElement]
    [BsonRequired]
    [DataType(DataType.Password)]
    [Required]
    public string Password { get; set; }
}

public class UserMaster : UserLogin
{      

    [BsonElement]
    [BsonRequired]
    [Required]
    public string FirstName { get; set; }

    [BsonElement]
    [BsonRequired]
    [Required]
    public string LastName { get; set; }

    [BsonIgnore]
    [DataType(DataType.Password)]
    [Required]
    public string NewPassword { get; set; }        
}

【讨论】:

  • 是的..我认为这是我的最后一个选择..实际上我被 ModelState.IsValidField 迷住了,所以认为核心中也会有一些溶胶..除此之外我在想,这是只有一个实例..如果在cuming项目模块中有很多这样的场景..我可能会继续依赖继承:(
  • 您必须了解如何最好地设计您的课程。也许继承不是正确的方法。尽管如此,DTO 类本质上是一个特殊用途的类,因此它应该用于该目的,仅此而已。如果你在多个地方做相同类型的事情,它可以被重用,但是试图让一个类甚至一个类层次结构处理所有可能的场景是错误的。此外,为特定 API 端点使用特定类可用作文档。您确切地知道该端点需要什么。
猜你喜欢
  • 1970-01-01
  • 2020-05-22
  • 2018-06-16
  • 1970-01-01
  • 1970-01-01
  • 2019-03-26
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
相关资源
最近更新 更多