220

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; }
1
  • 1
    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 Commented May 8, 2013 at 13:27

11 Answers 11

332

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.

Sign up to request clarification or add additional context in comments.

4 Comments

I've used it for Int32 (Int32.MaxValue) and it is ok, thanks!
It does show a stupid validation message though :( The field Fixed price discount must be between 0.01 and 1.79769313486232E+308.
@ppumkin Använd ErrorMessage , i.e. [Range(0.0, Double.MaxValue, ErrorMessage = "your error here")]
@ppumkin inherit from DataAnnotationsModelValidator class to customize error messages
131

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.

4 Comments

This is the best answer here IMHO, no extensions, no seemingly random strings/number, no custom code, and a reasonably sensible error message.
Wow that's cool. Are there any other advantages over using PositiveInfinity instead of maxvalue?
@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.
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.
56

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; }

3 Comments

I updated it to make it the same as the best answer here, since the OP isn't changing his mind lol
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.
@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. =)
43

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.

2 Comments

NO - definitely NOT part of MVC 3 :( BUt that library is a good extension to have any way :)
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).
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.

5 Comments

Why not just [Range(0.0,Decimal.MaxValue)]?
Won't compile, Decimal.MaxValue isn't a constant.
That constant is a nuisance, referring to a resource file for error text is no easier
Now you're making the assumption that the currency is dollar, not Yen or something else.
@jfar Decimal.MaxValue IS a constant. It's just that the Range has no overload to accommodate a decimal.
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 });
        }
    }
}

Comments

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.")]

2 Comments

Your error message should say "greater than or equal to".
Good catch. Added.
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

Comments

0

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

Comments

0

Late answer but I have this:

[Range(1, int.MaxValue)]
public int MyInteger { get; set; }

replace int by whatever numeric type you want. You can also replace 1 with int.MinValue.

Comments

-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.

2 Comments

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
As I pointed out below, but apparently it wasn't appreciated by someone.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.