ASP.NET MVC3 Model Validation DataAnnotations to do less than or equal to another property with client side validation

10,372

Solution 1

Have a look at this article. It explains how to extend the ASP.NET MVC model validation to support cross-field validation:

Extending ASP.NET MVC’s Validation
http://blogs.msdn.com/b/mikeormond/archive/2010/10/05/extending-asp-net-mvc-s-validation.aspx

Solution 2

Robert Harvey's answer put me on the right path but it is possible with ASP.NET MVC3 to quite simply override the validation using the following pattern:

public class LessThanOrEqualToPropertyAttribute : ValidationAttribute, IClientValidatable
{
    public string OtherProperty { get; set; }

    public override bool IsValid(object value)
    {
        return true;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value != null)
        {
            PropertyInfo propertyInfo = validationContext.ObjectType.GetProperty(OtherProperty);

            var otherValue = propertyInfo.GetGetMethod().Invoke(validationContext.ObjectInstance, null);

            if ((int)otherValue < (int)value)
                return new ValidationResult(ErrorMessage);

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

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule
        {
            ValidationType = "lessthanorequaltoproperty",
            ErrorMessage = FormatErrorMessage(ErrorMessage),
        };

        rule.ValidationParameters.Add("otherproperty", OtherProperty);

        yield return rule;
    }
}

This wasn't exactly clear from the various conflicting documentation I found.

Solution 3

I know this is late, but to piggy back on RSL's excellent self-answer, the only thing really missing was the client script to add an unobtrusive validation adapter. Good example of such over here.

Share:
10,372
Rob Stevenson-Leggett
Author by

Rob Stevenson-Leggett

I love to code and snowboard. Follow me on twitter: @rsleggett

Updated on June 04, 2022

Comments

  • Rob Stevenson-Leggett
    Rob Stevenson-Leggett about 2 years

    I have a simple form which is using ASP.NET MVC 3 unobtrusive client side validation.

    The model looks a bit like this (names changed for privacy):

    public class MyInputModel
    {
        public MyInputModel()
        {
        }
    
        public MyInputModel(MyViewData viewData)
        {
            ViewData = viewData;
            MaxValueForSize = viewData.MaxSize;
        }
    
        public int MaxValueForSize { get; set; }
    
    
        [RegularExpression("[1-9][0-9]*",ErrorMessage = "The value must be a whole number.")]
        public int Size { get; set; }
    
        [StringLength(255)]
        [Required]
        public string Description{ get; set; }
    }
    

    In my view I put a hidden field in for MaxValueForSize and I want to compare the entered value for Size to less than or equal to the MaxValueForSize property.

    I know I can do this server side by overriding validation attribute like so:

    internal class SizeValidAttribute : ValidationAttribute
    {
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if(value != null)
            {
                var model = (MyInputModel) validationContext.ObjectInstance;
    
    
                if ((int)value > model.MaxValueForSize)
                    return new ValidationResult(ErrorMessage);
    
            }
            return base.IsValid(value, validationContext);
        }
    }
    

    However I would like to (need to) have client side validation on this property. Similar to how the Compare annotation works.

    Does anyone know of a way to do this? Do I need to extend the client side validation somehow?

    Thanks for your help.