RSS feed
ASP.NET MVC 2: Validação do Modelo de Dados - ScottGu's Blog em Português

ASP.NET MVC 2: Validação do Modelo de Dados


[PS Além do blog, eu também estou agora utilizando o Twitter para atualizações rápidas e para compartilhar links. Siga-me em: twitter.com/scottgu]

Este é o segundo de uma série de posts que estou escrevendo sobre o próximo lançamento da ASP.NET MVC 2. Este post aborda algumas das melhorias para a validação de dados com a ASP.NET MVC 2.

Validação de Dados com a ASP.NET MVC 2

Validar a entrada de dados do usuário e garantir as regras/lógica de negócio é um requisito fundamental para a maioria das aplicações web. A ASP.NET MVC 2 inclui um conjunto de novas funcionalidades que tornam a validação dos dados de entrada do usuário e a aplicação da lógica de validação dos modelos de dados/modelos de visão significativamente mais fácil. Esses recursos são projetados de modo que a lógica de validação seja sempre aplicada no servidor e, opcionalmente, pode também ser aplicada no cliente através de JavaScript. A infraestrutura de validação e seus recursos na ASP.NET MVC 2 são projetados de modo que:

1) Os desenvolvedores podem facilmente tirar vantagem da validação através do suporte a DataAnnotation (Anotação de Dados) presente no .NET Framework.  DataAnnotations fornecem uma maneira muito fácil para adicionar regras de validação declarativamente em objetos e propriedades com um mínimo de código.   

2) Os desenvolvedores podem, opcionalmente, integrar seu próprio engine (motor) de validação, ou tirar vantagem de frameworks como Castle Validator ou a Biblioteca de Validação EntLib. Os recursos de validação da ASP.NET MVC 2 são projetados para tornar mais fácil a adição de qualquer arquitetura de validação - e ao mesmo tempo te possibilita tirar vantagem da nova infraestrutura de validação da ASP.NET MVC 2 (incluindo validação no lado do cliente, validação do modelo de dados, etc).

Isto significa que habilitar a validação é extremamente fácil em cenários comuns, permanecendo ainda muito flexível em cenários mais avançados.

Habilitando a Validação com a ASP.NET MVC 2 e DataAnnotations

Vamos seguir um passo a passo de um cenário CRUD simples com a ASP.NET MVC 2, que tira vantagem do suporte à validação através de DataAnnotation.  Especificamente, vamos implementar um formulário "Create" (Criar) que permite que um usuário entre com dados de amigos:

imagem

Queremos garantir que as informações inseridas sejam válidas antes de salvá-las em um banco de dados - e também queremos apresentar mensagens de erro apropriadas caso as informações estejam erradas:

imagem

Queremos ativar essa validação para que ela ocorra no servidor e no cliente (via JavaScript). Nós também queremos assegurar que o nosso código mantenha o princípio DRY - Don't Repeat Yourself ("Não Repita Você Mesmo") - o que significa que só devemos aplicar as regras de validação em um único lugar, e então todos os nossos controladores, ações e visões devem honrá-las.

A seguir eu usarei o VS 2010 para implementar o cenário descrito acima usando a ASP.NET MVC 2. Você também pode implementar este exato cenário utilizando o VS 2008 e a ASP.NET MVC 2.

Passo 1: Implementando um Controlador FriendsController (sem validação, para começar)

Vamos começar adicionando uma simples classe "Person" (Pessoa) em um novo projeto ASP.NET MVC 2 igual a seguir:

imagem

