210

I would like to specify that a decimal field for a price must be >= 0 but I don't really want to impose a max value.

Here's what I have so far...I'm not sure what the correct way to do this is.

[Range(typeof(decimal), "0", "??"] public decimal Price { get; set; }
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
user169867
  • 5,732
  • 10
  • 39
  • 56
  • Surely if this is going into a database you would need to specify the maximum allowed number based upon the selected database type? Otherwise you will get a nasty exception if this number is exceeded – Paul C May 08 '13 at 13:27

10 Answers10

316

How about something like this:

[Range(0.0, Double.MaxValue, ErrorMessage = "The field {0} must be greater than {1}.")]

That should do what you are looking for and you can avoid using strings.

carlin.scott
  • 6,214
  • 3
  • 30
  • 35
Jacob
  • 3,177
  • 2
  • 14
  • 3
125

If you are concerned about the string looking nice you could do this:

    [Range(0, Double.PositiveInfinity)]

This will have a default error message of:

The field SuchAndSuch must be between 0 and Infinity.

Jordan
  • 9,642
  • 10
  • 71
  • 141
  • 13
    This is the best answer here IMHO, no extensions, no seemingly random strings/number, no custom code, and a reasonably sensible error message. – Vitani Mar 14 '16 at 15:12
  • Wow that's cool. Are there any other advantages over using PositiveInfinity instead of maxvalue? – Enrico Jan 24 '22 at 13:49
  • 1
    @Enrico The meaningful message looks like the big advantage. Are there _dis_advantages? I wonder what happens if you enter a value too large for your database and less than infinity? In practice, I doubt I'll ever worry about it. – Auspex Jan 25 '22 at 12:40
  • 1
    This is good, but technically, a decimal has a max value of `79,228,162,514,264,337,593,543,950,335`, which is not infinite. Easy for a user to understand, but is technically wrong. As developers we have a habit to make things simple but wrong. – Marius Oct 19 '22 at 13:12
54

It seems there's no choice but to put in the max value manually. I was hoping there was some type of overload where you didn't need to specify one.

[Range(typeof(decimal), "0", "79228162514264337593543950335")]
public decimal Price { get; set; }
CarenRose
  • 1,266
  • 1
  • 12
  • 24
user169867
  • 5,732
  • 10
  • 39
  • 56
  • 19
    This code just look awful. I would suggest using http://dataannotationsextensions.org/ via nuget and as @Nicolai Schlenzig answered. Use `[Min(0)]` - This also has a better validation message. I would suggest updating your answer – Piotr Kula Jul 19 '13 at 09:36
  • I updated it to make it the same as the best answer here, since the OP isn't changing his mind lol – Worthy7 Feb 01 '17 at 01:18
  • The answers above (@Jordan and @Jacob) are much more appropriate. Especially since we are talking about Price. I understand that many times transactions have to be done with decimal values but there isn't any price 1.234 dollars or at least most of the times you don't want to show this to the user. – Anastasios Selmani Oct 13 '17 at 08:53
  • @AnastasiosSelmanis, I agree with you, expect the part when you say "but there isn't any price 1.234 dollars". You are assuming USD, and even then, when you use this for foreign exchange (though not mentioned here by OP), USD does go into more decimals. =) – RoLYroLLs Apr 02 '18 at 03:28
41

You can use:

[Min(0)]

This will impose a required minimum value of 0 (zero), and no maximum value.

You need DataAnnotationsExtensions to use this.

  • 12
    No I don't think this is correct. It is not part of the standard MVC3 framework it is from Data Annotations Extensions http://dataannotationsextensions.org/. Please provide a MSDN link. – Bernie White Apr 21 '12 at 10:10
  • 2
    NO - definitely NOT part of MVC 3 :( BUt that library is a good extension to have any way :) – Piotr Kula Jul 19 '13 at 09:30
  • 2
    Not part of MVC3 but it is not important. If you want validation on client side, you just need to use DataAnnotationsExtensions.MVC3 package. These two packages are available on nuget. I think that it is the best approach, as you don't have a stupid error message or don't need to redefine the error message each time you want to validate positive integer or decimal (which is fairly common). – gentiane Jan 22 '14 at 17:28
23

If you're working with prices, I'm sure you can safely assume nothing will cost more than 1 trillion dollars.

I'd use:

[Range(0.0, 1000000000000)]

Or if you really need it, just paste in the value of Decimal.MaxValue (without the commas): 79,228,162,514,264,337,593,543,950,335

Either one of these will work well if you're not from Zimbabwe.

CarenRose
  • 1,266
  • 1
  • 12
  • 24
John Farrell
  • 24,673
  • 10
  • 77
  • 110
13

You can use custom validation:

    [CustomValidation(typeof(ValidationMethods), "ValidateGreaterOrEqualToZero")]
    public int IntValue { get; set; }

    [CustomValidation(typeof(ValidationMethods), "ValidateGreaterOrEqualToZero")]
    public decimal DecValue { get; set; }

Validation methods type:

public class ValidationMethods
{
    public static ValidationResult ValidateGreaterOrEqualToZero(decimal value, ValidationContext context)
    {
        bool isValid = true;

        if (value < decimal.Zero)
        {
            isValid = false;
        }

        if (isValid)
        {
            return ValidationResult.Success;
        }
        else
        {
            return new ValidationResult(
                string.Format("The field {0} must be greater than or equal to 0.", context.MemberName),
                new List<string>() { context.MemberName });
        }
    }
}
Erikas Pliauksta
  • 1,402
  • 1
  • 14
  • 22
4

I was going to try something like this:

[Range(typeof(decimal), ((double)0).ToString(), ((double)decimal.MaxValue).ToString(), ErrorMessage = "Amount must be greater than or equal to zero.")]

The problem with doing this, though, is that the compiler wants a constant expression, which disallows ((double)0).ToString(). The compiler will take

[Range(0d, (double)decimal.MaxValue, ErrorMessage = "Amount must be greater than zero.")]
David T. Macknet
  • 3,112
  • 3
  • 27
  • 36
2

using Range with

[Range(typeof(Decimal), "0", "9999", ErrorMessage = "{0} must be a decimal/number between {1} and {2}.")]

[Range(typeof(Decimal),"0.0", "1000000000000000000"]

Hope it will help

Abi
  • 724
  • 6
  • 22
1

[Range(0.01,100000000,ErrorMessage = "Price must be greter than zero !")]

Sohail Akhter
  • 55
  • 1
  • 9
-2

I would put decimal.MaxValue.ToString() since this is the effective ceiling for the decmial type it is equivalent to not having an upper bound.

Dr Herbie
  • 3,930
  • 1
  • 25
  • 28
  • 5
    The problem is that is not a constant. You'll get this error: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type – user169867 Jul 27 '10 at 16:54
  • As I pointed out below, but apparently it wasn't appreciated by someone. – David T. Macknet Sep 20 '16 at 20:10