ASP .NET Core - Criando uma aplicação ASP .NET Core MVC com o VS 2017 - IX

 Neste artigo eu vou mostrar como criar uma aplicação ASP .NET Core MVC usando o VS 2017.

Continuando a oitava parte do artigo  vamos usar o Entity Framework Code First Migrations para adicionar um novo campo ao modelo e migrar essa alteração para o banco de dados.

Neste artigo vamos adicionar a lógica de validação ao Model Filme e verificar se as regras são aplicadas sempre que um usuário cria ou edita um filme.

Mantendo as coisas Simples ( DRY-Don´t repeat yourself )

Um dos princípios de design do MVC é conhecido pelo acrônimo DRY ("Do not Repeat Yourself"). A ASP.NET MVC incentiva você a especificar a funcionalidade ou o comportamento apenas uma vez e, em seguida, fazer com que ele seja refletido em toda parte da sua aplicação. Isso reduz a quantidade de código que você precisa para escrever e torna o código menos propenso ao erros, mais fácil de testar e mais fácil de manter.

Nota:  O princípio DRY, 'Não se Repita', é um importante princípio que procura reduzir a duplicação de código e os problemas oriundos dessa prática. A definição formal desse princípio diz : "Cada parte do conhecimento deve ter uma representação única, não ambígua e definitiva dentro do sistema."

O suporte de validação fornecido pelo MVC e pelo Entity Framework Core Code First é um bom exemplo do princípio DRY em ação. Você pode declarativamente especificar regras de validação em um lugar (na classe do modelo) e as regras são aplicadas em todos os lugares na aplicação

Adicionando regras de validação ao Model Filme

Para aplicar as regras no Model Filme vamos usar o recurso DataAnnotations.

A DataAnnotations fornece um conjunto embutido de atributos de validação que você aplica declarativamente a qualquer classe ou propriedade. Ela também contém atributos de formatação como DataType que ajudam na formatação e não fornecem qualquer validação. 

Para saber mais sobre esse assunto veja o artigo :  C# - Validando dados com Data Annotations - Macoratti

Abra o arquivo Filme.cs da pasta Models e atualize o código da classe usando os atributos de validação StringLength, RegularExpression e Range :

using System;
using System.ComponentModel.DataAnnotations;
namespace MvcFilme.Models
{
    public class Filme
    {
        public int ID { get; set; }
        [StringLength(60, MinimumLength = 3)]
        [Required]
        public string Titulo { get; set; }
        [Display(Name = "Data de Lançamento")]
        [DataType(DataType.Date)]
        public DateTime Lancamento { get; set; }
        [RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$")]
        [Required]
        [StringLength(30)]
        [Display(Name = "Gênero")]
        public string Genero { get; set; }
        [Range(1, 100)]
        [DataType(DataType.Currency)]
        [Display(Name = "Preço")]
        public decimal Preco { get; set; }
        [RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$")]
        [StringLength(5)]
        [Required]
        public string Classificacao { get; set; }
    }
}

Os atributos de validação especificam o comportamento que você deseja aplicar nas propriedades do modelo ao qual são aplicados.

Os atributos Required e MinimumLength indicam que uma propriedade deve ter um valor; Mas nada impede que um usuário entre com espaço em branco para satisfazer essa validação.

O atributo RegularExpression é usado para limitar quais caracteres podem ser inseridos. No código acima, Genero e Classificacao devem usar apenas letras (espaço em branco, números e caracteres especiais não são permitidos).

O atributo Range restringe um valor dentro de um intervalo especificado.

O atributo StringLength permite definir o comprimento máximo de uma propriedade string e, opcionalmente, seu comprimento mínimo.

Tipos de valor (como decimal, int, float, DateTime) são inerentemente necessários e não é necessário o atributo [Required].

Ter regras de validação automaticamente aplicadas pelo ASP.NET ajuda a tornar o aplicativo mais robusto. Ele também garante que você não se esqueça de validar algo e, inadvertidamente, deixar dados sujos no banco de dados.

Validação de erros na Interface de Usuário (UI)

Agora vamos executar a aplicação e criar um novo filme informando dados inválidos. Você vai obter o seguinte resultado:

Observe como o formulário automaticamente processou uma mensagem de erro de validação apropriada em cada campo que contém um valor inválido.

Os erros são aplicados tanto do lado do cliente (usando JavaScript e jQuery) e do lado do servidor (no caso de um usuário que tem o JavaScript desativado).

Um benefício significativo é que você não precisa alterar uma única linha de código na classe FilmesController ou na View Create.cshtml para habilitar essa validação da UI. O controlador e as Views criadas anteriormente captaram automaticamente as regras de validação que você especificou utilizando atributos de validação nas propriedades da classe do modelo Filme. Faça o teste de validação usando o método Action Editar, e a mesma validação será aplicada.

Os dados do formulário não são enviados para o servidor até que não haja erros de validação do lado do cliente.

Como a validação Funciona ?

Você pode estar perguntando como a validação da View foi gerada sem nenhuma atualização do código do controlador nem nas views Create nem Edit ?

Vamos da um espiada nos dois métodos Create do controlador FilmesController :

