ASP .NET Core - Usando o padrão ViewModel

  Neste artigo vou mostrar como utilizar o padrão ViewModel em aplicações ASP .NET Core MVC.

O padrão Model View ViewModel (MVVM) foi introduzido por John Gosmann em 2005 e é uma especialização do padrão de projeto Presentation Model (PM) que foi introduzido em 2004 por Martin Fowler.

Estruturalmente, uma aplicação que usa o padrão MVVM consiste basicamente em três componentes principais: o Modelo, a Visão(View) e a ViewModel.

Em uma aplicação ASP .NET MVC a ViewModel contém a lógica de interface do usuário, os comandos, os eventos, e uma referência para o modelo e não tema a responsabilidade de atualizar os dados da interface do usuário.

Assim a ViewModel representa apenas os dados que queremos exibir na View e pode ser composta de um ou mais Models.

Vamos supor que temos uma aplicação onde temos uma entidade Cliente e uma entidade Pedido e vamos precisar exibir em uma view informações de Cliente e de Pedido. Para poder fazer isso podemos criar uma ViewModel chamada ClienteViewModel e selecionar as propriedades que desejamos exibir de ambas as entidades (Cliente + Pedido).

 

Para mostrar um exemplo prático usando esse cenário vamos criar uma aplicação ASP .NET MVC usando o Entity Framework e o SQL Server onde teremos um banco de dados Vendas.mdf e as tabelas Clientes e Pedidos cuja estrutura é exibida a seguir:

Vamos precisar conhecer a string de conexão deste banco de dados no SQL Server. Para o meu exemplo a string de conexão é :  Data Source=.\;Initial Catalog=Vendas;Integrated Security=True

Você pode obter a string de conexão abrindo o Server Explorer e a seguir abrir uma conexão com o banco Vendas e depois pressionar F4 e ver na janela de propriedades a string de conexão.

Para acompanhar este artigo você precisa ter instalado o Visual Studio Community 2017 com os seguintes workloads e recursos instalados:

Se você não tem nenhuma noção sobre como funciona o padrão MVC e sua implementação ASP .NET sugiro que leia esses artigos :

Criando uma nova aplicação ASP .NET MVC

Abra no VS 2017 e no menu File clique em New Project;

A seguir selecione o template Visual C# -> Web e marque ASP .NET Core Web Application (.NET Framework);

Informe o nome Aspn_ViewModel e clique no botão OK;

Na próxima janela escolha a versão ASP .NET Core 1.1 e marque o template Web Application sem autenticação e clique no botão OK;

Teremos o projeto ASP .NET MVC criado contendo a estrutura básica, conforme figura abaixo, que será o nosso ponto de partida.

Instalando o Entity Framework Core 1.1

O Entity Framework Core (EF Core) é uma versão leve, extensível e multiplataforma do Entity Framework. O EF Core introduz muitas melhorias e novos recursos quando comparado com o EF6.x.  O EF Core mantém a experiência do desenvolvedor do EF6.x e a maioria das APIs de alto nível permanecem as mesmas, então o EF Core vai te parecer muito familiar se você conhece o Entity Framework 6.x.

Para instalar o Entity Framework em nosso projeto vamos usar a opção do menu Tools-> Nuget Package Manager ->  Package Manage Console.

Você deve instalar o pacote para o provedor do banco de dados EF Core que você deseja acessar. Os provedores atualmente disponíveis podem ser vistos neste link: Database Providers

Neste artigo vamos instalar o provider para o SQL Server.

Abra a janela do Console do Gerenciador de Pacotes clicando no menu Tools-> Nuget Package Manager ->  Package Manage Console.

A seguir digite o seguinte comando : Install-Package Microsoft.EntityFrameworkCore.SqlServer

Para concluir  vamos instalar o Microsoft.EntityFrameworkCore.Design para ter acesso às ferramentas de design para o SqlServer.

Na janela do Console digite o comando : Install-Package Microsoft.EntityFrameworkCore.Design

Criando o Modelo a partir do banco de dados

Agora que temos o suporte ao EF Core vamos criar o nosso modelo de entidades com base no banco de dados existente.

No menu Tools clique em Package Manager Console e a seguir na janela do console digite o comando:


Scaffold-DbContext "Data Source=.\;Initial Catalog=Vendas;Integrated Security=True" Microsoft.EntityFrameworkCore.SqlServer

 

