Entendo que IValidatableObject
é usado para validar um objeto de uma maneira que permita comparar propriedades entre si.
Ainda gostaria de ter atributos para validar propriedades individuais, mas quero ignorar falhas em algumas propriedades em certos casos.
Estou tentando usá-lo incorretamente no caso abaixo? Se não, como faço para implementar isso?
public class ValidateMe : IValidatableObject
{
[Required]
public bool Enable { get; set; }
[Range(1, 5)]
public int Prop1 { get; set; }
[Range(1, 5)]
public int Prop2 { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (!this.Enable)
{
/* Return valid result here.
* I don't care if Prop1 and Prop2 are out of range
* if the whole object is not "enabled"
*/
}
else
{
/* Check if Prop1 and Prop2 meet their range requirements here
* and return accordingly.
*/
}
}
}
Citação da postagem do blog de Jeff Handley sobre objetos e propriedades de validação com o validador :
Isso indica que o que você está tentando fazer não funcionará imediatamente, pois a validação será interrompida na etapa 2. Você pode tentar criar atributos herdados dos incorporados e verificar especificamente a presença de uma propriedade ativada (por meio de uma interface) antes de executar sua validação normal. Como alternativa, você pode colocar toda a lógica para validar a entidade no
Validate
métodofonte
Apenas para adicionar alguns pontos:
Como a
Validate()
assinatura do método retornaIEnumerable<>
, issoyield return
pode ser usado para gerar preguiçosamente os resultados - isso é benéfico se algumas das verificações de validação exigirem muita IO ou CPU.Além disso, se você estiver usando
MVC ModelState
, poderá converter as falhas do resultado da validação emModelState
entradas da seguinte maneira (isso pode ser útil se você estiver executando a validação em um fichário de modelo personalizado ):fonte
Eu implementei uma classe abstrata de uso geral para validação
fonte
O problema com a resposta aceita é que agora depende do chamador para que o objeto seja validado corretamente. Eu removeria o RangeAttribute e faria a validação do intervalo dentro do método Validate ou criaria uma subclasse de atributo personalizado RangeAttribute que leva o nome da propriedade necessária como argumento no construtor.
Por exemplo:
fonte
Eu gostei da resposta de cocogza, exceto que a chamada base.IsValid resultou em uma exceção de estouro de pilha, uma vez que reintroduzia o método IsValid repetidamente. Então, eu o modifiquei para um tipo específico de validação, no meu caso, para um endereço de email.
Isso funciona muito melhor! Não falha e produz uma boa mensagem de erro. Espero que isso ajude alguém!
fonte
O que eu não gosto no iValidate é que ele parece ser executado APÓS todas as outras validações.
Além disso, pelo menos em nosso site, ele seria executado novamente durante uma tentativa de salvamento. Eu sugiro que você simplesmente crie uma função e coloque todo o seu código de validação nisso. Como alternativa para sites, você pode ter sua validação "especial" no controlador após a criação do modelo. Exemplo:
fonte