ASP.Net MVC – AutoMapper e View Models

O AutoMapper é uma biblioteca pequena e simples construída para resolver um problema aparentemente complexo, que é livrar-se de um código que mapeou um objeto para outro. Este tipo de problema é muito comum e relativamente trabalhoso de resolver,  a ferramenta AutoMapper atua nesse cenário de forma simples e elegante.

ASP.Net MVC AutoMapper

No artigo anterior foi abordado o padrão View Model no ASP.Net MVC, esse padrão ajuda a organizar o código, pois divide as responsabilidades entre as Models de domínio e as Models que atendem Views, evitando que as Models de domínio sejam alteradas e poluídas com dados desnecessários ao domínio.

A primeira técnica de trabalhar com View Models foi abordada no artigo anterior.
A técnica abordada neste artigo é mais complexa e necessita de um mapeamento entre objetos que é feito com a ajuda da ferramenta AutoMapper.

No livro Padrões de Arquitetura de Aplicações Corporativas, Martin Fowler descreve um padrão base chamado Mapper. O AutoMapper foi desenvolvido por Jimmy Bogard, um dos autores do livro ASP.Net MVC 4 in Action.

Mapeando uma Model de domínio para uma View Model

O cenário deste exemplo é baseado em um sistema muito simples que consulta os dados de um cliente cadastrado e informa um número da sorte gerado randomicamente para este cliente.

Neste cenário possuímos a Model de domínio (cliente).

using System;

namespace MvcMapping.Models
{
    public class Cliente
    {
        public string Nome { get; set; }
        public string Sobrenome { get; set; }
        public DateTime DataNascimento { get; set; }
        public bool Ativo { get; set; }
    }
}

Note que não existe referência ao dado de número da sorte, pois ele é exibido apenas na View e não é armazenado com os dados de cliente, logo torna-se desnecessário fazer parte da modelagem da Model.

Na técnica apresentada anteriormente a solução seria criar uma View Model com uma propriedade do tipo cliente e complementar com dados adicionais a serem exibidos na View.
Este artigo irá abordar outra técnica que consiste em criar uma classe com a mesma estrutura de cliente e mais os novos dados adicionais, chamaremos ela de ClienteViewModel e estará disponível em uma pasta raiz do projeto MVC chamada ViewModels.

using System;
using System.ComponentModel.DataAnnotations;

namespace MvcMapping.ViewModels
{
    public class ClienteViewModel
    {

        [Required(ErrorMessage = "Preencher campo Nome")]
        public string Nome { get; set; }

        public string Sobrenome { get; set; }

        [Required(ErrorMessage = "Preencher campo Data de Nascimento")]
        [Display(Name = "Data de Nascimento")]
        [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:yyyy-MM-dd}")]
        [DataType(DataType.Date, ErrorMessage="Data em formato inválido")]
        public DateTime DataNascimento { get; set; }

        public bool Ativo { get; set; }

        public int NumeroDaSorte { get; set; }
    }
}

Na classe ClienteViewModel possuímos a mesma estrutura de clientes, mais o dado adicional de número da sorte e os DataAnnotations para validação de formulário.

Até este momento já é possível listar três benefícios imediatos:

  • A Model de domínio não precisou ser modificada sem necessidade.
  • A Model de domínio não está poluída com DataAnnotations de validação de formulário.
  • A manutenção destas classes torna-se muito mais fácil, uma vez que a Model de domínio não está amarrada às características de uma View.

Após a separação das responsabilidades temos uma Model e uma View Model, ambas representando a entidade cliente, agora é necessário mapear um objeto ao outro para que a ClienteController receba a Model cliente e responda para View uma ClienteViewModel (e vice-versa), esse trabalho é executado pelo AutoMapper.

Configurando o AutoMapper no projeto ASP.Net MVC

Primeiramente é necessário configurar as referências das bibliotecas do AutoMapper e isto pode ser feito facilmente com o NuGet

PM> Install-Package AutoMapper

