No desenvolvimento em ASP.Net utilizando o framework MVC é muito comum o uso do pattern View Model, esse pattern proporciona uma melhor organização do código e gestão dos dados utilizados na View, confira em quais situações ele é utilizável e algumas maneiras de como aplicá-lo.
A necessidade da utilização do pattern View Model surge na maioria dos projetos ASP.Net MVC, para os iniciantes costuma causar alguma confusão, porém é muito útil e poupa um bom trabalho.
O conceito de View Model não limita-se apenas para o ASP.Net MVC, você poderá encontrar referências sobre View Model para padrões MVC, MVP e MVVM, que por sua vez é implementado em tecnologias como ASP.Net, Silverlight e WPF.
Este artigo é dedicado para o entendimento do padrão View Model utilizando ASP.Net MVC.
O que é um ASP.Net MVC View Model?
No ASP.Net MVC os View Models nos permitem modelar várias entidades a partir de um ou mais modelos em um único objeto, eu gosto de usar como exemplo a comparação de View Models com uma DTO, pois ambas são soluções que foram projetadas para centralizar um conjunto de dados de diversas fontes assim evitando a necessidade de realizar várias chamadas para se obter todos os dados necessários e evitar a necessidade de alterar um modelo de domínio para realizar o transporte de algum dado específico.
Resumindo, um View Model representa um conjunto de uma ou mais Models e outros dados que serão representados em uma View que necessita exibir determinado conjunto de informações. A imagem abaixo ilustra o conceito de um View Model:
Utilizando uma View Model dedicada contendo a Model de domínio
Imagine que estamos desenvolvendo uma aplicação web de uma loja virtual onde possuímos a classe Produto:
public class Produto { public string Nome { get; set; } public decimal Valor { get; set; } }
Porém na View de carrinho de compras além das informações contidas na classe Produto é necessário exibir uma mensagem e o valor total do carrinho para vários produtos. O que fazer? Modificar a classe Produtos para conter essas informações?
Modificar a classe Produto não seria uma boa alternativa, afinal esses dados adicionais não fazem sentido pertencerem a entidade Produto, são dados pertinentes a View de carrinho de compras.
É nesse momento que o pattern View Model entra em ação para resolver esse problema de design. Criaremos então uma classe que irá prover dados para esta View e essa classe será uma View Model de carrinho de compras.
public class CarrinhoComprasViewModel { public IEnumerable Produtos { get; set; } public decimal TotalCarrinho { get; set; } public string Mensagem { get; set; } }
Podemos observar que esta View Model possui um IEnumerable de Produtos para uma lista de produtos e mais os dados de valor e mensagem que irão ser exibidos na View.
Não é um tipo de classe especial, é uma classe como qualquer outra Model, porém escrita especificamente para atender a uma View.
Confira o código da Controller de carrinho de compras.
public class CarrinhoComprasController : Controller { public ActionResult Index() { // Criando uma lista de produtos fake para exibição na View var produtos = new List<Produto>(); for (int i = 0; i < 10; i++) { produtos.Add(new Produto { Nome = "Produto " + i, Valor = 1.13M * i } ); } // Populando a model para exibição na View var model = new CarrinhoComprasViewModel { Produtos = produtos, TotalCarrinho = produtos.Sum(p => p.Valor), Mensagem = "Obrigado por comprar conosco!" }; return View(model); } }
E por fim a View de carrinho de compras
@model MeuExemploMVC.Models.CarrinhoComprasViewModel @{ ViewBag.Title = "Carrinho de Compras"; } <h2>@Model.Mensagem </h2> <fieldset> <legend>Carrinho de Compras</legend> <table> <caption>Produtos no Carrinho</caption> <thead> <tr> <th>Produto</th> <th>Valor</th> </tr> </thead> <tbody> @foreach (var produto in Model.Produtos) { <tr> <td>@produto.Nome</td> <td>@produto.Valor</td> </tr> } </tbody> <tfoot> <tr> <td><strong>Total</strong></td> <td>@Model.TotalCarrinho</td> </tr> </tfoot> </table> </fieldset>
O pattern de View Model está aplicado e não será mais necessário modificar a Model de Produto para adequar a View.
O arquivo físico de uma View Model pode estar em diferentes lugares, sendo:
- Em uma pasta chamada ViewModels na estrutura raiz do projeto MVC (aplicações pequenas)
- Uma *.dll referenciada no projeto MVC (aplicações de qualquer tamanho)
- Em projetos separados (como uma camada de serviços) para gerar dados específicos (aplicações grandes)
Utilizando AutoMapper para realizar o mapeamento de uma Model e suas variantes
Uma outra forma de utilizar View Models seria criando um mapeamento entre a Model entidade de domínio e a View Model que será exibida na View.
Os autores do livro ASP.Net MVC 4 in Action defendem fortemente a utilização de mapeamento entre as Models e suas possíveis variantes.
Com base no exemplo acima, a classe Produto poderia ter uma variante chamada ProdutoViewModel, qual possuiria os mesmos atributos de Produto entre outros mais.
O mapeamento entre essas duas Models seria feito através da ferramenta AutoMapper.
Este é um processo mais complexo e será abordado em meu post exclusivo sobre utilização do AutoMapper.
Benefícios de usar uma View Model
- Não precisar alterar uma classe Model para atender as necessidades de uma View.
- Poder agrupar informações de uma ou mais Models em uma única classe, poupando a necessidade de realizar N consultas.
- Um dado não contido em uma Model de domínio pode ser facilmente transportado através de uma View Model.
- Mudanças são muito mais fáceis de se realizar e sem afetar a Model do domínio.
- Não é necessário “poluir” as Models de domínio com DataAnnotations de validação de formulário, pois estas podem estar contidas diretamente na View Model.
Resumo
O uso de View Models é muito recomendado e irá ajudar a organizar e gerenciar os dados a serem transportados e exibidos, proporcionando flexibilidade para montar conjuntos de dados compatíveis com as necessidades da View.
No MVC existe o conceito de separação de responsabilidades onde “M” (Model) é considerada a menos importante, pois nem sempre a Model estará presente no projeto MVC e sim numa camada de domínio que irá prover estas classes. A Model do MVC está voltada ao uso na View, portanto algumas técnicas são necessárias para separar e mapear Models de entidades de domínio para Models do projeto MVC.
Referências
- Use View Models to manage data & organize code in ASP.NET MVC applications
- ASP.NET MVC View Model Patterns
- How we do MVC – View Models
- View Model pattern and AutoMapper in ASP.NET MVC Applications
Aguardem o próximo artigo complementar sobre AutoMapper 😉
Dúvidas e feedbacks são sempre muito bem vindos, utilize os comentários abaixo.