Validadores de valor mínimo / máximo em asp.net mvc

106

Validação usando atributos em asp.net mvc é muito bom. Tenho usado o [Range(min, max)]validador até agora para verificar valores, como por exemplo:

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

No entanto - agora preciso verificar as condições mínimas e máximas separadamente. Eu esperava encontrar atributos como estes:

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

Existem atributos predefinidos para escrever isso? Ou como faço para conseguir isso?

Stiank81
fonte
FluentValidation pode ser outra solução para resolver o intervalo de datas. Aqui está minha resposta a outra pergunta que pode ser útil .
Zinov

Respostas:

48

Aqui está como eu escreveria um validador para 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;
        }
    }

O atributo MinValue deve ser praticamente o mesmo

Charles Ouellet
fonte
Ok, esperava que existissem, mas justo o suficiente para escrevê-los. THX!
stiank81
1
Apenas para sua informação, isso não validaria magicamente o formulário no final do Javascript. Você precisaria escrever código + js adicional para isso.
basarat
3
@basarat na verdade você não vai precisar de JS extra, a biblioteca de validação jquery já tem funções para min / max, você só precisa implementar a IClientValidationinterface no atributo acima e retornar os valores corretos do GetClientValidationRulesmétodo
WickyNilliams
@WickyNilliams você adicionaria uma resposta com um exemplo de seu comentário, ou CharlesOuellet você editaria esta resposta com um exemplo do comentário de Wicky? Eu adoraria votar positivamente em um exemplo de trabalho que inclua a validação do lado do cliente.
Johnie Karr
@JohnieKarr Não trabalho mais com .NET, então não posso dar uma resposta. Dito isso, a resposta abaixo parece mostrar exatamente o que descrevi
WickyNilliams
195

Não acho que exista um atributo de validações mín. / Máx. Eu usaria algo como

[Range(1, Int32.MaxValue)]

para valor mínimo 1 e

[Range(Int32.MinValue, 10)]

para valor máximo 10

Cara
fonte
4
Mmm .. Não estou muito confortável com isso. Parece um pouco estranho para mim.
stiank81
21
É um pouco hacky .. mas às vezes hacks me fazem sentir mais confortável :)
Guy
4
Essa abordagem é adequada, desde que você substitua a mensagem de erro padrão ou obterá algo horrível como: "A propriedade x deve estar entre -2e ^ 31-1 e 10".
Nine Tails,
2
Como isso é hacky e desconfortável? Parece uma boa abordagem para mim.
1
RangeAttributetem AllowMultiple = false, então isso não pode ser compilado.
Daniel Schilling
38

Um exemplo completo de como isso poderia ser feito. Para evitar ter que escrever scripts de validação do lado do cliente, o ValidationType = "range" existente foi usado.

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
fonte
8
Ótima resposta. Gostaria de modificar um pouco a mensagem de erro: "Insira um valor maior ou igual a" é uma mensagem de erro mais correta (gramaticalmente).
Tieson T.
0

O plug-in de validação jQuery já implementa regras mínimas e máximas, só precisamos criar um adaptador para o nosso atributo personalizado:

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

Adaptador:

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

O atributo mínimo seria muito semelhante.

Benas Radzevicius
fonte