No projeto MVC crie uma pasta vazia chamada Mappers, dentro desta pasta será necessário criar uma classe que servirá de configuração dos profiles de mapeamento (Model > View Model) e (View Model > Model), esses profiles de mapeamento foram separados em dois arquivos, confira como abaixo como criar cada um deles.

Classe AutoMapperConfig

using AutoMapper;

namespace MvcMapping.Mappers
{
    public class AutoMapperConfig
    {
        public static void RegisterMappings()
        {
            Mapper.Initialize(x =>
            {
                x.AddProfile<DomainToViewModelMappingProfile>();
                x.AddProfile<ViewModelToDomainMappingProfile>();
            });
        }
    }
}

Classe DomainToViewModelMappingProfile

[UPDATE – 12/2015]Não é mais possível fazer o override do ProfileName nas novas versões do AutoMapper. Basta não sobrescrever esta property

using AutoMapper;
using MvcMapping.Models;
using MvcMapping.ViewModels;

namespace MvcMapping.Mappers
{
    public class DomainToViewModelMappingProfile : Profile
    {
        // Não realizar este override na versão 4.x e superiores
        public override string ProfileName
        {
            get { return "DomainToViewModelMappings"; }
        }

        protected override void Configure()
        {
            Mapper.CreateMap<Cliente, ClienteViewModel>();
        }
    }
}

Classe ViewModelToDomainMappingProfile

using AutoMapper;
using MvcMapping.Models;
using MvcMapping.ViewModels;

namespace MvcMapping.Mappers
{
    public class ViewModelToDomainMappingProfile : Profile
    {
        // Não realizar este override na versão 4.x e superiores
        public override string ProfileName
        {
            get { return "ViewModelToDomainMappings"; }
        }

        protected override void Configure()
        {
            Mapper.CreateMap<ClienteViewModel, Cliente>();
        }
    }
}

Esta é a estrutura necessária para configurar o AutoMapper de forma a utilizar o mínimo possível de código de mapeamento em outras classes da aplicação.

  • AutoMapperConfig > Inicializa os profiles de mapeamento (Model > View Model) e (ViewModel > Model).
  • DomainToViewModelMappingProfile > Profile de mapeamento (Model > View Model)
  • ViewModelToDomainMappingProfile > Profile de mapeamento (View Model > Model)

Confira como o projeto ficou estruturado

Projeto ASP.Net MVC AutoMapper

Neste momento resta apenas configurar que a classe AutoMapperConfig seja inicializada junto com a aplicação para registrar os profiles de mapeamento, essa configuração é feita no arquivo Global.asax

using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using MvcMapping.Mappers;

namespace MvcMapping
{

    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();

            // Configurando o AutoMapper para registrar os profiles
            // de mapeamento durante a inicialização da aplicação.
            AutoMapperConfig.RegisterMappings();
        }
    }
}

O AutoMapper está devidamente configurado na aplicação, no próximo passo será feita a conversão da Model cliente para a ClienteViewModel na Controller através do mapeamento que foi criado, confira como ficou o código da ClienteController

using System;
using System.Web.Mvc;
using MvcMapping.Models;
using MvcMapping.ViewModels;
using AutoMapper;

namespace MvcMapping.Controllers
{
    public class ClienteController : Controller
    {
        public ActionResult Index()
        {
            var rdnGen = new Random();

            // Um fake de uma consulta de cliente na base de dados.
            var cliente = new Cliente {
                                            Nome = "Eduardo",
                                            Sobrenome = "Pires",
                                            DataNascimento = Convert.ToDateTime("24/04/1982"),
                                            Ativo = true,
                                      };

            // Transformando a Model Cliente em ClienteViewModel
            var clienteView = Mapper.Map<Cliente, ClienteViewModel>(cliente);

            // Atribuindo valor aos dados adicionais da entidade Cliente
            clienteView.NumeroDaSorte = rdnGen.Next(1, 100);

            return View(clienteView);
        }
    }
}

