1

I regularly use the CompareAttribute data annotation in my models to validate that two fields are equal. For example, most of us use it to compare a password and a confirm password field.

It may seems trivial but I wonder how to use such annotation to compare that two fields are differents. For instance, I would like to verify that the password is different from the username.

For more complex validations, I know I have to use custom validators, but I was just wondering if there was something built-in for that.

Thank you.

JayMF
  • 91
  • 2
  • 12
  • possible duplicate of [Using DataAnnotations to compare two model properties](http://stackoverflow.com/questions/4938078/using-dataannotations-to-compare-two-model-properties) – Raphaël Althaus Feb 10 '14 at 18:29
  • @Raphael: This post does not cover how to verify that two properties are **different**. – JayMF Feb 10 '14 at 18:43
  • I'm going to guess that you would need to override the Match method of this attribute to get what you want at a minimum. – Mike Cheel Feb 10 '14 at 18:53

1 Answers1

4

You have two choices here, create your own ValidationAttribute inheriting from CompareAttribute or inheriting from ValidationAttribute.

1) Custom ValidationAttribute inherit from CompareAttribute

public class NotEqualAttribute : CompareAttribute
{
    public string BasePropertyName { get; private set; }
    private const string DefaultErrorMessage = "'{0}' and '{1}' must not be the same.";
    public MyCustomCompareAttribut(string otherProperty)
        : base(otherProperty)
    {
        BasePropertyName = otherProperty;
    }

    public override string FormatErrorMessage(string name)
    {
        return string.Format(DefaultErrorMessage, name, BasePropertyName);
    }
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var result = base.IsValid(value, validationContext);
        if (result == null)
        {
            return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
        }
        return null;
    }
}

2)Custom ValidationAttribute inherit from ValidationAttribute

  public class NotEqualAttribute : ValidationAttribute
    {
        private const string DefaultErrorMessage = "'{0}' and '{1}' must not be the same.";
        public string BasePropertyName { get; private set; }
        public NotEqualAttribute(string basePropertyName)
            : base(DefaultErrorMessage)
        {
            BasePropertyName = basePropertyName;
        }
        public override string FormatErrorMessage(string name)
        {
            return string.Format(DefaultErrorMessage, name, BasePropertyName);
        }
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var property = validationContext.ObjectType.GetProperty(BasePropertyName);
            if (property == null)
            {
                return new ValidationResult(
                    string.Format(
                        CultureInfo.CurrentCulture, "{0} is invalid property", BasePropertyName
                    )
                );
            }
            var otherValue = property.GetValue(validationContext.ObjectInstance, null);
            if (object.Equals(value, otherValue))
            {
                return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
            }
            return null;
        }
    }

Then you can use either one like:

public class YourModelClass
{
    public string PropertyA{ get; set; }

    [NotEqual("PropertyA")]
    public string PropertyB{ get; set; }
}
Lin
  • 15,078
  • 4
  • 47
  • 49