Jak określić minimalną, ale nie maksymalną liczbę dziesiętną za pomocą atrybutu adnotacji danych zakresu?

150

Chciałbym określić, że pole dziesiętne dla ceny musi być> = 0, ale tak naprawdę nie chcę narzucać wartości maksymalnej.

Oto, co mam do tej pory ... Nie jestem pewien, jaki jest właściwy sposób, aby to zrobić.

[Range(typeof(decimal), "0", "??"] public decimal Price { get; set; }
user169867
źródło
Z pewnością, jeśli chodzi o bazę danych, musisz określić maksymalną dozwoloną liczbę w oparciu o wybrany typ bazy danych? W przeciwnym razie otrzymasz paskudny wyjątek, jeśli ta liczba zostanie przekroczona
Coops

Odpowiedzi:

226

Co powiesz na coś takiego:

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

To powinno zrobić to, czego szukasz i możesz uniknąć używania ciągów.

Jakub
źródło
1
Użyłem go do Int32 (Int32.MaxValue) i jest ok, dzięki!
Bronek
15
Ale pokazuje głupi komunikat walidacyjny :(The field Fixed price discount must be between 0.01 and 1.79769313486232E+308.
Piotr Kula
16
@ppumkin Använd ErrorMessage, tj. [Range (0.0, Double.MaxValue, ErrorMessage = "twój błąd tutaj")]
flafffl
Dzięki Jacob. Świetna odpowiedź!
pimbrouwers
1
@ppumkin inherit from DataAnnotationsModelValidator class, aby dostosować komunikaty o błędach
Alexander
91

Jeśli obawiasz się ładnego wyglądu łańcucha, możesz to zrobić:

    [Range(0, Double.PositiveInfinity)]

Spowoduje to wyświetlenie domyślnego komunikatu o błędzie:

Pole SuchAndSuch musi mieć wartość od 0 do Infinity.

Jordania
źródło
11
To najlepsza odpowiedź tutaj IMHO, bez rozszerzeń, bez pozornie przypadkowych ciągów / liczb, bez niestandardowego kodu i rozsądnie rozsądny komunikat o błędzie.
Vitani,
42

Wygląda na to, że nie ma innego wyjścia, jak tylko ręcznie wprowadzić wartość maksymalną. Miałem nadzieję, że wystąpił jakiś rodzaj przeciążenia, w którym nie trzeba było go określać.

[Range(typeof(decimal), "0", "79228162514264337593543950335")]
public decimal Price { get; set; }
user169867
źródło
14
Ten kod po prostu wygląda okropnie. Sugerowałbym użycie dataannotationsextensions.org przez nuget i jak odpowiedział @Nicolai Schlenzig. Użyj [Min(0)]- to również ma lepszy komunikat walidacji. Proponuję zaktualizować swoją odpowiedź
Piotr Kula
Zaktualizowałem go, aby był taki sam, jak najlepsza odpowiedź tutaj, ponieważ OP nie zmienia zdania lol
Worthy7
Odpowiedzi powyżej (@Jordan i @Jacob) są o wiele bardziej odpowiednie. Zwłaszcza, że ​​mówimy o cenie. Rozumiem, że wiele razy transakcje muszą być dokonywane z wartościami dziesiętnymi, ale nie ma ceny 1,234 dolara lub przynajmniej w większości przypadków, gdy nie chcesz tego pokazywać użytkownikowi.
Anastasios Selmanis
@AnastasiosSelmanis, zgadzam się z tobą, spodziewaj się części, kiedy mówisz "ale nie ma ceny 1.234 dolara". Zakładasz USD, a nawet wtedy, gdy używasz tego do wymiany walut (choć nie jest to wspomniane tutaj przez OP), USD ma więcej miejsc po przecinku. =)
RoLYroLLs
35

Możesz użyć:

[Min(0)]

Spowoduje to nałożenie wymaganej wartości minimalnej 0 (zero), ale żadnej wartości maksymalnej.

Aby z tego skorzystać, potrzebujesz DataAnnotationsExtensions .

Nicolai Schlenzig
źródło
8
Nie, nie sądzę, że to prawda. Nie jest częścią standardowej struktury MVC3, pochodzi z rozszerzeń adnotacji danych dataannotationsextensions.org . Podaj łącze MSDN.
Bernie White,
1
NIE - zdecydowanie NIE jest częścią MVC 3 :( Ale ta biblioteka jest dobrym rozszerzeniem, żeby mieć jakikolwiek sposób :)
Piotr Kula
1
Nie jest częścią MVC3, ale nie jest ważne. Jeśli chcesz sprawdzać poprawność po stronie klienta, wystarczy użyć pakietu DataAnnotationsExtensions.MVC3. Te dwa pakiety są dostępne w nuget. Myślę, że jest to najlepsze podejście, ponieważ nie masz głupiego komunikatu o błędzie lub nie musisz redefiniować komunikatu o błędzie za każdym razem, gdy chcesz sprawdzić dodatnią liczbę całkowitą lub dziesiętną (co jest dość powszechne).
gentiane
21

Jeśli pracujesz z cenami, jestem pewien, że możesz bezpiecznie założyć, że nic nie będzie kosztować więcej niż 1 bilion dolarów.

Użyłbym:

[Range(0.0, 1000000000000)]

Lub jeśli naprawdę tego potrzebujesz, po prostu wklej wartość Decimal.MaxValue(bez przecinków):79,228,162,514,264,337,593,543,950,335

Każdy z nich będzie działał dobrze, jeśli nie jesteś z Zimbabwe.

John Farrell
źródło
7
Dlaczego nie po prostu [Range(0.0,Decimal.MaxValue)]?
Coops
4
Nie skompiluje, Decimal.MaxValue nie jest stałą.
John Farrell
Ta stała jest uciążliwa, odwoływanie się do pliku zasobów dla tekstu błędu nie jest łatwiejsze
Coops
3
Teraz zakładasz, że walutą jest dolar, a nie jen czy coś innego.
Fred
1
@jfar Decimal.MaxValue JEST stałą. Po prostu Range nie ma przeciążenia, aby pomieścić ułamek dziesiętny.
Ε Г И І И О
11

Możesz użyć niestandardowej weryfikacji:

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

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

Typ metod walidacji:

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
źródło
2

Chciałem spróbować czegoś takiego:

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

Problem z tym polega jednak na tym, że kompilator potrzebuje stałego wyrażenia, co jest zabronione ((double)0).ToString(). Kompilator będzie brać

[Range(0d, (double)decimal.MaxValue, ErrorMessage = "Amount must be greater than zero.")]
David T. Macknet
źródło
Czy ktokolwiek by to zlekceważył, mógłby wyjaśnić, dlaczego uważasz, że moje rozwiązanie jest słabe lub nieprzydatne? Ponieważ samo głosowanie w dół bez żadnego wyjaśnienia jest całkowicie nieprzydatne.
David T. Macknet
Komunikat o błędzie powinien brzmieć „większe lub równe”.
Ε Г И І И О
Dobry chwyt. Dodany.
David T. Macknet
1

używając Range with

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

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

Mam nadzieję, że to pomoże

Abi
źródło
1

[Zakres (0,01,100000000, ErrorMessage = "Cena musi być większa od zera!")]

Sohail Akhter
źródło
0

Powiedziałbym, decimal.MaxValue.ToString()ponieważ jest to efektywny pułap dla typu decmial, co jest równoznaczne z brakiem górnej granicy.

Dr Herbie
źródło
4
Problem w tym, że nie jest to stała. Otrzymasz ten błąd: Argument atrybutu musi być wyrażeniem stałym, wyrażeniem typu lub wyrażeniem tworzenia tablicy o typie parametru atrybutu
user169867
Jak zaznaczyłem poniżej, ale najwyraźniej nikt tego nie docenił.
David T. Macknet,