123

Validation using attributes in asp.net mvc is really nice. I have been using the [Range(min, max)] validator this far for checking values, like e.g.:

[Range(1, 10)]
public int SomeNumber { get; set; }

However - now I need to check the min and max condition separately. I expected to find attributes like these:

[MinValue(1, "Value must be at least 1")]
[MaxValue(10, "Value can't be more than 10")]
public int SomeNumber { get; set; }

Are there any predefined attributes for writing this? Or how do I achieve this?

stiank81
  • 25,418
  • 43
  • 131
  • 202
  • FluentValidation can be another solution to solve the date range. [Here is my answer to another question that might be helpful](https://stackoverflow.com/questions/21777412/mvc-model-validation-for-date). – Zinov Dec 06 '16 at 14:52

4 Answers4

226

I don't think min/max validations attribute exist. I would use something like

[Range(1, Int32.MaxValue)]

for minimum value 1 and

[Range(Int32.MinValue, 10)]

for maximum value 10

Guy
  • 5,370
  • 6
  • 25
  • 30
  • 25
    It is a bit hacky.. but sometimes hacks make me feel more comfortable :) – Guy Aug 31 '11 at 16:03
  • Went with this, but had problems once we were dealing with huge floating point values. – Jonn Nov 19 '12 at 01:45
  • @Jonn: I know it is late but might be usefull to someone else too in the future. There is also `Int64.MaxValue; // = 9223372036854775807L`, `UInt64.MaxValue; // = 18446744073709551615UL`, `double.MaxValue; // = 1.79769313486232E+308`, `Single.MaxValue; // Same as float.MaxValue = 3.402823E+38f`. there should be an option for any job I would assume. Note `decimal.MaxValue` won't work as it is not a constant. – Nope Dec 18 '12 at 19:05
  • Tried this, but found jquery validator (1.11.0) interprets the values as text. Range was set to "0"-"2147483647" `int.MaxValue` - any value that textually is less will work, eg "2047" (less than "2147") but "3" is more than "2" so failed. Had to set range 0 to 999999999 but would probably go with custom attribute as per other answer if that extra digit was really needed. – freedomn-m Nov 27 '13 at 18:27
  • 4
    This approach is fine as long as you override the default error message or you will get something horrible like: "Property x must be between -2e^31-1 and 10". – Russell Horwood Oct 02 '14 at 15:31
  • 1
    The default message would display as "The field {field_name} must be between 1 and 2147483647.". I've edited the answer to add custom error messages which you can set to something more sensible. – thelem May 17 '16 at 14:23
  • 2
    `RangeAttribute` has `AllowMultiple = false`, so this cannot compile. – Daniel Schilling Aug 03 '18 at 21:38
59

Here is how I would write a validator for MaxValue

public class MaxValueAttribute : ValidationAttribute
    {
        private readonly int _maxValue;

        public MaxValueAttribute(int maxValue)
        {
            _maxValue = maxValue;
        }

        public override bool IsValid(object value)
        {
            return (int) value <= _maxValue;
        }
    }

The MinValue Attribute should be fairly the same

Charles Ouellet
  • 6,338
  • 3
  • 41
  • 57
  • Ok, was expecting that they exist, but fair enough to write them. Thx! – stiank81 Aug 31 '11 at 12:40
  • 3
    Just FYI this would not magically validate the form on the Javascript end. You would need to write additional code + js for that. – basarat Mar 15 '13 at 01:30
  • 3
    @basarat actually you won't need extra JS, the jquery validation library already has functions for min/max, you just need to implement the `IClientValidation` interface on the above attribute and return the correct values from the `GetClientValidationRules` method – WickyNilliams Sep 06 '13 at 13:56
  • @WickyNilliams would you add an answer with an example of your comment, or CharlesOuellet will you edit this answer with an example of Wicky's comment? I would love to upvote a working example that includes client side validation. – Johnie Karr May 24 '16 at 21:27
  • @JohnieKarr I don't work with .NET anymore, so I can't provide much of an answer. That said, [this answer below](http://stackoverflow.com/a/11486387/135778) seems to show exactly what I described – WickyNilliams May 25 '16 at 08:36
  • I agree with @WickyNilliams, the answer below uses built-in validation attributes to JS validation will work out of the box. I would like to update my answer but haven't worked in MVC for a while and most of the time I did not need client side validation in the projects I was working on. – Charles Ouellet May 25 '16 at 14:11
41

A complete example of how this could be done. To avoid having to write client-side validation scripts, the existing ValidationType = "range" has been used.

public class MinValueAttribute : ValidationAttribute, IClientValidatable
{
    private readonly double _minValue;

    public MinValueAttribute(double minValue)
    {
        _minValue = minValue;
        ErrorMessage = "Enter a value greater than or equal to " + _minValue;  
    }

    public MinValueAttribute(int minValue)
    {
        _minValue = minValue;
        ErrorMessage = "Enter a value greater than or equal to " + _minValue;
    }

    public override bool IsValid(object value)
    {
        return Convert.ToDouble(value) >= _minValue;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule();
        rule.ErrorMessage = ErrorMessage;
        rule.ValidationParameters.Add("min", _minValue);
        rule.ValidationParameters.Add("max", Double.MaxValue);
        rule.ValidationType = "range";
        yield return rule;
    }

}
Tundey
  • 2,926
  • 1
  • 23
  • 27
Mario
  • 411
  • 4
  • 2
  • 8
    Great answer. I would modify the error message a bit: "Enter a value greater than or equal to " is a more (grammatically-speaking) correct error message. – Tieson T. Jul 26 '12 at 00:04
0

jQuery Validation Plugin already implements min and max rules, we just need to create an adapter for our custom attribute:

public class MaxAttribute : ValidationAttribute, IClientValidatable
{
    private readonly int maxValue;

    public MaxAttribute(int maxValue)
    {
        this.maxValue = maxValue;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule();

        rule.ErrorMessage = ErrorMessageString, maxValue;

        rule.ValidationType = "max";
        rule.ValidationParameters.Add("max", maxValue);
        yield return rule;
    }

    public override bool IsValid(object value)
    {
        return (int)value <= maxValue;
    }
}

Adapter:

$.validator.unobtrusive.adapters.add(
   'max',
   ['max'],
   function (options) {
       options.rules['max'] = parseInt(options.params['max'], 10);
       options.messages['max'] = options.message;
   });

Min attribute would be very similar.

Benas Radzevicius
  • 279
  • 1
  • 3
  • 17