Search code examples
c#asp.net-mvcrazorvalidationattribute

Custom validation attribute that compares the value of my property with another property's value in my model class


I want to create a custom validation attribute, in which I want to compare the value of my property with another property's value in my model class. For example I have in my model class:

...    
public string SourceCity { get; set; }
public string DestinationCity { get; set; }

And I want to create a custom attribute to use it like this:

[Custom("SourceCity", ErrorMessage = "the source and destination should not be equal")]
public string DestinationCity { get; set; }
//this wil lcompare SourceCity with DestinationCity

How can I get there?


Solution

  • Here's how you could obtain the other property value:

    public class CustomAttribute : ValidationAttribute
    {
        private readonly string _other;
        public CustomAttribute(string other)
        {
            _other = other;
        }
    
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var property = validationContext.ObjectType.GetProperty(_other);
            if (property == null)
            {
                return new ValidationResult(
                    string.Format("Unknown property: {0}", _other)
                );
            }
            var otherValue = property.GetValue(validationContext.ObjectInstance, null);
    
            // at this stage you have "value" and "otherValue" pointing
            // to the value of the property on which this attribute
            // is applied and the value of the other property respectively
            // => you could do some checks
            if (!object.Equals(value, otherValue))
            {
                // here we are verifying whether the 2 values are equal
                // but you could do any custom validation you like
                return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName));
            }
            return null;
        }
    }