Nesta instrução temos :

  1. O comando:  Scaffold-DbContext

  2. A string de conexão do banco de dados : "Data Source=.\;Initial Catalog=Vendas;Integrated Security=True"

  3. O nome do provedor usado :  Microsoft.EntityFrameworkCore.SqlServer

Na figura abaixo vemos o comando após a sua execução gerar as classe Clientes.cs , Pedidos.cs e VendasContext :

O processo de engenharia reversa criou as classes das entidades e um contexto derivado baseado no esquema do banco de dados existente. As classes de entidade são objetos C# simples que representam os dados que você estará consultando e salvando, no nosso exemplo, são as informações de clientes e  pedidos.

Registrando o contexto com injeção de dependência

A ASP.NET Core implementa a injeção de dependência por padrão. Os serviços (como o contexto de banco de dados do EF) são registrados com injeção de dependência durante a inicialização do aplicativo. Componentes que requerem esses serviços (como controladores MVC) fornecem esses serviços através de parâmetros do construtor.

Para que os controladores MVC da nossa aplicação utilizem o VendasContext, vamos registrar o contexto como um serviço.

Para registrar o nosso contexto VendasContext como um serviço, abra o arquivo Startup.cs e adicione as linhas realçadas em azul ao método ConfigureServices:

using Microsoft.EntityFrameworkCore;
...
....
        // This method gets called by the runtime. Use this method to add services to the container.
 
      public void ConfigureServices(IServiceCollection services)
        {
            var connection = @"Data Source =.\; Initial Catalog = Vendas; Integrated Security = True";
            services.AddDbContext<VendasContext>(options => options.UseSqlServer(connection));
            // Add framework services.
            services.AddMvc();
        }

....

Nota: Um aplicativo real geralmente colocaria a string de conexão em um arquivo de configuração. Por uma questão de simplicidade, estamos definindo-a via código.

Criando a ViewModel : ClienteViewModel

Agora sim vamos aplicar o padrão ViewModel pois desejamos exibir em uma view as informações de clientes e pedidos. Vamos então criar uma pasta ViewModel no projeto para organizar o código.

Selecione o projeto e no menu Project clique em New Folder e informe o nome ViewModel.

Selecione esta pasta e no menu Project clique em Add Class e informe o nome ClienteViewModel. A seguir inclua o código abaixo na classe ClienteViewModel:

using System;
namespace Aspn_ViewModel.ViewModel
{
    public class ClienteViewModel
    {
        public int ClienteViewModelId { get; set; }    

        public string Nome { get; set; }       // Cliente
        public string Endereco { get; set; }  // Cliente
        public string Email { get; set; }        // Cliente
        public DateTime? DataPedido { get; set; }               // Pedido
        public Nullable<decimal> PrecoPedido { get; set; } // Pedido
    }
}

Dessa forma criamos a nossa ViewModel contendo informação das entidades Cliente e Pedido para serem exibidas em uma View.

Criando o Controller : ClientePedidosController

Se você não sabe o que é um Controller então pode ler os seguintes artigos  :

Os Controllers ou Controladores são os componentes que lidam com a interação do usuário, trabalham com o modelo e, finalmente, selecionam uma exibição de renderização que mostra essa interface ao usuário. Por padrão os controladores são colocados na pasta Controllers da solução.

A criação automática dos métodos Actions para realizar o CRUD e as Views é conhecida como Scaffolding. O Scaffolding irá criar automaticamente os métodos Action e as Views, e, quando você precisar personalizar o código gerado, você pode usar classes parciais ou você regenera o código quando as houver alterações.

Vamos iniciar criando um controlador em nosso projeto. Clique com o botão direito do mouse sobre a pasta Controllers, e a seguir clique em Add -> Controller;

Na janela Add MVC Dependencies selecione a opção - Minimal Dependencies e clique no botão Add;

O VS 2017 vai adicionar as dependências necessárias para montar o controller.

Após isso repita o procedimento e clique com o botão direito do mouse sobre a pasta Controllers, e a seguir clique em Add -> Controller;

Na janela Add Scaffold selecione a opção : MVC Controller - Empty

Clique no botão Add.

Agora na janela Add Controller informe o nome : ClientePedidosController