        // GET: Filmes/Create
        public IActionResult Create()
        {
            return View();
        }
       [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create([Bind("ID,Titulo,Lancamento,Genero,Preco,Classificacao")] Filme filme)
        {
            if (ModelState.IsValid)
            {
                _context.Add(filme);
                await _context.SaveChangesAsync();
                return RedirectToAction("Index");
            }
            return View(filme);
        }    

O primeiro método Create(HTTP GET) exibe o formulário Create inicial. A segunda versão de Create ([HttpPost]) processa a postagem (Post) do formulário e chama o método ModelState.IsValid para verificar se o filme tem qualquer erro de validação.

Chamar este método avalia quaisquer atributos de validação que foram aplicados ao objeto. Se o objeto tiver erros de validação, o método Create re-exibe o formulário. Se não houver erros, o método salva o novo filme no banco de dados. Em nosso exemplo de filme, o formulário não é enviado ao servidor quando há erros de validação detectados no lado do cliente; O segundo método Create nunca é chamado quando há erros de validação do lado do cliente.

Se você desativar o JavaScript em seu navegador, a validação do cliente será desabilitada e você poderá testar o método HTTP POST Create onde teremos ModelState.IsValid detectando quaisquer erros de validação.

Você pode definir um ponto de interrupção no método [HttpPost] Create e verificar que o método nunca é chamado, a validação do lado do cliente não irá enviar os dados do formulário quando erros de validação são detectados.Tente desabilitar o JavaScript em seu navegador, e envie o formulário com erros, o ponto de interrupção será atingido. Assim você ainda tem a validação completa mesmo sem JavaScript.

Se você abrir o arquivo Create.cshtml verá o código mostrado abaixo que é usado pelo método Create para exibir o formulário inicial e para re-exibir o form quando um error ocorrer:

 ...
<form asp-action="Create">
    <div class="form-horizontal">
        <h4>Filme</h4>
        <hr />
        <div asp-validation-summary="ModelOnly" class="text-danger"></div>
        <div class="form-group">
            <label asp-for="Titulo" class="col-md-2 control-label"></label>
            <div class="col-md-10">
                <input asp-for="Titulo" class="form-control" />
                <span asp-validation-for="Titulo" class="text-danger"></span>
            </div>
        </div>
        <div class="form-group">
            <label asp-for="Classificacao" class="col-md-2 control-label"></label>
            <div class="col-md-10">
                <input asp-for="Titulo" class="form-control" />
                <span asp-validation-for="Classificacao" class="text-danger"></span>
            </div>
        </div>
...

A Tag Helper input usa os atributos DataAnnotations e produz atributos HTML necessários para a validação jQuery no lado do cliente. O Validator Tag Helper exibe erros de validação.

O que é realmente agradável sobre essa abordagem é que nem o controlador nem a view Create sabem nada sobre as regras de validação reais sendo aplicadas ou sobre as mensagens de erro específicas exibidas. As regras de validação e as strings de erro são especificadas somente na classe Filme. Essas mesmas regras de validação são aplicadas automaticamente à visualização Edit e a quaisquer outros modelos de visualizações que você possa criar que editam seu modelo.

Quando você precisa alterar a lógica de validação, pode fazê-lo exatamente em um lugar, adicionando atributos de validação ao modelo (neste exemplo, a classe Filme). Você não terá que se preocupar com diferentes partes do aplicativo que não sejam consistentes com a forma como as regras são aplicadas - toda a lógica de validação será definida em um lugar e usado em todos os lugares. Isso mantém o código muito limpo, e o torna fácil de manter e evoluir. E isso significa que você estará honrando totalmente o princípio DRY.

Usando atributos DataType

Abra o arquivo Filme.cs e examine a classe Filme.

O namespace System.ComponentModel.DataAnnotations fornece atributos de formatação para além do conjunto incorporado de atributos de validação.

Já aplicamos um valor de enumeração DataType para a data de lançamento e para os campos de preço.

O trecho de código a seguir mostra as propriedades DataLancamento e Preco com o atributo DataType apropriado.

    public class Filme
    {
        public int ID { get; set; }
        [StringLength(60, MinimumLength = 3)]
        [Required]
        public string Titulo { get; set; }
        [Display(Name = "Data de Lançamento")]
        [DataType(DataType.Date)]
        public DateTime Lancamento { get; set; }
        [RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$")]
        [Required]
        [StringLength(30)]
        [Display(Name = "Gênero")]
        public string Genero { get; set; }
        [Range(1, 100)]
        [DataType(DataType.Currency)]
        [Display(Name = "Preço")]
        public decimal Preco { get; set; }
        [RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$")]
        [StringLength(5)]
        [Required]
        public string Classificacao { get; set; }
    }

Os atributos DataType fornecem somente sugestões para o mecanismo de visualização para formatar os dados e fornecer atributos como <a> para URLs e <a href="mailto:EmailAddress.com"> para o email.

Você pode usar o atributo RegularExpression para validar o formato dos dados. O atributo DataType é usado para especificar um tipo de dados que é mais específico do que o tipo intrínseco do banco de dados, eles não são atributos de validação.  Nesse caso, só queremos manter o controle da data, e não da hora. A enumeração DataType fornece muitos tipos de dados, como Date, TIme, PhoneNumber, Currency, EmailAddress e etc.

O atributo DataType também pode permitir que o aplicativo forneça automaticamente recursos específicos de tipo. Por exemplo, um link mailto: pode ser criado para DataType.EmailAddress e um seletor de data pode ser fornecido para DataType.Date em navegadores que suportam HTML 5. Os atributos DataType emitem atributos HTML 5-data, que navegadores HTML 5 podem entender. Assim os atributos DataType não fornecem qualquer validação.

O atributo DataType.Date não especifica o formato da data que é exibida. Por padrão, o campo de dados é exibido de acordo com os formatos padrão com base no CultureInfo do servidor. Para exibir especificamente o formatao da da Data usamos o atributo DisplayFormat:

         ...
        [Display(Name = "Data de Lançamento")]
        [DisplayFormat(DataFormatString = "{0:dd-MM-yyyy}", ApplyFormatInEditMode = true)]
        [DataType(DataType.Date)]
        public DateTime Lancamento { get; set; }
        ...

A configuração ApplyFormatInEditMode especifica que a formatação também deve ser aplicada quando o valor é exibido em uma caixa de texto para edição. (Talvez você não queira aplicar isso para alguns campos - por exemplo, para valores de moeda, você provavelmente não vai querer o símbolo de moeda na caixa de texto para edição.)

Você pode usar o atributo DisplayFormat por si só, mas geralmente é uma boa idéia usar o atributo DataType. O atributo DataType transmite a semântica dos dados em vez de como processá-lo em uma tela e fornece os seguintes benefícios que você não obtém com DisplayFormat:

- O navegador pode ativar recursos HTML5 (por exemplo, para mostrar um controle de calendário, o símbolo de moeda apropriado à localidade, links de e-mail, etc.)
- Por padrão, o navegador renderizará dados usando o formato correto com base em sua localidade
- O atributo DataType pode habilitar o MVC para escolher o modelo de campo correto para processar os dados (o DisplayFormat por si mesmo usa o modelo string).

Nota: A validação jQuery não funciona com o atributo Range e DateTime.

Para concluir podemos simplificar o código combinando os atributos em uma única linha conforme mostrado a seguir:

    public class Filme
    {
        public int ID { get; set; }
        [StringLength(60, MinimumLength = 3)]
        public string Titulo { get; set; }
        [Display(Name = "Data de Lançamento"), DataType(DataType.Date)]
        public DateTime Lancamento { get; set; }
        [Display(Name = "Gênero"), RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$"), Required, StringLength(30)]
        public string Genero { get; set; }
        [Display(Name = "Preço"), Range(1, 100), DataType(DataType.Currency)]
        public decimal Preco { get; set; }
        [RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$"), StringLength(5)]
        public string Classificacao { get; set; }
    }

Na próxima parte do artigo, analisaremos o aplicativo e faremos algumas melhorias nos métodos Details e Delete gerados automaticamente.

"(Disse Jesus)Eu sou a porta; se alguém entrar por mim, salvar-se-á, e entrará, e sairá, e achará pastagens.
O ladrão não vem senão a roubar, a matar, e a destruir; eu vim para que tenham vida, e a tenham com abundância."

João 10:9,10

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti