Asp.net-mvc – Changing validation range programmatically (MVC3 ASP.NET)

asp.net-mvcasp.net-mvc-3validation

Let's say I have this view model:


    public class MyModel
    {
        [Range(0, 999, ErrorMessage = "Invalid quantity")]
        public int Quantity { get; set; }
    }

Now, for specific instances of this model the range of valid values will change: some may not be 0, some may not be higher than 5. The min/max values for the valid ranges are coming from the DB and can change anytime.

How do I change the min/max properties of the RangeAttribute on the fly? Or what it the best way to validate my scenario?

Best Answer

Something along the lines of this might be more what your after...

ViewModel:

public class ViewModel
{
    public DateTime MinDate {get; set;}
    public DateTime MaxDate {get; set;}

    [DynamicRange("MinDate", "MaxDate", ErrorMessage = "Value must be between {0} and {1}")]
    public DateTime Date{ get; set; }
}

Library class or elsewhere:

public class DynamicRange : ValidationAttribute, IClientValidatable
    {
        private readonly string _minPropertyName;
        private readonly string _maxPropertyName;

    public DynamicRange(string minPropName, string maxPropName)
    {
        _minPropertyName = minPropName;
        _maxPropertyName = maxPropName;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var minProperty = validationContext.ObjectType.GetProperty(_minPropertyName);
        var maxProperty = validationContext.ObjectType.GetProperty(_maxPropertyName);

        if(minProperty == null)
            return new ValidationResult(string.Format("Unknown property {0}", _minPropertyName));

        if (maxProperty == null)
            return new ValidationResult(string.Format("Unknown property {0}", _maxPropertyName));

        var minValue = (int) minProperty.GetValue(validationContext.ObjectInstance, null);
        var maxValue = (int) maxProperty.GetValue(validationContext.ObjectInstance, null);

        var currentValue = (int) value;

        if (currentValue <= minValue || currentValue >= maxValue)
        {
            return new ValidationResult(string.Format(ErrorMessage, minValue, maxValue));
        }

        return null;
    }

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

        rule.ValidationParameters["minvalueproperty"] = _minPropertyName;
        rule.ValidationParameters["maxvalueproperty"] = _maxPropertyName;
        yield return rule;
    }

From: MVC unobtrusive range validation of dynamic values

Related Topic