Walidatory wartości min./maks. W asp.net mvc

106

Sprawdzanie poprawności przy użyciu atrybutów w asp.net mvc jest naprawdę przyjemne. Do tej pory korzystałem z [Range(min, max)]walidatora do sprawdzania wartości, takich jak np:

[Range(1, 10)]
public int SomeNumber { get; set; }

Jednak - teraz muszę osobno sprawdzić stan min i max. Spodziewałem się znaleźć takie atrybuty:

[MinValue(1, "Value must be at least 1")]
[MaxValue(10, "Value can't be more than 10")]
public int SomeNumber { get; set; }

Czy są jakieś predefiniowane atrybuty do pisania tego? Albo jak to osiągnąć?

stiank81
źródło
FluentValidation może być kolejnym rozwiązaniem do rozwiązania zakresu dat. Oto moja odpowiedź na inne pytanie, które może być pomocne .
Zinov

Odpowiedzi:

48

Oto jak napisałbym walidator dla MaxValue

public class MaxValueAttribute : ValidationAttribute
    {
        private readonly int _maxValue;

        public MaxValueAttribute(int maxValue)
        {
            _maxValue = maxValue;
        }

        public override bool IsValid(object value)
        {
            return (int) value <= _maxValue;
        }
    }

Atrybut MinValue powinien być mniej więcej taki sam

Charles Ouellet
źródło
Ok, spodziewałem się, że istnieją, ale wystarczająco uczciwe, aby je napisać. Dzięki!
stiank81
1
Po prostu do Twojej wiadomości, to nie spowoduje magicznej weryfikacji formularza po stronie JavaScript. W tym celu musiałbyś napisać dodatkowy kod + js.
basarat
3
@basarat właściwie nie będziesz potrzebować dodatkowego JS, biblioteka walidacyjna jquery ma już funkcje min / max, wystarczy zaimplementować IClientValidationinterfejs na powyższym atrybucie i zwrócić poprawne wartości z GetClientValidationRulesmetody
WickyNilliams
@WickyNilliams czy dodałbyś odpowiedź z przykładem swojego komentarza, czy CharlesOuellet czy zmodyfikujesz tę odpowiedź na przykładzie komentarza Wicky'ego? Chciałbym zagłosować za przykładem roboczym, który obejmuje walidację po stronie klienta.
Johnie Karr
@JohnieKarr Nie pracuję już z .NET, więc nie mogę udzielić zbyt wielu odpowiedzi. To powiedziawszy, ta odpowiedź poniżej wydaje się dokładnie pokazywać to, co opisałem
WickyNilliams
195

Nie sądzę, że istnieje atrybut walidacji min / max. Użyłbym czegoś takiego

[Range(1, Int32.MaxValue)]

dla wartości minimalnej 1 i

[Range(Int32.MinValue, 10)]

dla wartości maksymalnej 10

Chłopak
źródło
4
Mmm ... Niezbyt wygodne z tym. Wygląda na to trochę zepsuty.
stiank81
21
To trochę hackowe ... ale czasami hacki sprawiają, że czuję się bardziej komfortowo :)
Guy
4
To podejście jest w porządku, o ile nadpisujesz domyślny komunikat o błędzie lub otrzymasz coś okropnego, na przykład: „Właściwość x musi znajdować się między -2e ^ 31-1 a 10”.
Dziewięć ogonów
2
Jak to jest hacky i niewygodne? Wydaje się, że to dobre podejście do mnie.
1
RangeAttributema AllowMultiple = false, więc nie można tego skompilować.
Daniel Schilling
38

Kompletny przykład tego, jak można to zrobić. Aby uniknąć konieczności pisania skryptów walidacji po stronie klienta, użyto istniejącego ValidationType = "zakres".

public class MinValueAttribute : ValidationAttribute, IClientValidatable
{
    private readonly double _minValue;

    public MinValueAttribute(double minValue)
    {
        _minValue = minValue;
        ErrorMessage = "Enter a value greater than or equal to " + _minValue;  
    }

    public MinValueAttribute(int minValue)
    {
        _minValue = minValue;
        ErrorMessage = "Enter a value greater than or equal to " + _minValue;
    }

    public override bool IsValid(object value)
    {
        return Convert.ToDouble(value) >= _minValue;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule();
        rule.ErrorMessage = ErrorMessage;
        rule.ValidationParameters.Add("min", _minValue);
        rule.ValidationParameters.Add("max", Double.MaxValue);
        rule.ValidationType = "range";
        yield return rule;
    }

}
Mario
źródło
8
Świetna odpowiedź. Zmodyfikowałbym nieco komunikat o błędzie: „Wprowadź wartość większą lub równą” to bardziej (gramatycznie) poprawny komunikat o błędzie.
Tieson T.
0

Wtyczka jQuery Validation już implementuje reguły min i max, musimy tylko stworzyć adapter dla naszego atrybutu niestandardowego:

public class MaxAttribute : ValidationAttribute, IClientValidatable
{
    private readonly int maxValue;

    public MaxAttribute(int maxValue)
    {
        this.maxValue = maxValue;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule();

        rule.ErrorMessage = ErrorMessageString, maxValue;

        rule.ValidationType = "max";
        rule.ValidationParameters.Add("max", maxValue);
        yield return rule;
    }

    public override bool IsValid(object value)
    {
        return (int)value <= maxValue;
    }
}

Adapter:

$.validator.unobtrusive.adapters.add(
   'max',
   ['max'],
   function (options) {
       options.rules['max'] = parseInt(options.params['max'], 10);
       options.messages['max'] = options.message;
   });

Atrybut minimalny byłby bardzo podobny.

Benas Radzevicius
źródło