Ao clicar no botão Add, o mecanismo de Scaffolding do Visual Studio irá criar um arquivo ClientePedidosController.cs, na pasta Controllers.

Vamos abrir o arquivo ClientePedidoController e incluir o código abaixo na Action Index:

using Aspn_ViewModel.ViewModel;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;
namespace Aspn_ViewModel.Controllers
{
    public class ClientePedidosController : Controller
    {
        public IActionResult Index()
        {
            //cria uma instância do contexto
            VendasContext db = new VendasContext();
            //Para tratar as informações de clientes e pedidos
            List<ClienteViewModel> listaClientesVM = new List<ClienteViewModel>();
            //consulta os dados do banco de dados
            //fazendo a junção da duas tabelas
            //e armazenando as informações em listaClientes
            var listaClientes = (from Cli in db.Clientes
                                        join Ped in db.Pedidos on Cli.ClienteId equals Ped.ClienteId
                                        select new { Cli.Nome, Cli.Email, Cli.Endereco,
                                                          Ped.DataPedido, Ped.PrecoPedido }).ToList();
            //percorre a lista de clientes e preenche
            //a ViewModel com os dados que serão exibidos na view
            foreach (var item in listaClientes)
            {
                ClienteViewModel cliVM = new ClienteViewModel(); //ViewModel
                cliVM.Nome = item.Nome;
                cliVM.Email = item.Email;
                cliVM.Endereco = item.Endereco;
                cliVM.DataPedido = item.DataPedido;
                cliVM.PrecoPedido = item.PrecoPedido;
                listaClientesVM.Add(cliVM);
            }
            //Retorna as informações para View
            return View(listaClientesVM);
        }
    }
}

O código já esta comentado e basicamente retorna as informações de clientes e pedidos da ViewModel para a View.

Criando a View Index para exibir informações a partir da ViewModel

Vamos agora criar a View Index para exibir as informações da ViewModel.

Clique com o botão direito sobre o método Action Index() no controlador ClientePedidosController e a seguir clique em Add View.

A seguir informe os dados conforme a figura abaixo:

Clicando no botão Add teremos a view Index.cshtml criada na pasta Views/ClientePedidos com o seguinte código:

@model IEnumerable<Aspn_ViewModel.ViewModel.ClienteViewModel>
@{
    ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p>
    <a asp-action="Create">Create New</a>
</p>
<table class="table">
    <thead>
        <tr>
                <th>@Html.DisplayNameFor(model => model.Nome)</th>
                <th>@Html.DisplayNameFor(model => model.Endereco)</th>
                <th>@Html.DisplayNameFor(model => model.Email)</th>
                <th>@Html.DisplayNameFor(model => model.DataPedido)</th>
                <th>@Html.DisplayNameFor(model => model.PrecoPedido)</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model) {
        <tr>
            <td>@Html.DisplayFor(modelItem => item.Nome)</td>
            <td>@Html.DisplayFor(modelItem => item.Endereco)</td>
            <td>@Html.DisplayFor(modelItem => item.Email)</td>
            <td>@Html.DisplayFor(modelItem => item.DataPedido)</td>
            <td>@Html.DisplayFor(modelItem => item.PrecoPedido)</td>
            <td>
                <a asp-action="Edit" asp-route-id="@item.ClienteViewModelId">Edit</a> |
                <a asp-action="Details" asp-route-id="@item.ClienteViewModelId">Details</a> |
                <a asp-action="Delete" asp-route-id="@item.ClienteViewModelId">Delete</a>
            </td>
        </tr>
       }
    </tbody>
</table>

Executando o projeto e navegando para ClientePedidos iremos obter o seguinte resultado:

Dessa forma vemos a exibição na View Index das informações de clientes e pedidos obtidas a partir da View Model - ClienteViewModel - criada para esta finalidade.

Isso posto temos que :

- A sua view não depende mais do Model mas da ViewModel;
- Você pode agrupar informações de diversos Models em uma única classe: a ViewModel;
- Voce não terá que alterar uma classe do Model para atender as necessidades de uma View;
- Você pode fazer mudanças na sua ViewModel sem afetar o modelo de domínio;

Pegue o projeto aqui :  Aspn_ViewModel.zip (sem as referências)
 

(Disse Jesus) Todo o que o Pai me dá virá a mim; e o que vem a mim de maneira nenhuma o lançarei fora.
João 6:37

 

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