137

I'd like to be able to only allow a form to submit if the value in a certain field is greater than 0. I thought maybe the Mvc Range attribute would allow me to enter only 1 value to signify only a greater than test, but no luck there as it insists on Minimum AND Maximum values.

Any ideas how this can be achieved?

jaffa
  • 26,770
  • 50
  • 178
  • 289

4 Answers4

326

You can't store a number bigger than what your underlying data type could hold so that fact that the Range attribute requires a max value is a very good thing. Remember that doesn't exist in the real world, so the following should work:

[Range(1, int.MaxValue, ErrorMessage = "Please enter a value bigger than {1}")]
public int Value { get; set; }
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 2
    The downside of this approach is that if it validates "abcd" it's going to display: `Please enter a value less than or equal to 2147483647`. – Mike Cole Dec 11 '13 at 22:48
  • 1
    you shouldn't be able to enter letters in a numeric field. The problem i have with this is if i enter 9999999999999999999 it says my number is too small. – John Lord Sep 11 '20 at 13:46
36

I found this answer looking to validate any positive value for a float/double. It turns out these types have a useful constant for 'Epsilon'

Represents the smallest positive System.Double value that is greater than zero.

    [Required]
    [Range(double.Epsilon, double.MaxValue)]
    public double Length { get; set; }
Phil
  • 951
  • 12
  • 16
  • 1
    Epsilon is actually a calculus function. It is a "limit" function that basically says "the smallest number that can be distinguished from zero" so you could end up with entries of .00000001. I would put a realistic number on the min. – John Lord Apr 17 '19 at 20:21
  • Given that my numbers _can_ be very small, I don't have a way to calculate just how small, and all I want is to ensure I don't get a divide-by-zero error, this `Epsilon` method is actually exactly what I need – Auspex Apr 18 '23 at 13:41
26

You can create your own validator like this:

    public class RequiredGreaterThanZero : ValidationAttribute
{
    /// <summary>
    /// Designed for dropdowns to ensure that a selection is valid and not the dummy "SELECT" entry
    /// </summary>
    /// <param name="value">The integer value of the selection</param>
    /// <returns>True if value is greater than zero</returns>
    public override bool IsValid(object value)
    {
        // return true if value is a non-null number > 0, otherwise return false
        int i;
        return value != null && int.TryParse(value.ToString(), out i) && i > 0;
    }
}

Then "include" that file in your model and use it as an attribute like this:

    [RequiredGreaterThanZero]
    [DisplayName("Driver")]
    public int DriverID { get; set; }

I commonly use this on dropdown validation. Note that because it's extending validationattribute you can customize the error message with a parameter.

John Lord
  • 1,941
  • 12
  • 27
  • 1
    I ended up using this answer for another situation that did require a custom validator. For simple integer greater than zero validation, Darin's answer should be used. – Zach May 20 '19 at 17:59
  • I actually prefer his method as well, but the people i work with have an issue with "arbitrarily setting limits" on values. – John Lord May 21 '19 at 13:18
  • Ha, that seems strange. I could see their reasoning if the valid range was less than the max integer size. – Zach May 21 '19 at 14:02
  • it's more of an issue with decimals. Without looking, i'm pretty sure that one doesn't have a min or max function built in. – John Lord May 21 '19 at 14:25
  • 1
    This was the best solution for me! – Dave Stuart Dec 30 '19 at 21:36
  • I've implemented a similar solution but called it simply `[Positive]`, and inherited from`RangeAttribute` to utilize framework code as much as possible. – Zoltán Tamási Feb 12 '20 at 14:54
  • We actually don't use this ourselves any more. I implemented a generic "required" function that i created an overload for that treats zero as empty if i tell it to. – John Lord Feb 17 '20 at 00:15
0

The above validator works with integers. I extended this to work with a decimal:

    public class RequiredDecimalGreaterThanZero : ValidationAttribute
    {
        /// <summary>
        /// Designed for dropdowns to ensure that a selection is valid and not the dummy "SELECT" entry
        /// </summary>
        /// <param name="value">The integer value of the selection</param>
        /// <returns>True if value is greater than zero</returns>
        public override bool IsValid(object value)
        {
            // return true if value is a non-null number > 0, otherwise return false
            decimal i;
            return value != null && decimal.TryParse(value.ToString(), out i) && i > 0;
        }
    }
Greg Gum
  • 33,478
  • 39
  • 162
  • 233