Note que foi necessário apenas uma linha para transformar a Model Cliente em ClienteViewModel. De forma muito elegante foi criado um objeto do tipo ClienteViewModel já populado com os dados existentes no objeto Cliente.

A partir deste momento o AutoMapper está fazendo o trabalho de mapeamento e a View está recebendo uma View Model compatível com suas necessidades, confira o código da View

@model MvcMapping.ViewModels.ClienteViewModel

@{
    ViewBag.Title = "Sorte do Dia";
}

<hgroup class="title">
    <h1>@ViewBag.Title.</h1>
</hgroup>

<table>
    <tr>
        <td>
            @Html.LabelFor(m => m.Nome)
            @Html.DisplayFor(m => m.Nome)
        </td>
    </tr>
    <tr>
        <td>
            @Html.LabelFor(m => m.Sobrenome)
            @Html.DisplayFor(m => m.Sobrenome)
        </td>
    </tr>
    <tr>
        <td>
            @Html.LabelFor(m => m.DataNascimento)
            @Html.DisplayFor(m => m.DataNascimento)
        </td>
    </tr>
    <tr>
        <td>
            @Html.LabelFor(m => m.Ativo)
            @Html.DisplayFor(m => m.Ativo)
        </td>
    </tr>
    <tr>
        <td>
            @Html.LabelFor(m => m.NumeroDaSorte)
            @Html.DisplayFor(m => m.NumeroDaSorte)
        </td>
    </tr>
</table>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

Para mapear mais Models / View Models basta editar os arquivos DomainToViewModelMappingProfile e ViewModelToDomainMappingProfile com os mapeamentos necessários.

Achou muito trabalhoso ter que montar a estrutura de pasta e os 3 arquivos de mapeamento? Existe uma forma que dispensa toda essa configuração (inclusive inicialização no Global.asax), basta adicionar uma linha a mais em cada momento que houver o mapeamento, confira.

public class ClienteController : Controller
{
    public ActionResult Index()
    {
        var rdnGen = new Random();

        // Um fake de uma consulta de cliente na base de dados.
        var cliente = new Cliente {
                                        Nome = "Eduardo",
                                        Sobrenome = "Pires",
                                        DataNascimento = Convert.ToDateTime("24/04/1982"),
                                        Ativo = true,
                                    };

        // Criando o Mapeamento por demanda.
        Mapper.CreateMap<Cliente, ClienteViewModel>();

        // Transformando a Model Cliente em ClienteViewModel
        var clienteView = Mapper.Map<Cliente, ClienteViewModel>(cliente);

        // Atribuindo valor aos dados adicionais da entidade Cliente
        clienteView.NumeroDaSorte = rdnGen.Next(1, 100);

        return View(clienteView);
    }
}

Apesar de ser mais simples eu pessoalmente não recomendo utilizar o mapeamento desta forma, pois além de somar uma linha a mais em todo momento de executar o mapeamento, o comando de criação de mapeamento não fica centralizado, é difícil ter visão dos mapeamentos já existentes e dificulta também a manutenção.

Resumo

Utilizar o AutoMapper é muito simples conforme foi exemplificado, colabora para adoção do padrão View Model e evita a necessidade de escrever extensos códigos de mapeamento, assim proporcionando mais agilidade no desenvolvimento e facilitando a manutenção, e claro, o código final fica com um aspecto muito mais elegante.

Existem outras ferramentas para mapeamento com a mesma finalidade, a mais popular até o momento é o AutoMapper.

Referências

Nota

“Como mencionado no artigo anterior o padrão View Model está presente no MVC, MVP e MVVM, este artigo aborda a utilização deste padrão para MVC.”

Espero que este artigo ajude a entender o conceito do padrão View Model e o mapeamento de objetos através do AutoMapper.

Feedbacks são sempre muito bem vindos, utilize os comentários abaixo.