Esta classe tem quatro propriedades (implementadas usando o conceito de propriedades automáticas (em Inglês) da linguagem C#, as quais são agora suportadas também na linguagem VB no VS 2010 - viva!).

Vamos então adicionar uma classe de controlador "FriendsController" em nosso projeto que expõe dois métodos de ação "Create". O primeiro método de ação é chamado quando uma requisição HTTP-GET chega para a URL Friends/Create. Este método irá exibir um formulário em branco para que possamos inserir dados da pessoa. O segundo método de ação é chamado quando um pedido HTTP-POST chega para a URL Friends/Create. Este método mapeia os dados de entrada do formulário postado para um objeto Person, verifica que nenhum erro tenha ocorrido, e se os dados forem válidos, salvará os mesmos no banco de dados (vamos implementar o trabalho com o banco de dados mais tarde neste tutorial). Se os dados de entrada do formulário postado forem inválidos, o método de ação exibirá novamente o formulário com mensagens de erro:

imagem

Depois de implementarmos nosso controlador, podemos clicar com o botão direito do mouse dentro de um dos seus métodos de ação e escolher a opção "Add Vies" (Adicionar Visão) dentro do Visual Studio - o que fará com que a janela de diálogo "Add View" apareça. Vamos escolher a implementação automática de uma visão "Create" para a qual é passado um objeto Person:

imagem

O Visual Studio irá gerar automaticamente uma visão Create.aspx par nós dentro do diretório \Views\Friends\ do nosso projeto. Observe a seguir como o VS tira vantagem dos novos métodos de ajuda HTML fortemente tipados da ASP.NET MVC 2 (permitindo um melhor suporte à IntelliSense e à verificação do código no tempo de compilação):

imagem

Agora, quando executamos a aplicação e chegamos na URL Friends/Create, obteremos um formulário em branco no qual poderemos inserir dados:

imagem

Em virtude de não termos implementado nenhuma validação dentro da aplicação, nada nos impede de entrar com dados errados dentro do formulário e enviar o mesmo para o servidor.

Passo 2: Habilitar a Validação usando DataAnnotations

Vamos agora atualizar nossa aplicação para aplicar algumas regras de validação básicas. Nós vamos implementar estas regras no nosso modelo de objeto Person - e não dentro do nosso Controlador ou nossa Visão. O benefício que ganhamos ao implementar as regras de validação dentro do nosso objeto Person é que isto garantirá que a validação será aplicada em qualquer cenário dentro da nossa aplicação que usa um objeto Person (por exemplo: se mais tarde adicionarmos um cenário de edição). Isto vai nos ajudar a manter nosso código DRY evitando a repetição de regras de validação em múltiplos lugares. 

A ASP.NET MVC 2 permite que os desenvolvedores adicionem facilmente atributos de validação declarativos nas classes do modelo ou visões do modelo, fazendo com que estas regras de validação sejam automaticamente aplicadas sempre que a ASP.NET MVC realizar operações de ligação de dados dentro da aplicação. Para vermos isto em ação, vamos atualizar nossa classe Person para termos alguns atributos de validação dentro dela. Para fazermos isso, vamos adicionar uma declaração "using" para o namespace "System.ComponentModel.DataAnnotations" no topo do arquivo - e, em seguida, decoraremos as propriedades do objeto Person com atributos de validação [Required] (Requerido), [StringLength] (Tamanho da String), [Range] (Intervalo) e [RegularExpression] (Expressão Regular) (que são implementados dentro deste namespace):

imagem

Nota: Acima nós estamos explicitamente especificando as mensagens de erro com strings. Alternativamente, você pode definí-las dentro de arquivos de recursos (com extensão .resx) e, opcionalmente, localizá-las, dependendo do idioma e cultura do usuário que está acessando o sistema. Você pode aprender mais sobre como localizar mensagens de erro de validação aqui (em Inglês).

Agora que nós adicionamos os atributos de validação em nossa classe Person, vamos reexecutar nossa aplicação para ver o que acontece quando entramos com valores errados e enviamos os mesmos para o servidor:

imagem

Observe acima como a nossa aplicação já possui uma experiência de erro aceitável. Os elementos de texto com entrada de dados inválida são destacados em vermelho, e as mensagens de erro de validação que especificamos são exibidas para o usuário final. O formulário também está preservando os dados de entrada do usuário que foram inicialmente digitados - para que ele não precise preencher tudo novamente. Como assim, você pode perguntar, isso aconteceu?

Para entender esse comportamento, vamos olhar o método de ação Create que trata o cenário de POST do nosso formulário:

imagem

Quando nosso formulário HTML é enviado de volta para o servidor, o método acima será chamado. Em virtude do método de ação aceitar um objeto "Person" como um parâmetro, a ASP.NET MVC vai criar um objeto Person e mapeará automaticamente os dados do formulário de entrada para este objeto. Como parte deste processo, a ASP.NET MVC também irá verificar se os atributos de validação DataAnnotation para o objeto Person são válidos. Se tudo for válido, então a verificação de ModelState.IsValid dentro do nosso código irá retornar true - e neste caso nós (possivelmente) salvaremos o objeto Person no banco de dados e então redirecionaremos o usuário de volta para a home-page.

Se houver algum erro de validação no objeto Person, nosso método de ação reexibe o formullário com o objeto Person inválido. Isto é feito através da última linha de código no trecho de código acima.

As mensagens de erro são então exibidas dentro da nossa visão porque o nosso formulário Create tem cahamadas para o método de ajuda <% = Html.ValidationMessageFor() %> próximo a cada método de ajuda <%= Html.TextBoxFor() %>.O método de ajuda <%= Html.ValidationMessageFor() %> mostrará a mensagem de erro apropriada para cada propriedade inválida do modelo passado para a visão: 

imagem

A coisa agradável com relação a este padrão/abordagem é que ela é bastante fácil de configurar - e ela nos permite adicionar ou alterar as regras de validação facilmente em nossa classe Person, sem termos que mudar qualquer código dentro dos nossos Controladores ou Visões. Esta capacidade de especificar as regras de validação em um lugar e fazer com elas sejam honradas e respeitadas em todos os lugares nos permite evoluir rapidamente nossa aplicação e regras, com um mínimo de esforço possibilitando-nos manter o nosso código DRY.

Passo 3: Habilitando a Validação no Lado do Cliente

Nossa aplicação atualmente só realiza a validação no lado do servidor - o que significa que nossos usuários finais terão que enviar o formulário para o servidor antes que eles vejam mensagens de erro de validação.

Uma das coisas legais sobre a arquitetura de validação da ASP.NET MVC 2 é que ela suporta tanto a validação no lado do servidor como também no lado do cliente.  Para tornar isto possível, tudo o que precisamos fazer é adicionar duas referências JavaScript em nossa visão, e escrever uma linha de código:

imagem

Quando acrescentamos estas três linhas, a ASP.NET MVC 2 usará os meta-dados de validação que adicionamos em nossa classe Person e ligará a lógica de validação JavaScript no lado do cliente. Isto significa que os usuários receberão erros de validação imediatamente quando eles mudarem para outro campo a partir de um campo inválido através da tecla Tab. 

Para ver o suporte JavaScript funcionando no lado do cliente para a nossa aplicação de amigos, vamos executar novamente a aplicação e preencher as três primeiras caixas de texto com valores válidos - clicando no botão "Create" logo em seguida. Observe como nós vamos receber uma mensagem de erro imediatamente para o valor que falta ser preenchido sem termos que enviar o formulário para o servidor:

imagem

Se entrarmos com algum texto que não seja um endereço de e-mail válido, a mensagem de erro irá mudar imediatamente de "Email Required" (Email necessário) para "Not a valid email" (Não é um e-mail válido) (as quais são as mensagens de erro que especificamos quando nós adicionamos as regras de validação em nossa classe Person):

imagem

Quando digitamos um e-mail válido, a mensagem de erro irá desaparecer imediatamente e a cor de fundo da caixa de texto voltará ao seu estado normal:

imagem

O bom é que nós não temos que escrever qualquer JavaScript personalizado para habilitarmos a lógica de validação acima. Nosso código de validação também é ainda muito DRY - nós podemos especificar as regras em um único lugar e ter as mesmas aplicadas em toda a aplicação - e em ambos os lugares: no cliente e no servidor.

Note que por motivos de segurança as regras de validação no lado do servidor sempre são aplicadas mesmo se você tiver o suporte às regras de validação no lado do cliente ativado. Isto impede que os hackers tentem enganar o servidor driblando as regras no lado do cliente.

O suporte à validação JavaScript no lado do cliente na ASP.NET MVC 2 pode funcionar com qualquer framework/motor de validação que você venha a usar com a ASP.NET MVC. Ele não requer que você use a abordagem de validação através de DataAnnotation - toda a infraestrutura funciona de maneira independente de DataAnnotations e pode trabalhar em conjunto com o Castle validador, o EntLib Validation Block, ou qualquer outra solução de validação customizada que você escolha usar.

Se você não quiser usar nossos arquivos JavaScript no lado do cliente, você também pode substituir o plugin de validação da jQuery passando então a usar a biblioteca que você escolher. O download da biblioteca ASP.NET MVC Futures também incluirá suporte para habilitar a validação jQuery para o framework de validação no lado do servidor da ASP.NET MVC 2.

Passo 4: Criando um Atributo [Email] Personalizado para a Validação

O namespace System.ComponentModel.DataAnnotations dentro do .NET Framework já possui alguns atributos de validação que você pode usar. Nós usamos 4 atributos diferentes no exemplo acima - [Required], [StringLength], [Range] e [RegularExpression].

Você também pode, opcionalmente, definir os seus atributos de validação personalizados e usá-los da mesma forma. Você pode definir atributos de validação completamente personalizados derivando da classe base ValidationAttribute dentro do namespace System.ComponentModel.DataAnnotations. Alternativamente, você pode optar por derivar de qualquer um dos atributos de validação existentes se você quiser simplesmente extender a funcionalidade da classe base. 

Por exemplo, para ajudar a limpar o código dentro da nossa classe Person nos podemos criar um novo atributo de validação [E-mail] que encapsula a expressão regular que faz a verificação de e-mails válidos. Para fazer isso, nós podemos simplesmente derivar este novo atributo a partir da classe base RegularExpression como mostrado a seguir, chamando o construtor da classe base RegularExpression com a regex de e-mail adequada:

imagem

Podemos, então, atualizar a nossa classe Person para usarmos o nosso novo atributo de validação [E-mail] no lugar da expressão regular que usamos anteriormente - o que torna o código mais limpo e encapsulado:

imagem

Quando criamos atributos de validação personalizados, podemos especificar a lógica de validação que roda tanto no servidor como no cliente através de JavaScript.

Além de criar atributos de validação que se aplicam à propriedades individuais em um objeto, você também pode aplicar atributos de validação no nível da classe - o que permite a você executar a lógica de validação em múltiplas propriedades dentro de um objeto. Para um exemplo disto, você pode analisar o atributo customizado "PropertiesMustMatchAttribute" que está incluído no arquivo AccountModels.cs/vb dentro do template de projeto padrão da ASP.NET MVC 2 (vá em File->New ASP.NET MVC 2 Web Project dentro do VS 2010 e busque por esta classe). 

Passo 5: Persistindo/Salvando os dados em um Banco de Dados

Vamos agora implementar a lógica necessária para salvar nossos amigos em um banco de dados. 

imagem 

Neste momento estamos simplesmente trabalhando com uma simples classe C# (por vezes referida como uma classe "POCO" (em Inglês) - "simples e velho objeto da CLR"). Uma abordagem que poderíamos usar seria escrever algum código de persistência separado que mapeia esta classe existente que já gravamos no banco de dados. Soluções para mapeamento objeto relacional (ORM) como NHibernate suportam muito bem este estilo de mapeamento POCO/PI. O ADO.NET Entity Framework (EF) que acompanha o .NET 4 também suportará mapeamento POCO/PI e igualmente à NHibernate, opcionalmente, também permitirá a definição de mapeamentos de persistência em uma maneira "somente código" (nenhum arquivo de mapeamento ou designers serão necessários). 

Se nosso objeto Person fosse mapeado para um banco de dados desta forma, então não teríamos a necessidade de fazer quaisquer mudanças em nossa classe Person ou em qualquer uma das nossas regras de validação - que continuariam funcionando muito bem. 

Mas, e se estivermos usando uma ferramenta gráfica para nossos mapeamentos ORM?

Muitos desenvolvedores que usamo o Visual Studio hoje não escrevem seus próprios mapeamentos ORM / lógica de persistência - e ao invés disso usam os designers que acompanham o Visual Studio para os ajudar a gerenciar esta tarefa.

Uma questão que muitas vezes surge quando se usa DataAnnotations (ou qualquer outra forma de validação baseada em atributos) é "como você pode aplicar tais regras de validação quando o objeto do modelo com o qual você está trabalhando é criado e mantido por um designer gráfico?".  Por exemplo, o que aconteceria se ao invés de termos uma classe Person no estilo POCO igual a que estamos usando até agora, tivéssemos definido e mantido a nossa classe Person dentro do Visual Studio através de uma ferramenta gráfica para mapeamento como LINQ para SQL ou o designer do ADO.NET EF?

imagem

Acima é exibido um screenshot que mostra uma classe Person definida através do designer do ADO.NET EF no VS 2010. A janela no topo define a classe Person, a janela na parte inferior mostra o editor de mapeamento e como as suas propriedades mapeiam de/para uma tabela "People" (Pessoas) dentro de um banco de dados.  Quando você clica em salvar no designer este gera automaticamente uma classe Person para você dentro do seu projeto. Isso é ótimo, só que toda vez que você fizer uma alteração e clicar em salvar, o designer irá recriar a classe Person - o que faria com que qualquer atributo de validação que você tivesse adicionado na classe fosse perdido.

Uma maneira para adicionar meta-dados baseados em atributos (iguais aos atributos de validação) em uma classe que é criada/mantida automaticamente por um designer do VS é aplicar uma técnica que chamamos de "buddy classes" (classes amigas). Basicamente você cria uma classe separada que contém seus atributos de validação e meta-dados e então liga a mesma à classe gerada pelo designer aplicando um atributo "MetadataType" em uma classe parcial que é compilada juntamente com a classe gerada pela ferramenta, neste caso o designer do VS. Por exemplo, se quiséssemos aplicar as regras de validação que usamos anteriormente em uma classe Person mantida pelo designer de LINQ to SQL ou ADO.NET EF, nós poderíamos atualizar nosso código de validação fazendo com este passe a ficar em uma classe separada chamada "Person_Validation" que é ligada à classe "Person" criada automaticamente pelo VS usando o seguinte código:

imagem

A abordagem acima não é tão elegante como uma abordagem POCO pura -, mas tem a vantagem de trabalhar com praticamente qualquer ferramenta ou código gerado por designers dentro do Visual Studio.

Última Passo - Salvando o Amigo no Banco de Dados

Nosso último passo - independentemente de nós usarmos uma classe Person POCO ou uma classe Person gerada automaticamente por alguma ferramenta - será salvar os nossos amigos válidos no banco de dados. 

Para fazer isso, temos simplesmente que trocar a declaração do marcador "Todo" dentro da nossa classe FriendsController por 3 linhas de código que salvam o novo amigo no banco de dados. A seguir está o código completo para a classe FriendsController - usando o ADO.NET EF para fazer a persistência dos dados para nós:

imagem

E agora, quando nós visitamos a URL Friends/Create podemos facilmente adicionar novas Pessoas no nosso banco de dados de amigos:

imagem

A validação de todos os dados é aplicada tanto no cliente como no servidor. Podemos facilmente adicionar/modificar/excluir regras de validação em um só lugar, fazendo com que estas sejam aplicadas em todos os controladores e visões que fazem parte da nossa aplicação.

Resumo

A ASP.NET MVC 2 torna muito mais fácil integrar validação de dados em aplicações web. Ela promove uma abordagem de validação baseada no modelo de dados, a qual permite que você mantenha suas aplicações focadas no principio DRY, te ajudando a garantir que as regras de validação sejam aplicadas de forma consistente em toda a aplicação. O suporte integrado para DataAnnotations da ASP.NET MVC 2 faz com que cenários de validação sejam implementados de maneira extremamente fácil sem a necessidade de instalar qualquer pacote adicional. O suporte para extensões dentro da infraestrutura de validação da ASP.NET MVC 2 permite que você implemente uma vasta gama de cenários de validação mais avançados - através da conexão de qualquer framework/motor de validação customizado ou existente.

Espero que ajude,

Scott

 

Texto traduzido do post original por Leniel Macaferi

Published Friday, January 15, 2010 6:14 AM by Leniel Macaferi
Filed under: , , ,

Comments

# re: ASP.NET MVC 2: Validação do Modelo de Dados

Saturday, October 2, 2010 3:50 PM by Veranildo Veras

Muito bom o artigo, meus parabéns SCOTT, você como sempre renovando.

# re: ASP.NET MVC 2: Validação do Modelo de Dados

Saturday, October 23, 2010 7:25 PM by Arthur

Esse artigo me ajudou bastante, bem explicado e muito detalhado

Obrigado

# re: ASP.NET MVC 2: Validação do Modelo de Dados

Thursday, November 25, 2010 10:56 AM by Rm

Espetacular este artigo, ajudou muito. Obrigado e parabéns Scott.