ASP .NET MVC 3 - Um pouco de Validações e Verificações


Numa aplicação MVC a validação é aplicada no modelo do domínio e não na interface do usuário.

Isso significa que nós definimos os nossos critérios de validação em um lugar, e isso produz os efeitos em qualquer lugar que o modelo é usado.

A ASP.NET MVC suporta regras de validação declarativas definidas com atributos do namespace System.ComponentModel.DataAnnotations.

Os atributos Data Annotation foram introduzido no .NET 3.5 como uma forma de adicionar a validação para as classes usadas por aplicações ASP.NET. Desde aquela época, o RIA Services começou a usar anotações de dados e eles agora fazem parte do Silverlight também. No EF 4.0 o Code-First permite que você construa um EDM usando código (C#/VB .NET) e também permite realizar a validação com atributos Data Annotations.

Para este recurso devemos usar o namespace System.ComponentModel.DataAnnotations pois é ele que provê atributos de classes (usados para definir metadados) e métodos que podemos usar em nossas classes para alterar as convenções padrão e definir um comportamento personalizado que pode ser usado em vários cenários.

Assim no ASP .NET MVC a validação e verificação das informações são realizadas por meio de atributos, quando ocorre uma mensagem de erro os métodos ValidationSummary, ValidationMessage e ValidationMessageFor são usados para exibir a mensagem ao usuário.

Os atributos de validação são aplicados na definição do Model.

Obs: Podemos também utilizar o método AddModelError(chave,mensagemDeErro) para exibir mensagens de erro.
Este método é usado no Controlador. Exemplo:
//Valida os dados no lado do servidor.
if(string.IsNullOrEmpty(pessoa.Nome))
    ModelState.AddModelError("Nome","Nome é obrigatório");

Se houver alguma mensagem de erro, a propriedade IsValid do ModelState retornará false, e o modelo estará inválido.

O MVC detecta os atributos de validação e os utiliza para validar os dados durante o processo model binding. Lembre-se que temos que declarar o namespace System.ComponentModel.DataAnnotations.

Os principais atributos para validação e formatação são:

1- Required - Obriga a entrada de um campo especificado.

[Required]
public string Nome { get ; set}

Parâmetros

ErrorMessage - Define a mensagem de erro;
AllowEmptyStrings - Define se são permitidos valores em branco;

[Required(ErrorMessage="O nome do usuário é obrigatório",AllowEmptyStrings=false)]
 public string Nome { get; set; }

2- RegularExpression - Permite usar expressões regulares em validações mais específicas

[Required(ErrorMessage = "Informe o seu email")]
[RegularExpression(".+\\@.+\\..+",ErrorMessage = "Informe um email válido...")]
public string Email { get; set; }

3- Display - Define o texto que será visível para uma propriedade quando usada em um campo de formulário

[Required(ErrorMessage="O nome do usuário é obrigatório",AllowEmptyStrings=false)]
[Display(Name = "Nome do Usuário")]
public string UserName { get; set; }

4- StringLength - Determina a quantidade máxima de caracteres que poderá ser informada

[Required]
 [Display(Name = "Informe a Senha")]
 [StringLength(10,MinimumLength=4)]
 public string Password { get; set; }

O parâmetro MinimumLength define a quantidade mínima de caracteres permitida

5- DataType - Associa um tipo adicional a uma propriedade

[Required]
[DataType(DataType.Password)]
[StringLength(10,MinimumLength=4)]
[Display(Name = "Password")]
public string Password { get; set; }

No exemplo acima a propriedade Password que é do tipo String possui um tipo adicional Password definido.

6- DisplayFormat - Aplica um formato definido a uma propriedade

[Required]
[Display(Name = "Data do pedido")]
[DisplayFormat(DataFormatString = "mm/dd/yyyy")]
public DateTime Datapedido { get; set; }
[Required]
[Display(Name = "Preco do Produto")]
[DisplayFormat(DataFormatString = "{0,c}")]
public decimal PrecoProduto { get; set; }

7- Range - Define um intervalo para uma propriedade onde a validação será aplicada

[Required]
[Display(Name = "Idade do beneficiário")]
[Range(18,65)]
public int idadeBeneficiario { get; set; }

8- Compare - Permite comparar o conteúdo de duas propriedades

[DataType(DataType.Password)]
[Display(Name = "Confirmar a senha")]
[Compare("Password", ErrorMessage = "A senhe e a confirmação da senha são diferentes")]
public string ConfirmaPassword { get; set; }

Obs: Este atributo pertence ao namespace System.Web.Mvc

9- Remote

O atributo Remote permite aproveitar o suporte do validador remote do plug-in jQuery. Isso permite que a biblioteca de validação do lado do cliente possa chamar um método personalizado que você definiu no servidor para executar a lógica de validação que só pode ser feita do lado do servidor.

No exemplo a seguir o atributo remote especifica que a validação do cliente irá chamar uma Action chamada NomeUsuarioDisponivel na classe UsersController , a fim de validar o campo NomeUsuario.

public class Usuario
{
    [Remote("NomeUsuarioDisponivel", "Users")]
    public string NomeUsuario { get; set; }
}

O código do controlador correspondente seria algo do tipo:

public class UsersController 
{ 
    public bool NomeUsuarioDisponivel(string nomeUsuario) 
    { 
        if(MyRepository.UserNameExists(nomeUsuario)) 
        { 
            return "false"; 
        } 
        return "true"; 
    } 
}

Ativando a validação do lado do cliente

Podemos usar o JQuery com DataAnnotation de forma a não ter impacto no servidor; para isso devemos fazer algumas configurações:

No arquivo web.config temos que incluir :

  <appSettings>
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />

  </appSettings>

A chave UnobtrusiveJavaScriptEnabled faz com que as regras sejam apresentadas usando atributos HTML 5.

Além disso devemos incluir três arquivos JavaScript na view ou na master page ou na page layout:

<script src="<%=Url.Content("~/Scripts/jquery-1.4.1.min.js")%>" type="text/javascript"></script>
<script src="<%=Url.Content("~/Scripts/jquery.validate.min.js")%>" type="text/javascript"></script>
<script src="<%=Url.Content("~/Scripts/jquery.validade.unobtrusive.min.js")%>" type="text/javascript"></script>

Podemos ainda ativar a validação do cliente no controlador usando o seguinte código:

HtmlHelper.ClientValidationEnabled = true;
HtmlHelper.UnobtrusiveJavaScriptEnabled = true;

E também podemos fazer a mesma coisa em uma view conforme o código abaixo:

<%HtmlHelper.EnableClientValidation(); %>
<%HtmlHelper.EnableUnobtrusiveJavaScript(); %>

Exemplo:

<% Html.EnableClientValidation();%>
<%using (Html.BeginForm())
{ %>
<p>
<%=Html.LabelFor(Model=>Model.Nome)%>
<%=Html.TextBoxFor(Model=>Model.Nome)%>
<%=Html.ValidationMessageFor(Model => Model.Nome)%>
</p>
<p>
<%=Html.LabelFor(Model=>Model.Email)%>
<%=Html.TextBoxFor(Model=>Model.Email)%>
<%=Html.ValidationMessageFor(Model => Model.Email)%>
</p>
<p>
<input type="submit" value="Salvar" />
</p>
<%} %>

Da teoria à prática

Vamos agora colocar em prática a teoria vista acima criando um novo projeto do tipo ASP .NET MVC 3 Web Application com o nome ValidacaoMVC;

No menu File clique em New Project e selecione o template indicado, informe o nome e clique em OK;

Agora vamos começar definindo o Model. Clique com o botão direito sobre a pasta Models e selecione Add Class informando o nome Cliente.cs;

A seguir digite o código abaixo no arquivo Cliente.cs:

namespace ValidacaoMVC.Models
{
    public class Cliente
    {
        public string Nome { get; set; }
        public string Email { get; set; }
        public string Fone { get; set; }
        public int Idade { get; set; }
    }
}

Vamos definir o escopo da nossa validação a partir deste modelo.

Com estas definições podemos definir as nossas validações.

1- Validação feita no Controlador

Vamos incluir um controlador no nosso projeto clicando com o botão direito do mouse sobre a pasta Controllers e clicando em Add -> Controller;

Na janela Add Controller informe o nome ClienteControler e clique em Add;

Vamos criar uma Action chamada Validacao conforme o código abaixo:

using System.Web.Mvc;
using ValidacaoMVC.Models;
using System.Text.RegularExpressions;

namespace ValidacaoMVC.Controllers
{
    public class ClienteController : Controller
    {
        public ActionResult Validacao(Cliente cliente)
        {
            //Validacao do lado do servidor.
            if (string.IsNullOrEmpty(cliente.Nome))
                ModelState.AddModelError("Nome", "O nome é obrigatório");

            if (string.IsNullOrEmpty(cliente.Email))
                ModelState.AddModelError("Email", "O email é obrigatório");
            else
            {   //verifica se o email é valido 
                if (!Regex.Match(cliente.Email, @"^[A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\.\-]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})$").Success)
                    ModelState.AddModelError("Email", "O email é inválido.");
            }

            if (cliente.Idade == 0)
                ModelState.AddModelError("Idade", "A idade deve ser informada");
            else
            {
                if (cliente.Idade <= 21)
                {   //verifica se a idade é maior ou igual a 21 anos
                    ModelState.AddModelError("Idade", "A idade informada tem que ser maior que 21.");
                }
            }

            if (string.IsNullOrEmpty(cliente.Fone))
                ModelState.AddModelError("Fone", "O Telefone é obrigatório.");
            else
            {   //verifica se o telefone esta no formato válido
                if (!Regex.Match(cliente.Fone, @"^[0-9]{2}-[0-9]{4}-[0-9]{4}$").Success)
                    ModelState.AddModelError("Telefone", "Informe o telefone no formato: ####-####. Ex: 1234-5678");
            }

            // A validação falhou ?
            if (!ModelState.IsValid)
            {
                //sim falhou 
                return View();
            }
            else
            {
                //esta tudo ok
                return Redirect("/");
            }
        }
        
        public ActionResult Index()
        {
            return View();
        }
    }
}

Agora vamos criar duas views uma para a validação e outra para Index.

Clique com o botão direito do mouse no interior da Action Validacao e selecione Add View;

A seguir informe o nome Validacao e marque a opção Create a strongly-typed view e selecione o Model Class Cliente e selecione o template Edit e clique em Add;

Repita o processo acima para a Action Index e informe o nome Index e selecione o template Empty:

Dessa forma teremos as views Validacao.cshtml e Index.cshtml criadas na pasta Views->Cliente:

Vamos alterar o arquivo _Layout.cshtml na pasta Views->Shared de forma a exibir uma aba para Cliente incluindo o trecho de código abaixo:

.............
     <div id="menucontainer">
                <ul id="menu">
                <li>@Html.ActionLink("Home", "Index", "Home")</li>
                <li>@Html.ActionLink("About", "About", "Home")</li>
                <li>@Html.ActionLink("Cliente", "Validacao", "Cliente")</li>
    </div>
.........

O código da view Validacao.shtml é dado a seguir:

@model Validacao_MVC.Models.Cliente

@{
    ViewBag.Title = "Validacao";
}

<h2>Validacao1</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@Html.ValidationSummary(true, "Ocorreu um erro no preenchimento do formulário. Verifique...")

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Cliente</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.Nome)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Nome)
            @Html.ValidationMessageFor(model => model.Nome)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Email)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Email)
            @Html.ValidationMessageFor(model => model.Email)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Fone)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Fone)
            @Html.ValidationMessageFor(model => model.Fone)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Idade)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Idade)
            @Html.ValidationMessageFor(model => model.Idade)
        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Retornar", "Index")
