Vimos no post anterior (aqui) como fazer validação de dados (client e server-side) no ASP.NET MVC 3.
Continuando no tema, hoje vou mostrar como é simples criar atributos de validação (Data Annotations) personalizados.
Ainda no exemplo dado no post anterior, citado acima, utilizei o atributo [RegularExpression] para validar o formato de e-mail da classe Pessoa. Imagine agora utilizar um atributo personalizado, como [EmailEmFormatoValido], no lugar do [RegularExpression]. Ficaria muito mais claro, além de encapsular a lógica de validação em um único lugar.
Para criar esse atributo personalizado é muito simples. Basta implementar uma classe que herde de ValidationAttribute (do namespace System.ComponentModel.DataAnnotations) e sobrescrever o método IsValid da mesma. Fica assim:
public class EmailEmFormatoValido : ValidationAttribute { public EmailEmFormatoValido() { ErrorMessage = "E-mail deve estar em formato válido."; } public override bool IsValid(object value) { var email = value as string; if (email != null) return Regex.IsMatch(email, @"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"); return true; } }
Simples não é? No construtor da classe, defini uma mensagem padrão e no método IsValid implementei a lógica de validação desejada.
Note que o método IsValid retorna “true” sempre que o valor do campo estiver nulo. Isso é recomendável, senão você estaria deixando a propriedade obrigatória mesmo que o atributo [Required] não estivesse sendo usado.
Agora que temos o atributo criado, vamos utilizá-lo na propriedade Email da nossa classe Pessoa, no lugar do atributo [RegularExpression]:
public class Pessoa { [Required(ErrorMessage = "Nome deve ser preenchido")] public string Nome { get; set; } [Required(ErrorMessage = "E-mail deve ser preenchido")] [EmailEmFormatoValido] public string Email { get; set; } }
Notem que usei o atributo [EmailEmFormatoValido] sem especificar a mensagem ErrorMessage, pois já defini uma mensagem padrão no construtor da classe como mostrado anteriormente. No entanto, você pode especificá-la, sobrescrevendo a mensagem padrão.
Isso é tudo que precisamos para termos uma validação server-side usando nosso atributo personalizado. No entanto, caso você rode a aplicação, notará que a validação client-side não funciona. Isto ocorre porque os scripts client-side são gerados somente para os atributos básicos [Required], [RegularExpression], [Range] e [StringLength].
Sendo assim, é preciso implementar a validação client-side para seu atributo personalizado.
O primeiro passo é implementar um ModelValidator associado ao nosso atributo EmailEmFormatoValido. Fazemos isso, herdando de DataAnnotationsModelValidator<T> (do namespace System.Web.Mvc), onde T é nosso atributo:
public class EmailValidator : DataAnnotationsModelValidator { private readonly string _mensagem; public EmailValidator(ModelMetadata metadata, ControllerContext context, EmailEmFormatoValido attribute) : base(metadata, context, attribute) { _mensagem = attribute.ErrorMessage; } public override IEnumerable GetClientValidationRules() { var rule = new ModelClientValidationRule { ErrorMessage = _mensagem, ValidationType = "email" }; return new[] { rule }; } }
Notem que precisamos sobrescrever o método GetClientValidationRules, o qual retorna um array de regras que servirão como metadata para a validação em javascript que iremos escrever.
No exemplo acima, estou retornando apenas uma regra (ModelClientValidationRule) com a mensagem de erro igual à mensagem de erro definida em nosso atributo EmailEmFormatoValido (a mensagem de erro é obtida de attribute.ErrorMessage no construtor da classe). Definimos também na regra, o ValidationType para “email”, que mais tarde usaremos em nosso javascript.
O segundo passo é registrar esse novo validator, vinculando-o ao atributo EmailEmFormatoValido. Fazemos isso em Application_Start, no Global.asax:
protected void Application_Start() { // mantenha o codigo existente como está // vinculando nosso novo validator ao nosso atributo DataAnnotationsModelValidatorProvider. RegisterAdapter(typeof(EmailEmFormatoValido), typeof(EmailValidator)); }
Por fim, precisamos implementar a validação em javascript:
Sys.Mvc.ValidatorRegistry.validators.email = function (rule) { return function (value, context) { if (!value || EhEmail(value)) return true; return rule.ErrorMessage; }; }; function EhEmail(email) { regex = new RegExp("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"); return regex.test(email); }
O mais importante do código acima está em “….ValidatorRegistry.validators.email“. Ele está adicionando um validator ao dicionário de validators, usando a chave “email”, que deve ser o mesmo nome que definimos no ValidationType da classe EmailValidator.
Ufa! Terminamos! Após criar nosso validator EmailValidator (1), registrá-lo no Global.asax (2) e implementar a validação javascript (3), podemos ver a nosso atributo EmailEmFormatoValido funcionando corretamente no lado cliente.
Claro, vale lembrar que sua view (ou master) deve referenciar os seguintes scripts (juntamente com o script de validação mostrado acima).
Com isso, vimos como é fácil customizar os Data Annotations, podendo criar validadores para formato de e-mail, validadores de CPF/CNPJ e mais uma infinidade, deixando nossa validação simples e padronizada.
Obs.: tudo que foi mostrado aqui pode ser utilizado no ASP.NET MVC 2.
agradeço novamente pela contribuição dando seguemento a validações to tipo anotation, ensinar faz parte do aprender. sucesso.
CurtirCurtir
Obrigado, Nelson
Divulgue meu blog pros amigos. Estarei postando mais sobre ASP.NET MVC.
[]s
CurtirCurtir
Parabéns!
Grandes Tutoriais sobre MVC.
CurtirCurtir
Obrigado, Fúlvio
[]s
CurtirCurtir
Robson!
Por acaso se tem algum artigo sobre MVC para que eu possa colocar na minha monografia!
Tipo
O que e MVC?
Como Funciona?
É que preciso de referencia bibliografica, AUTOR, ANO, PAGINA E NOME DO LIVRO OU ARTIGO, REVISTA.
Se tiver e se puder me passar!
Fico muito agradecido
CurtirCurtir
Assim de cabeça não sei de nenhum.. Você vai encontrar nos livros de padrões de projeto (GoF e Head First). Isso se você estiver se referindo ao MVC “puro” e não especificamente ao ASP.NET MVC.
[]s
CurtirCurtir
Robson
Obrigado assim mesmo!
Vou tentar buscar mais informações!
CurtirCurtir
Tava precisando de um explicação de validação, muito obrigado, me ajudou muito
@jquerybrasil
CurtirCurtir
Que bom que foi útil.
[]s
CurtirCurtir
Olá!
Muito bom o post!
Conseguiu resolver facilmente um problema que pensei ser difícil.
Obrigada!
CurtirCurtir
De nada, Amanda! 🙂
Em breve mais posts de MVC 3
CurtirCurtir
Robson, Quando insiro o codigo javascript mostrado obtenho o seguinte erro:
“Uncaught ReferenceError: Sys is not defined” Sabe me dizer o porque ?
Obs.: Entendo que ele esta me dizendo que a referência ou objeto “Sys” não existe.
CurtirCurtir
Olá, Fagner
Desculpe pela demora.
No exemplo usei o validator client-side da própria Microsoft (note a linha ‘Sys.Mvc.ValidatorRegistry.validators…’) ao invés de faze-lo com JQuery. Isso acabou não ficando claro no post. Portanto, você precisará incluir mais um js, se não me engano o nome é: MicrosoftMvcValidation.js.
NO ENTANTO, os scripts Microsoft****.js estão obsoletos, tendo sido substituídos pelos equivalentes em JQuery. Portanto, recomendo não mais utilizá-los. Espero em breve atualizar este post (ou escrever outro) mostrando como adicionar um custom validator client-side usando a validação do JQuery.
Em uma breve “googlada”, você encontra artigos legais. A ideia é a mesma mostrada aqui.
[]s
CurtirCurtir
Gostaria de saber se você já fez ou tem algum exemplo para validação de enumeradores?
Parabéns pelo Post e pelo seu trabalho!!!
Abraço
att
CurtirCurtir
Olá Éverton
Que tipo de validação vc quer fazer?
Não me recordo no momento mas posso dar uma olhada.
[]s
CurtirCurtir
Olá Robson
Criei validadores de CNPJ e CPF, através de ValidationAttributes e com suporte a validação no cliente.
Disponibilizei ele no github https://github.com/lucas-silva/mvczin, fica como opção para o pessoal.
Parabéns pelo artigo, muito bem explicado
Abraços
CurtirCurtir
Opa, Lucas
Muito legal por contribuir!
[]s
CurtirCurtir