Como especificar um decimal mínimo, mas não decimal máximo, usando o atributo de anotação de dados do intervalo?

150

Gostaria de especificar que um campo decimal para um preço deve ser> = 0, mas não quero impor um valor máximo.

Aqui está o que tenho até agora ... Não sei qual é a maneira correta de fazer isso.

[Range(typeof(decimal), "0", "??"] public decimal Price { get; set; }
user169867
fonte
Certamente, se isso estiver entrando em um banco de dados, você precisará especificar o número máximo permitido com base no tipo de banco de dados selecionado? Caso contrário, você receberá uma exceção desagradável se este número for excedido
Coops

Respostas:

226

Que tal algo como isso:

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

Isso deve fazer o que você está procurando e pode evitar o uso de strings.

Jacob
fonte
1
Eu usei para Int32 (Int32.MaxValue) e está tudo bem, obrigado!
Bronek
15
Ele mostra uma mensagem estúpida validação embora :(The field Fixed price discount must be between 0.01 and 1.79769313486232E+308.
Piotr Kula
16
@ppumkin Resposta ErrorMessage, ou seja, [Range (0.0, Double.MaxValue, ErrorMessage = "seu erro aqui")]
flafffl
Obrigado Jacob. Ótima resposta!
Pimbrouwers
1
@ppumkin herdar de uma classe DataAnnotationsModelValidator personalizar mensagens de erro
Alexander
91

Se você está preocupado com a aparência da string, você pode fazer o seguinte:

    [Range(0, Double.PositiveInfinity)]

Isso terá uma mensagem de erro padrão de:

O campo SuchAndSuch deve estar entre 0 e Infinito.

Jordânia
fonte
11
Esta é a melhor resposta aqui IMHO, sem extensões, sem seqüências aparentemente aleatórias / número, sem código personalizado e uma mensagem de erro razoavelmente sensata.
Vitani 14/03
42

Parece que não há escolha a não ser colocar o valor máximo manualmente. Eu esperava que houvesse algum tipo de sobrecarga em que você não precisasse especificar um.

[Range(typeof(decimal), "0", "79228162514264337593543950335")]
public decimal Price { get; set; }
user169867
fonte
14
Este código parece horrível. Eu sugeriria o uso de dataannotationsextensions.org via nuget e como @Nicolai Schlenzig respondeu. Use [Min(0)]- também possui uma mensagem de validação melhor. Sugiro atualizar sua resposta
Piotr Kula
I atualizado para torná-lo o mesmo que a melhor resposta aqui, já que o OP não está mudando sua mente lol
Worthy7
As respostas acima (@Jordan e @Jacob) são muito mais apropriadas. Especialmente porque estamos falando de preço. Entendo que muitas vezes as transações precisam ser feitas com valores decimais, mas não há preço de 1.234 dólares ou, pelo menos, na maioria das vezes, você não deseja mostrar isso ao usuário.
Anastasios Selmanis
@AnastasiosSelmanis, concordo com você, espere a parte quando você disser "mas não há nenhum preço 1,223 dólares". Você está assumindo o dólar e, mesmo assim, quando o usa para câmbio (embora não seja mencionado aqui pelo OP), o dólar entra em mais casas decimais. =)
RoLYroLLs
35

Você pode usar:

[Min(0)]

Isso imporá um valor mínimo necessário de 0 (zero) e nenhum valor máximo.

Você precisa DataAnnotationsExtensions para usar isso.

Nicolai Schlenzig
fonte
8
Não, eu não acho que isso esteja correto. Não faz parte da estrutura padrão do MVC3, mas sim da Data Annotations Extensions dataannotationsextensions.org . Forneça um link do MSDN.
Bernie Branca
1
NO - definitivamente não é parte da MVC 3 :( Mas essa biblioteca é uma extensão do bom ter qualquer maneira :)
Piotr Kula
1
Não faz parte do MVC3, mas não é importante. Se você deseja validação no lado do cliente, basta usar o pacote DataAnnotationsExtensions.MVC3. Esses dois pacotes estão disponíveis no nuget. Eu acho que é a melhor abordagem, pois você não tem uma mensagem de erro estúpida ou não precisa redefinir a mensagem de erro toda vez que deseja validar um número inteiro positivo ou decimal (o que é bastante comum).
Gentian
21

Se você trabalha com preços, tenho certeza de que pode assumir com segurança que nada custará mais de 1 trilhão de dólares.

Eu usaria:

[Range(0.0, 1000000000000)]

Ou, se você realmente precisar, basta colar o valor de Decimal.MaxValue(sem vírgulas):79,228,162,514,264,337,593,543,950,335

Qualquer um deles funcionará bem se você não for do Zimbábue.

John Farrell
fonte
7
Por que não apenas [Range(0.0,Decimal.MaxValue)]?
Coops
4
Não será compilado, Decimal.MaxValue não é uma constante.
John Farrell
Essa constante é um incômodo, referindo-se a um arquivo de recurso para texto de erro não é mais fácil
Coops
3
Agora você está assumindo que a moeda é dólar, não iene ou outra coisa.
Fred
1
@jfar Decimal.MaxValue É uma constante. Só que o Range não tem sobrecarga para acomodar um decimal.
Ε Г И І И О
11

Você pode usar a validação personalizada:

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

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

Tipo de métodos de validação:

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
fonte
2

Eu tentaria algo assim:

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

O problema de fazer isso, porém, é que o compilador deseja uma expressão constante, o que não permite ((double)0).ToString(). O compilador irá assumir

[Range(0d, (double)decimal.MaxValue, ErrorMessage = "Amount must be greater than zero.")]
David T. Macknet
fonte
Quem recusou isso explicaria por que você acha que minha solução é ruim ou não é útil? Porque apenas a votação sem explicação é totalmente inútil.
David T. Macknet
Sua mensagem de erro deve dizer "maior que ou igual a".
Ε Г И І И О
Boa pegada. Adicionado.
David T. Macknet
1

usando Range com

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

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

Espero que ajude

Abi
fonte
1

[Intervalo (0,01,100000000, ErrorMessage = "O preço deve ser maior que zero!")]

Sohail Akhter
fonte
0

Eu diria que, decimal.MaxValue.ToString()como esse é o teto efetivo para o tipo decmial, é equivalente a não ter um limite superior.

Dr Herbie
fonte
4
O problema é que não é uma constante. Você obterá este erro: Um argumento atributo deve ser uma expressão constante, typeof expressão ou matriz expressão de criação de um tipo de parâmetro atributo
user169867
Como apontei abaixo, mas aparentemente não foi apreciado por alguém.
David T. Macknet