</div>

Executando o projeto iremos obter:

2- Validação feita no Model

Podemos utilizar os recursos do Data Annotations para realizar a validação no Model com isso estamos centralizando a nossa técnica de validação e estamos usando um recurso que pode ser usando tanto no ASP .NET MVC como com ASP .MET.

Para fazer isso vamos aplicar os atributos definidos no início ao nosso Model conforme mostra o código abaixo no arquivo Cliente.cs:

Obs: Lembre que temos que incluir o namespace do Data Annotations : using System.ComponentModel.DataAnnotations;

using System.ComponentModel.DataAnnotations;
namespace Validacao_MVC.Models
{
    public class Cliente
    {
        [Required(ErrorMessage = "O Nome é obrigatório.")]
        [StringLength(50,MinimumLength=5)]
        [Display(Name = "Informe o nome do cliente.")]
        public string Nome { get; set; }

         [Required(ErrorMessage = "O E-mail é deve ser informado.")]
         [Display(Name = "Informe o email do cliente.")]
        public string Email { get; set; }

         [Required(ErrorMessage = "O Telefone está vazio.")]
        public string Fone { get; set; }

         [Range(21, 99, ErrorMessage = "A idade deve ser maior que 18 anos e menor que 99 anos.")]
        public int Idade { get; set; }
    }
}
Cliente.cs

Após essas definições podemos alterar o nosso controlador ClienteController conforme o código abaixo:

using System.Web.Mvc;
using Validacao_MVC.Models;
using System.Text.RegularExpressions;

namespace Validacao_MVC.Controllers
{
    public class ClienteController : Controller
    {
        public ActionResult Validacao(Cliente cliente)
        {
            // A validação falhou ?
            if (!ModelState.IsValid)
            {
                //sim falhou 
                return View();
            }
            else
            {
                //esta tudo ok
                return Redirect("/Home");
            }
        }

        public ActionResult Index()
        {
            return View();
        }
    }
}

Executando o projeto novamente iremos obter o seguinte resultado quando a aba Cliente for clicada:

Pegue o projeto completo aqui: Validacao_MVC.zip

Rom 12:15 alegrai-vos com os que se alegram; chorai com os que choram;
Rom 12:16
sede unânimes entre vós; não ambicioneis coisas altivas mas acomodai-vos às humildes; não sejais sábios aos vossos olhos;

Rom 12:17
a ninguém torneis mal por mal; procurai as coisas dignas, perante todos os homens.

Referências:


José Carlos Macoratti