根据其属性之一(ASP.Net Core 2.0)跳过模型的所有验证

时间:2017-09-08 17:26:14

标签: c# asp.net asp.net-mvc validation asp.net-core

如何在其属性之一上跳过模型的所有验证。例如,如果对象的WillBeDeleted属性为true,则验证程序将跳过所有验证规则。

namespace ViewModel
{
    public class ContactForm : IViewModel
    {
        [ValidateNever]
        public Contact Item { get; set; }

        public Category Category { get; set; }

        [Required, DisplayName("First name")]
        [StringLength(200, ErrorMessage = "First name should not exceed 200 characters.")]
        public string FirstName { get; set; }

        [Required, DisplayName("Last name")]
        [StringLength(200, ErrorMessage = "Last name should not exceed 200 characters.")]
        public string LastName { get; set; }

        public List<TelephonesSubForm> Telephones { get; set; } = new List<TelephonesSubForm>();

        public List<EmailsSubForm> Emails { get; set; } = new List<EmailsSubForm>();

        public class TelephonesSubForm : IViewModel
        {
            public int Id { get; set; }

            public bool MustBeDeleted { get; set; }

            [Required]
            public TelephoneAndEmailType Type { get; set; }

            [Required]
            [StringLength(200, MinimumLength = 10, ErrorMessage = "Telephone should not exceed 200 characters.")]
            public string Telephone { get; set; }
        }

        public class EmailsSubForm
        {
            public int Id { get; set; }

            public bool MustBeDeleted { get; set; }

            [Required]
            public TelephoneAndEmailType Type { get; set; }

            [Required]
            [StringLength(200, MinimumLength = 10, ErrorMessage = "Email should not exceed 200 characters.")]
            public string Email { get; set; }
        }
    }
}

在给定的示例模型中,当MustBeDeletedtrue时,表示将在保存操作中删除电子邮件或电话项目。

我搜索并发现有关条件(自定义)验证的几个问题,他们建议在检查验证状态之前从ModelState中删除特定键。就像this一样。

4 个答案:

答案 0 :(得分:0)

虽然这不是问题的完整答案,但可以继承验证属性(RequiredAttributeStringLengthetc)并覆盖IsValid方法。作为样本,我提供其中一个。

public class RequiredWhenItIsNotDeletingAttribute : RequiredAttribute
{
    string DeletingProperty;

    /// <summary>
    /// Check if the object is going to be deleted skip the validation.
    /// </summary>
    /// <param name="deletingProperty">The boolean property which shows the object will be deleted.</param>
    public RequiredWhenItIsNotDeletingAttribute(string deletingProperty = "MustBeDeleted") =>
        DeletingProperty = deletingProperty;

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var property = validationContext.ObjectType.GetProperty(DeletingProperty);

        if((bool)property.GetValue(validationContext.ObjectInstance))
            return ValidationResult.Success;

        return base.IsValid(value, validationContext);
    }
}

答案 1 :(得分:0)

您可以调用方法:

createCache(...)
当MustBeDeleted为真时

答案 2 :(得分:0)

从IValidatableObject继承模型

并实现接口方法:

  public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {

      if (YourCondition==false){
        yield return new ValidationResult(
          $"This is wrong",
          new[] { nameof(Email) });
      }
      else
         yield return ValidationResult.Success

    }

但是您将必须对每个属性进行验证,并排除已经编写的装饰!

答案 3 :(得分:0)

我要添加新答案并保留旧答案,因为这可能对某人有用

因此,创建一个自定义属性:

  public class CustomShouldValidateAttribute : Attribute, IPropertyValidationFilter
  {
    public CustomShouldValidateAttribute(){

    }
    public bool ShouldValidateEntry(ValidationEntry entry, ValidationEntry parentEntry)
    {
      //Here you change this verification to Wether it should verificate or not, In this case we are checking if the property is ReadOnly (Only a get method)
      return !entry.Metadata.IsReadOnly;      
    }
  }

,然后在您的课程上使用自定义属性对其进行修饰

[CustomShouldValidateAttribute]
public class MyClass{
public string Stuff{get;set;}
public string Name {get{return "Furlano";}}
}