93 pensou em “ASP.Net MVC – AutoMapper e View Models

  1. Olá Eduardo, tudo bem cara?

    Ótimo post, parabéns. Apenas fazendo um apêndice no conteúdo:

    Quando o mapeamento é simples, ele é perfeito! Porém, quando temos um mapeamento complexo, temos alguns pontos para avaliar. Veja, internamente, o AutoMapper realiza uma querie para cada join definido em nossa querie. Escrevi sobre isto a um tempo atras, veja:

    http://rafaelzaccanini.net/2012/02/17/mapeando-simple-objects-e-complex-objects-com-automapper/

    Abs

  2. Olá Eduardo Pires, primeiramente parabéns pelo post.
    Não tenho muita experiência com projetos MVC e entendo que a Model é um ponto comum entre as camadas “assunto na qual já discuti bastante com outros desenvolvedores”. Porem sempre achei estranho o forte acoplamento dela na aplicação, principalmente em grandes projetos.
    Obrigado por me mostrar que não sou um desenvolvedor maluco :-).

    • Ewerton tudo bem?

      Esse assunto é mais denso que parece…
      Um site ASP.NET MVC é uma camada, camada de apresentação. Uma grande aplicação possui N camadas, ex se for baseada em DDD essa aplicação possui ao menos 4 camadas (UI [MVC], Domain, Application, Infrastructure) e dentro dessas camadas mais algumas subdivisões.

      Falando ainda em DDD a camada de domínio é a que provê os modelos, entidades, objetos de valor etc…
      A model do MVC não necessita existir, você precisará representá-las, por isso as ViewModels e o AutoMapper, pois elas espelham os modelos de domínio na UI.

      Pensar que a arquitetura de uma aplicação ASP.NET MVC começa e termina no projeto Web é errado, recomendo apenas para projetos bem pequenos.

      Te dei mais argumentação agora? 🙂 rsss…
      Abraço!

      • Acredito que 90% delas. rsss
        Mais uma vez obrigado por mostrar que sou normal e provar que estou no caminho certo. 🙂

  3. Eduardo primeiramente parabéns pelo post, mas tenho uma dúvida em relação ao modelo DDD usado com automapper … por exemplo trabalho com padrão repository e meus métodos do repository sempre me retornam um objeto DTO ou View Model …

    Mas se eu usar o automapper teria que retornar um objeto model para o controller e fazer o mapeamento … sem contar que não teria como eu usar select new no repository para escapar do lazy loading … gostaria de saber se alguém tem alguma sugestão ou eu estou pensando da maneira errada .

    • Olá André,

      Tem algumas coisas erradas ai.

      Se você trabalha com DDD provavelmente tem uma interface do seu repository na camada do seu domínio certo? E para que seu repository retorne uma ViewModel o seu domínio então precisa conhecer essa ViewModel, isso está errado, a ViewModel é uma classe da camada de apresentação, o domínio não deve conhecê-la.

      No caso do DDD você tem agregados, ou seja, pode ter classes que são modelagens das quais vc precisa e elas poderão ser transformadas em ViewModels através do AutoMapper.

      Você vê algum problema em seguir nessa sugestão?

      Abs!

      • Opa muito obrigado , concordo que dominio nao pode conhecer a apresentação , mas por exemplo em um sistema aqui da empresa uso DTO para transferir esses dados para as classes modelos, mas um dia conversando com um amigo ele me disse que o modelo DDD é muito bom mas se o sistema em si for muito grande pode haver problemas com performance …

        Abrs !

        • Não sei se esta certo mas eu faço assim:

          Passo os dados da ViewModel para o controller que por sua vez usa um metodo para fazer o mapeamento do que tem na viewModel para um objeto DTO e passo esse objeto para o repositorio que por sua vez usa um metodo desse objeto DTO para realizar o mapeamento e receber um objeto Modelo aí realizar o “CRUD” não sei se esta certo , se não estiver por favor me ajudem que quero aprender o correto …

          Abraços

          • André,

            Tem um passo a mais ai, da ViewModel você já pode transformar direto em Model do domínio na Controller.
            A ViewModel é uma espécie de DTO, por que não utiliza apenas ela?

            Abs!

          • Nossa muito obrigado Eduardo, realmente me ajudou em muito e mais uma vez meus parabéns pela clareza com que explica.

            Abraços.

  4. Olá Pessoal, bom dia!

    Como posso fazer para mapear Objetos internos para objetos da ViewModel ?

    Exemplo:

    O objeto Cotacao [Domínio], estou mapeando para CotacaoViewModel [ViewModel], e este objeto possui Fornecedor [Domínio], porem quero que ele também seja mapeado para FornecedorViewModel.

    No final das contas, quero trabalhar com objetos somente da ViewModel entre a controladora e a visão.

    Obrigado.

  5. Em um cenário que eu uso DMX e usando DDD com MVC eu teria 3 “modelo” : ViewModel, Entidade de Domínio e as Entidades do Entity. Como eu usaria o automapper nessa situação? Teria que installar na camada de Apresentação e na Infraestrutura?

    • Fala Renan,

      Nesse caso vc entrou num cenário complexo, pode haver alguns problemas devido a esse modelo.
      Eu opto em refazer o modelo usando o EF Power Tools e recriar minhas entidades sem depender do EDMX.

      Abs!

  6. Ótimo tutorial, Eduardo!
    Mas surgiu uma dúvida quando fui utilizar o AutoMapper com classes que herdem de uma classe base. Por exemplo:
    Crio uma classe chamada EntityBase com um Guid e uma Data de Criação.
    Faço com que todas as minhas entidades herdem de EntityBase afim de que todas tenham por padrão esses campos e eu não tenha que cria-los manualmente a cada nova entidade.

    O AutoMapper não consegue atribuir valores automaticamente a essas propriedades herdadas.

    Você tem alguma dica de como fazer isso?

  7. Pingback: Você conhece o AutoMapper? | akaMud – Blog

  8. Bom dia Eduardo.

    Muito bom o artigo, porém eu tenho uma dúvida.

    No seu outro artigo você comenta que podemos criar uma “ViewModel” específica para anteder o nosso negócio.

    Ex:
    public class CarrinhoComprasViewModel
    {
    public IEnumerable Produtos { get; set; }
    public decimal TotalCarrinho { get; set; }
    public string Mensagem { get; set; }
    }

    Como eu posso utilizar o AutoMapper para realizar esse mapeamento da minha ViewModel (customizada) com a(s) minhas classes na Model (Produtos, ProdutosItens, Etc…) ?

    Ou seja, como posso mapear uma ViewModel para duas ou mais Model?

    Obrigado.

  9. Fala Eduardo, tudo joia?
    Então, entendi o uso do auto mapper graças a você hehe, mas fiquei com uma dúvida:

    Como que eu faço o mapeamento de um ViewModel que possui propriedades de dois models e o passo reverso(dos models para o ViewModel)? Estilo Nota e itens da nota.

    Desde já agradeço,

    • No contexto do artigo a o Mapper fica na camada apresentação (MVC). Em alguns casos sua aplicação poderá consumir dados externos na camada de serviço e, nesse caso, é possível usar o AutoMapper para converter da Model “externa” para a sua.

  10. Fala Eduardo,
    primeiramente parabéns pelos artigos, você tem me ajudado muito em meu amadurecimento como programador.

    Uma duvida, eu costumo utilizar em meus projetos ORM EntityFramework com database-first. Minha dúvida é o seguinte, estou estudando sobre DDD e por usar database-first, eu gero minhas entidades de persistência pelo proprio entity framework (Poco To Entities por exemplo). Utilizar o AutoMaper para mapear meus modelos de domínio para o banco é uma boa pratica? Você recomenda outra maneira?

  11. Fala Eduardo, não conhecia isso. Ficou muito bom usando o AutoMapper agora! Parabens por divulgar conhecimentos.

  12. Muito simples e direta a explicação. Esclareceu perfeitamente uma dúvida que eu tinha! Parabéns pelo post!

  13. Excelente postagem! Depois que li este artigo e um complemento no Stackoverflow, em questão de uma hora já estava com o Autommaper configurado e rodando com um converter customizado em meu projeto.

    Como resultado o meu Controller ficou mais limpo mesmo tendo que ensinar o Automapper a converter de uma classe de domínio para Dictionary.

  14. O mais importante neste tipo de abordagem é a clareza e objetividade do artigo.
    Os quesitos foram muito bem utilizados, foi muito esclarecedor.

    Muito obrigado!

  15. Cara, sério, escreva um livro!
    Muito boa a sua escrita e a forma que passa as informações!
    Obrigado pelas dicas e abraços!

  16. Eduardo,

    Tenho seguido alguns dos seus tutoriais e de uns tempos pra cá o AutoMapper começou a reclamar de que o Mapper.Map está obsoleto.

    Mapper.Map<IEnumerable,
    IEnumerable>(_clientApp.GetAll())

    Sabe como resolver para utilizar a nova versão?

    • João Duarte,

      Houve mudança de versão no AutoMapper.

      Na classe DomainToViewModelMappingProfile, por exemplo, ele estava reclamando. Tirei o nome da classe Mapper e parou de reclamar.

      Antes: Mapper.CreateMap();

      Agora:

      public class DomainToViewModelMappingProfile : Profile
      {
      protected override void Configure()
      {
      CreateMap();
      }
      }

      Na classe de serviço da Application. Ex.: AlunoAppService, o método de adição não mudou…

      public void AdicionarAluno(AlunoViewModel alunoViewModel)
      {
      var aluno = Mapper.Map(alunoViewModel);

      // Consome serviço de domínio
      _alunoService.AdicionarAluno(aluno);
      }

      Será que o seu problema também não é na configuração?

    • ótimo artigo..Parabéns Eduardo.

      só fiquei com uma dúvida…
      como posso fazer com que as validações criadas no ViewModel funcionem no WindowsForms no C#? pois todos os exemplos que encontrei sobre viewModel sao para ASP.net

    • Não apenas o Mapper ficou desatualizado (como o Paulo disse, parece que basta chamar CreateMap direto), mas o método sobrescrito Configure() reclama que está obsoleto.

  17. Foi criado uma ClienteViewModel para adicionar um campo NumeroDaSorte é o DataAnnotations , este foi o motivo de se utilizar o AutoMapper. Mais o porquê não poderia ser adicionar o campo NumeroDaSorte é DataAnnotations junto com a classe Cliente?

    • Caro SSouza, o post é antigo mas acho que ainda dá tempo: Termos como Padrões, Boas práticas de programação devem sempre estar presentes na vida do programador, amador ou profissional. Isto leva seu código a se resumir em Organização e (na tão falada pelo autor aqui e na maioria de seus posts) Elegância. Trate seu código com carinho, mantenha-o organizado e elegante, seguindo as boas práticas de programação e os padrões adotados no mundo inteiro. Se você for uma pessoa organizada isto não vai ser problema para você.

  18. Alguem ja teve este erro

    Additional information: Expression ‘vm => Convert(vm.Endereco.Id)’ must resolve to top-level member and not any child object’s properties. Use a custom resolver on the child type or the AfterMap option instead.

  19. Eduardo, muito bom o post!
    Uma dúvida, tem a possibilidade do autoMapper perder em performance ?? Exemplo em uma conversão de Collection que tem outros objetos ??

    • Janderson, para resultados complexos existe sim uma perca de performance, uma alternativa é o Dapper, dá uma lida nele que é muito simples de usar também.

  20. Estarei utilizando o AutoMapper no projeto atual e esse post me mostrou que é uma ferramenta bem simples de implementar.

  21. Muito bom!
    Parabéns pelos artigos, eu como um iniciante na programação, estou conseguindo acompanhar seus posts facilmente. Ótimas explicações. Parabéns!

  22. Eduardo tenho uma questionamento mais complicado a fazer, tenho a seguinte situação : classe Usuario {
    public Nullable usu_tipo { get; set; }
    …..
    }
    Não quero mostrar para o usuário essa informação pois ele não saberá do que se trata quero informar assim na grid esse campo :
    1 – Estudante
    2 – Avulso

    Pesquisei e ví que a melhor maneira seria usar view model olhando esse seu tutorial achei ideal, mais na implementação como associo esse campo no view model ?

  23. Boa noite Eduardo,
    Estou a procura de explicações do AutoMapper 5.0.2, você tem alguma explicação, conselhos ou algo que possa me ajudar? Preciso de fazer as configurações mas não estou conseguindo.

    Aguardo retorno, abraço.
    Atenciosamente,
    Bruno Hilário

  24. Bom dia.

    Como faço para realizar um mapper de um objeto que contem uma sublista?
    ex:
    public int Mobilidade { get; set; }
    public decimal NotaMobilidade { get; set; }
    public List FormacaoModel{ get; set; } //como resolvo esse?

    • Assumindo que a sua classe chama-se Mobilidade, uma maneira que você pode fazer isso é criando um conversor customizado para mapear a sua lista de FormacaoModel (no caso abaixo chamado de MobilidadeConverter:

      // mapeamento da classe usando o conversor customizado
      Mapper.CreateMap<Mobilidade, IEnumerable>().ConvertUsing(); // cria a lista de FormacaoModel (dto’s)

      Basta agora, criar a classe do seu conversor customizado para mapear a lista (MobilidadeConverter):

      class MobilidadeConverter : ITypeConverter<Mobilidade, IEnumerable>
      {
      public IEnumerable Convert(DbContext context)
      {
      Mobilidade mobilidade = (Mobilidade)context.SourceValue;
      foreach (var dto in mobilidade.FormacaoModel.Select(e => Mapper.Map(e)))
      {
      Mapper.Map(mobilidade, dto); // mapeia Mobilidade(int) e NotaMobilidade
      yield return dto;
      }
      }
      }

      Acho que seria isso. Espero ter ajudado. 😀

  25. Alguém pode informar como ficou a versão mais nova do AutoMapper?

    Pois a sobrescrita diz que está obsoleto. E os exemplos dados aqui nenhum funcionou.

    Valeu galera

  26. Ambos estão dando erro, alguem já conseguiu fazer funcionar na versão mais nova?

    public class DomainToViewModelMappingProfile : Profile
    {
    public override string ProfileName
    {
    get { return “DomainToViewModelMappings”; }
    }

    protected override void Configure()
    {

    Mapper.CreateMap();
    }

    }

    ——————

    public class ViewModelToDomainMappingProfile : Profile
    {
    public override string ProfileName
    {
    get { return “ViewModelToDomainMappings”; }
    }

    protected override void Configure()
    {
    Mapper.CreateMap();
    }
    }

    • Rogerio, eu estava com o mesmo problema e as soluções postadas aqui também não funcionaram pra mim. Estou usando atualmente a versão 6.0.2 do AutoMapper. Segue abaixo o código que funcionou nesta versão seguindo o padrão mostrado pelo Eduardo no vídeo.

      Na classe AutoMapperConfig não mudou nada:

      public class AutoMapperConfig
      {
      public static void RegisterMappings()
      {
      Mapper.Initialize(x =>
      {
      x.AddProfile();
      x.AddProfile();
      });
      }
      }

      As mudanças foram somente nas classes “ViewModelToDomainMappingProfile” e “DomainToViewModelMappingProfile” onde o criação dos mapeamentos são feitos diretamente no construtor das classes. Segue:

      public class ViewModelToDomainMappingProfile : Profile
      {
      public ViewModelToDomainMappingProfile()
      {
      CreateMap();
      CreateMap();
      CreateMap();
      CreateMap();
      }
      }

      public class DomainToViewModelMappingProfile : Profile
      {
      public DomainToViewModelMappingProfile()
      {
      CreateMap();
      CreateMap();
      CreateMap();
      CreateMap();
      }
      }

      Sei que o seu post já é antigo e provavelmente você já deve ter resolvido o seu problema, mas como eu precisei disso agora e demorei muito pra encontrar algo que funcionasse na versão 6.x, resolvi deixar a solução aqui para futuras consultas.
      Grande abraço e espero que ajude outras pessoas.

  27. Olá Eduardo,
    Mas vamos imaginar que temos um projeto com mais camadas (BLL, DAO etc…) ou utilizando o modelo DDD.
    Vc continuaria mantendo a conversão utilizada pelo AutoMapper dentro da Action do Controller? Pois vi no asp.net cast que vc participa, dizendo que não podemos “sujar” o controller com muitas tarefas.

    Abraço

  28. Boa Tarde!

    Seguir o passo a passo, mas sempre acontece esse erro

    “Erro de Servidor no Aplicativo ‘/’.

    Não foi possível carregar arquivo ou assembly ‘AutoMapper, Version=5.2.0.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005’ ou uma de suas dependências. A definição do manifesto do assembly localizado não corresponde à referência do assembly. (Exceção de HRESULT: 0x80131040)”

    Não conseguir resolver.

    Poderia ajudar?

  29. Oi Eduardo, parabéns pelo vídeo!

    Conheci o seu trabalho tem pouco tempo e estou lendo vários de seus artigos. No artigo em que você fala sobre o AutoMapper, na classe “DomainToViewModelMappingProfile”, você está utilizando uma ordem diferente de mapeamento da que é utilizada no vídeo:

    Vídeo: CreateMap();

    Artigo: CreateMap();

    Obs: percebi que o AutoMapper não permite mais utilizar o Mapper.CreateMap, apenas o CreateMap. Deu certo no exemplo que fiz.

    A função diz “CreateMap”, então a forma de certa seria o exemplo que está no artigo ou não teria problema em escrever assim?

    Sou novo na área de desenvolvimento e agradeço muito por compartilhar seu conhecimento.

    • Não deixou publicar as tag do CreateMap, no caso seria mais ou menos assim:

      Vídeo: CreateMap ClienteViewModel, Cliente();

      Artigo: CreateMap Cliente, ClienteViewModel();

      sem as tags.

  30. Não existe uma forma de deixar a ViewModel mais fácil de ser configurada? Pois dessa forma temos que recriar uma classe que já existe, repetindo código, só pra adicionar um campo, e quando alguma informação for modificada na Model, a ViewModel ficará desatualizada, já que não existe nenhum vinculo explicito entre elas, porque nesse caso não é melhor usar herança ou composição?

  31. Post muito bem escrito, melhor que a documentação do automapper, venho programando a quase 1 ano e sempre procuro melhorar meu código, vi a necessidade de mappear as classes de uma forma mais automatica, de começo pensei em fazer um módulo para esse mappeamento, porém, com um rápida pequisa achei seu artigo e pronto, agora esta tudo como deveria.

    Automapper ajuda o código a ficar limpo, sem necessidade de ficar mappeando classes na mão, parabéns pelo seu artigo.

  32. Excelente artigo. Simples, objetivo e que agrega alto valor para os desenvolvedores. Parabéns!

  33. ALGUEM JA CORRIGIU ESSE ERRO? vs2012 automapper 4.2.1 me dá esse erro, n consigo resolver

    Missing type map configuration or unsupported mapping.

    Mapping types:
    Cliente -> ClienteViewModel
    Etecno.Domain.Entities.Cliente -> Etecno.MVC.ViewModels.ClienteViewModel

    Destination path:
    IEnumerable`1[0]

    Source value:
    Etecno.Domain.Entities.Cliente

    • Exelente Post. Claro e objetivo. Muito bem detalhado. Parabéns Eduardo. Gostaria que falasse mais um pouco sobre como utilizar com segurança “.ForMember” e aquelas Options que se usam o source / target. Um grande abraço.

Os comentários estão fechados.