ASP.NET Identity – Customizando o cadastro de usuários

Com o lançamento do ASP.NET MVC 5 um novo modelo de autenticação e autorização foi disponibilizado, o ASP.NET Identity, uma solução muito mais aberta e granular, acompanhe aqui como efetuar algumas customizações.

O ASP.NET Identity pode ser configurado no momento da criação da aplicação web, onde algumas opções são disponibilizadas para sua utilização, neste exemplo utilizarei o modelo de Individual User Accounts (modelo padrão).

ASP.NET Identity

O template de projeto que o Visual Studio disponibiliza na criação da aplicação ASP.NET MVC contempla uma implementação do ASP.NET Identity da qual já é possivel cadastrar-se como usuário. Ao executarmos o projeto pela primeira vez e clicar no link Register no topo da aplicação, será exibida a View de registro.

ASP.NET Identity

Até este ponto mais fácil seria impossível certo?
Suponha que o seu cadastro necessite de mais algumas informações como:

  • Nome
  • Sobrenome
  • E-mail

O ASP.NET Identity expõe um conjunto de classes de forma que fica muito fácil realizar qualquer tipo de customização. Mãos à obra.

Passo 1 – Customizar a classe de usuário

Localize e abra o arquivo IdentityModels.cs na pasta Models do seu projeto ASP.NET MVC. O código original será este:

namespace DemoIdentity.Models
{
    public class ApplicationUser : IdentityUser
    {
    }

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext()
            : base("DefaultConnection")
        {
        }
    }
}

Observe que existem duas classes nesse arquivo (depois refatoramos) a classe ApplicationUser é sua classe de usuário, note que ela não possui propriedade nenhuma apenas herda de IdentityUser, pois é esta classe que possui as propriedades de usuário, a classe ApplicationUser está ali disponível justamente para a customização.

Abaixo o código após a customização

namespace DemoIdentity.Models
{
    public class ApplicationUser : IdentityUser
    {
        public string Nome { get; set; }

        public string Sobrenome { get; set; }

        public string Email { get; set; }
    }

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext()
            : base("DefaultConnection")
        {
        }
    }
}

Passo 2 – Customizar a ViewModel

Neste projeto está sendo utilizado o padrão ViewModel, isso significa que a View de registro é baseada nesta ViewModel para exibir as informações em tela.

Localize e abra o arquivo AccountViewModels.cs na pasta Models, originalmente existem quatro classes neste mesmo arquivo (mais um item para refatorar). Encontre a classe RegisterViewModel:

public class RegisterViewModel
{
    [Required]
    [Display(Name = "User name")]
    public string UserName { get; set; }

    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }
}

A mesma classe agora após a customização:

public class RegisterViewModel
{
    [Required]
    [Display(Name = "User name")]
    public string UserName { get; set; }

    [Required]
    public string Nome { get; set; }

    [Required]
    public string Sobrenome { get; set; }

    [Required]
    [Display(Name = "E-mail")]
    [EmailAddress]
    public string Email { get; set; }

    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }
}

Note que fiz uso de alguns DataAnnotations para configurar que os campos sejam requeridos e para ocorrer a validação de formato de email durante o input dos dados.

Passo 3 – Customizar a View

Agora para preencher com dados as novas propriedades da ViewModel será necessário customizar a View.

Localize e abra o arquivo Register.cshtml na pasta Views > Account.
Note que a View faz uso da ViewModel que acabamos de customizar

@model DemoIdentity.Models.RegisterViewModel

O resultado final da View será esse:

@model DemoIdentity.Models.RegisterViewModel
@{
    ViewBag.Title = "Register";
}

<h2>@ViewBag.Title.</h2>

@using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()
    <h4>Create a new account.</h4>
    <hr />
    @Html.ValidationSummary()
    <div class="form-group">
        @Html.LabelFor(m => m.UserName, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.Nome, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Nome, new { @class = "form-control" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.Sobrenome, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Sobrenome, new { @class = "form-control" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" class="btn btn-default" value="Register" />
        </div>
    </div>
}

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

Execute a aplicação para validar o resultado:

ASP.NET Identity

Passo 4 – Customizar a Controller

Este é o passo final, apesar da navegação estar pronta, a Controller ainda não está apta a receber as novas propriedades customizadas e realizar a gravação no banco.

Localize e abra o arquivo AccountController.cs na pasta Controllers
Identifique a Action de registro, o código original será este:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = new ApplicationUser() { UserName = model.UserName };
        var result = await UserManager.CreateAsync(user, model.Password);
        if (result.Succeeded)
        {
            await SignInAsync(user, isPersistent: false);
            return RedirectToAction("Index", "Home");
        }
        else
        {
            AddErrors(result);
        }
    }

    return View(model);
}

Após a customização o resultado deverá ser este:

public async Task<ActionResult> Register(RegisterViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = new ApplicationUser()
        {
            UserName = model.UserName,
            Nome = model.Nome,
            Sobrenome = model.Sobrenome,
            Email = model.Email
        };

        var result = await UserManager.CreateAsync(user, model.Password);
        if (result.Succeeded)
        {
            await SignInAsync(user, isPersistent: false);
            return RedirectToAction("Index", "Home");
        }
        else
        {
            AddErrors(result);
        }
    }

    return View(model);
}

Note que esta Action recebe o objeto RegisterViewModel como parâmetro, foi necessário apenas inserir as novas propriedades do objeto ApplicationUser que receberão as informações que vieram da ViewModel.

Sua customização está finalizada, execute a aplicação, registre um usuário e confira o resultado.

Observações:

  • O primeiro cadastro pode demorar um pouco, pois o mecanismo do Code First está criando o banco de dados e as tabelas necessárias para o ASP.NET Identity operar.
  • Faça testes no formulário, por ex, deixar algum campo em branco ou usar um e-mail em formato inválido.

Após registrar o usuário pela aplicação, você pode conferir o resultado da criação do banco de dados através do painel SQL Server Object Explorer do Visual Studio:

ASP.NET Identity

Vimos que é muito fácil realizar uma customização de um controle de acesso pelo ASP.NET Identity, caso queira criar mais campos basta seguir o mesmo roteiro.

Referências

Em breve publicarei mais artigos de customização do ASP.NET Identity, com técnicas mais avançadas e refatoração do projeto original.

Ficou com dúvidas? Quer compartilhar conosco alguma experiência? Utilize os comentários abaixo 😉

Até a próxima.

Campus Party 2014 – Palestra sobre ASP.NET

No dia 31/01 eu tive o prazer de palestrar na Campus Party 7 – Edição 2014 / SP meu tema foi sobre ASP.NET, novidades, tendências e mobilidade.

Para quem não sabe a Campus Party é o maior evento tecnológico do mundo, ela atrai anualmente geeks, nerds, empreendedores, gamers, cientistas e muitos outros criativos que reúnem-se para acompanhar centenas de atividades sobre Inovação, Ciência, Cultura e Entretenimento Digital.

Foi o maior evento onde palestrei, fico muito satisfeito em ter palestrado no mesmo evento que meu ídolo Bruce Dickinson 😉

Motivos não faltaram para eu compilar e buscar compartilhar o máximo de informações possíveis sobre a plataforma ASP.NET, minha palestra foi na virada da madrugada, mas mesmo assim o público foi chegando e quando notei a audiência estava ótima!

Ao finalizar minha apresentação o retorno também foi ótimo, recebi muitos feedbacks positivos, tirei bastante dúvidas e conversei com o pessoal que ficou para continuar o assunto comigo fora do palco.

Disponibilizo para visualização os slides que utilizei em minha palestra.

Com certeza estarei de volta na Campus Party ano que vem, espero que me apresentando novamente também.

Acompanhe e conheça mais o evento no site oficial da Campus Party.

Abraços!

ASP.NET MVC 5.1 – O que mudou?

Foi anunciado em 20/01/2014 o release do ASP.NET MVC 5.1 que chegou com boas novidades e atualizações, na mesma data o Visual Studio recebeu o Update 1, confira em detalhes.

ASP.NET MVC 5.1

Requerimentos de Software

Download

A release do ASP.NET MVC 5.1 foi liberada como um pacote disponível na galeria NuGet. Todos os pacotes sequem a especificação Semantic Versioning, por exemplo o ASP.NET MVC 5.1 RTM tem a seguinte versão: “5.1.0”.

Para facilitar mais você ainda pode utilizar o NuGet Package Manager Console com o seguinte comando:

Install-Package Microsoft.AspNet.Mvc -Version 5.1.0

Documentação

Tutoriais e outras informações sobre o ASP.NET MVC 5.1 estão disponíveis no site oficial do ASP.NET (http://www.asp.net)

Novidades no ASP.NET MVC 5.1

Melhorias no Attribute routing

O Attribute Routing agora suporta restrições, permitindo o versionamento e header baseado na seleção da rota. Muitos aspectos de attribute routes podem agora ser customizados via a interface IDirectRouteFactory e a classe RouteFactoryAttribute.

Suporte a Enum nas views

  1. Novo helper @Html.EnumDropDownListFor() Pode ser usado como a maioria dos HTML helpers com a ressalva que a expressão precisa ser avaliada como um tipo de Enum ou um Nullable<T> onte T é um tipo de enun. Utilize EnumHelper.IsValidForEnumHelper() para verificar estes requerimentos.
  2.  

  3. Novo método EnumHelper.GetSelectList() qual retorna um IList<SelectListItem>.
    Isto é útil quando você precisa manipular uma select lista antes de chamá-la, por exemplo um @Html.DropDownListFor(), ou quando você desejar exibir os nomes que o @Html.EnumDropDownListFor() mostra.

O código a seguir demonstra como aplicar:

@if (EnumHelper.IsValidForEnumHelper(ViewData.ModelMetadata))
{
    @Html.EnumDropDownListFor(model => model, htmlAttributes: new { @class = "form-control" })
}
@if (EnumHelper.IsValidForEnumHelper(ViewData.ModelMetadata))
{
    foreach (SelectListItem item in EnumHelper.GetSelectList(ViewData.ModelMetadata,
	(Enum)Model)) { … }
}

Você pode conferir um exemplo completo aqui.

suporte a Bootstrap em editor templates

Agora é possível passar no EditorFor um atributo HTML como um objeto anônimo:

Exemplo:

@Html.EditorFor(model => model, new { htmlAttributes = new { @class = "form-control" }, })

Validação não intrusiva para MinLengthAttribute e MaxLengthAttribute

Validações client-side para string e arrays agora são suportadas para as propriedades decoradas com os atributos MinLength e MaxLength.

Supporte ao contexto ‘this’ no Ajax não intrusivo

As funções de callback (OnBegin, OnComplete, OnFailure, OnSuccess) agora estão habilitadas a localizar o elemento da invocação através do contexto ‘this’. Exemplo:

@Ajax.ActionLink("Click me", "AjaxAction", new AjaxOptions { UpdateTargetId = "foo", OnBegin = "OnClick" })

<script>
    function OnClick(jqXHR) {
        if ($(this).hasClass("foo")) {
            jqXHR.setRequestHeader("custom-header", "value");
        }
    }
</script>

Problemas Conhecidos e Mudanças Significativas

Attribute Routing

Ambiguidades nas correspondências de attribute routing agora irão reportar um erro em vez de escolher a primeira correspondência.

Attribute Routes estão proibidos de usar o parâmetro {controller} e de usar o parâmetro {action} em rotas colocada em actions. O uso destes parâmetros muito provavelmente levará a gerar ambiguidades.

utilizar Scaffolding de MVC/Web API em um projeto com pacotes 5.1 resultará em pacotes 5.0 para aqueles que ainda não existem no projeto.

Atualizar para ASP.NET MVC 5.1 através dos pacotes NuGet não atualiza as ferramentas como Scaffolding ou o template de ASP.NET Web Application.

Eles usam uma versão anterior do ASP.NET (5.0.0.0). Como resultado o Scaffolding irá instalar os pacotes antigos (5.0.0.0) como pacotes requeridos se ainda não estiverem disponíveis em seu projeto. Entretanto o Scaffolding do Visual Studio 2013 RTM ou Update 1 não sobrescreve os últimos pacotes em seu projeto.

Se você usar Scaffolding após ter atualizados os pacotes em seu projeto para Web API 2.1 ou ASP.NET MVC 5.1, confira se as versões estão consistentes.

Syntax Highlighting para Razor Views no Visual Studio 2013

Se você atualizar para o ASP.NET MVC 5.1 RTM sem atualizar o Visual Studio 2013, você não conseguirá o suporte no editor para o syntax highlighting enquanto estiver editando as Razor Views, você precisará atualizar o Visual Studio 2013 para obter este suporte.

tipos renomeados

Alguns dos tipos (types) utilizados para a extensibilidade do attribute routing foram renomeados na versão do ASP.NET MVC 5.1 RTM.

Nome do Tipo Antigo (5.1 RC) Novo Nome do Tipo (5.1 RTM)
IDirectRouteProvider IDirectRouteFactory
RouteProviderAttribute RouteFactoryAttribute
DirectRouteProviderContext DirectRouteFactoryContext

Correções de Bugs

O time do ASP.NET realizou a correção de diversos bugs da versão anterior como parte deste release (ASP.NET MVC 5.1 RTM). Confira a lista completa de todos os bugs corrigidos (e outros ainda em andamento) aqui.


Estas são todas as novidades da versão ASP.NET MVC 5.1, lembre-se de atualizar a sua versão do Visual Studio 2013 para o melhor proveito das novidades.

Em breve publicarei um artigo sobre as novidades do ASP.NET WebAPI 2.1.

Referências

Até a próxima 😉

Agora sou um Microsoft MVP

É com uma imensa satisfação que informo a todos que fui nomeado Microsoft MVP Most Valuable Professional na competência ASP.Net / IIS.

Microsoft MVP

O título de Microsoft MVP é um reconhecimento dado pela Microsoft aos profissionais que possuem profundos conhecimentos em algum produto / tecnologia Microsoft.
Existem diversas competências que são elegíveis, a minha especialidade é ASP.Net / IIS.

Atualmente existem cerca de 4.000 MVPs em todo mundo e cerca de 100 MVPs no Brasil.

Eu quis escrever este post para agradecer as pessoas que foram importantes nessa conquista e contar um pouco sobre a trajetória para quem está interessado em seguir este caminho.

Eu conheci o título de MVP quando trabalhei em uma consultoria em 2004, sempre valorizei os profissionais que possuem este reconhecimento, pois sempre foram pessoas de destaque e admiração. Em meados de 2011 eu mudei muitas coisas em minha vida e decidi dividir o conhecimento que acumulei até agora nesses 14 anos de trabalho em TI. Minha primeira ação foi criar este blog e escrever meus primeiros artigos.

Junto ao blog iniciei diversas ações paralelas, atuando nos fóruns da Microsoft onde respondo muitas dúvidas, divulgando informações importantes sobre tecnologia nas maiores redes sociais, gravando vídeo-aulas e claro realizando palestras e eventos.

Eu penso que o título de MVP é dado a profissionais com grande destaque técnico em uma determinada categoria, porém na minha opinião o mais importante é a paixão em dividir o conhecimento com todos, isso não é trabalho fácil, é necessário doar muito tempo e energia, fazer escolhas entre compromissos e vida pessoal, etc…

Durante o período de 2011 até agora eu me dediquei durante muitas horas (muitas mesmo) para produzir e gerar conteúdos técnicos, viajei diversas vezes para palestrar fora da cidade, tudo isso com dinheiro do próprio bolso, deixei de ficar muitos finais de semana inteiros com filho e namorada para poder estar presente em eventos importantes, mesmo que não fosse para palestrar. Tudo isso tem um custo pessoal muito alto mas o retorno deste trabalho existe na satisfação em ajudar as pessoas, ser reconhecido pelo conhecimento técnico e claro receber um prêmio destes que é o maior reconhecimento da Microsoft.

Isso tudo ajudou em muito na minha carreira também, muitas coisas boas surgiram através deste trabalho e meu conhecimento técnico cresceu numa velocidade muito maior.

Gostaria de agradecer em especial algumas pessoas que me ajudaram muito neste caminho:

Primeiramente ao mestre Ramon Durães, que deu minha primeira oportunidade de palestrar em um evento, eu nunca havia me apresentado antes e mesmo assim pude palestrar no VS Summit 2012, após isso muitas outras oportunidades surgiram. E também me indicou a concorrer ao título de Microsoft MVP. Muito obrigado mestre!

Agradeço ao meu amigo Fernando Henrique, por me motivar a tentar conquistar o título, me ajudou muito me indicando e tirando diversas dúvidas, principalmente sobre o processo de nomeação, sem esta motivação eu não teria chegado tão cedo, muito obrigado!

Agradeço ao meu amigo Rogério Rodrigues por ter me convidado para palestrar em diversos eventos como os do DevBrasil e em universidades, isso me ajudou bastante, muito obrigado!

Agradeço ao meu amigo Waldyr Felix por também ter me indicado a concorrer ao prêmio Microsoft MVP.

Agradeço a Fernanda Saraiva, líder dos MVPs do Brasil, por ter me aprovado no processo seletivo, me indicar a para receber o título e ter acreditado no meu trabalho. Muito obrigado.

Agradeço muito minha família e filho, pois sempre acreditaram no meu trabalho e sempre me apoiaram em tudo que fiz.

E agradeço especialmente minha namorada Juliana, por ter me acompanhado desde o primeiro passo, revisou PPTs e artigos comigo, me acompanhou em palestras, teve muita paciência comigo e me emprestou durante muitos finais de semana para eu poder realizar este trabalho.

Até eu descobrir que havia sido nomeado Microsoft MVP eu acreditava ser algo inatingível, mas é, basta fazer um trabalho bem feito, se relacionar bem com a comunidade e uma hora tudo acontece 🙂

Este reconhecimento é um grande motivador para que eu faça ainda mais, pretendo entregar muito mais em 2014 e renovar durante muitos anos o título de Microsoft MVP.

Obrigado a todos que participaram aqui no blog, nas redes sociais ou pessoalmente, este reconhecimento é um resultado que dependeu de cada um de vocês.

E este ano irei para Seattle com todos os MVPs do mundo, finalmente vou conhecer a sede da Microsoft o/

Conheça um pouco mais sobre o prêmio Microsoft MVP

Abraços!

Ebook – Guia .Net para Aplicações Corporativas.

Guia .Net para Aplicações Corporativas (título traduzido) é um e-Book gratuito com um conteúdo muito recente e atualizado, ideal para arquitetos e desenvolvedores que desejam ampliar os conhecimentos sobre abordagens e tecnologias disponíveis para construir aplicações corporativas modernas.

Guia .Net para Aplicações Corporativas

Fiz o download desde e-Book hoje, já li cerca de 40% e estou gostando o suficiente para compartilhar com vocês. Confira o conteúdo:

.NET Technology Guide for Business Applications

  1. Key takeaways
  2. Purpose of this guide
    • WHO SHOULD USE THIS GUIDE
    • HOW TO USE THIS GUIDE
  3. Overview
    • THE NET FRAMEWORK AND THE FUTURE OF DEVELOPMENT
  4. Emerging application patterns
    • DEVICES
      • Native applications for Windows devices
      • Web applications for any device
    • SERVICES
    • CLOUD AND HYBRID-CLOUD
    • END-TO-END SCENARIOS IN EMERGING APPLICATION PATTERNS
      • Scenario: Connected Native Windows Store Applications
      • Scenario: Modern Web Applications for Any Mobile Device (Tablets and phone)
  5. Established application patterns
    • BUSINESS APPLICATIONS SEGMENTATION BY PRIORITIES
    • SMALL AND MEDIUM-SIZED BUSINESS APPLICATIONS
      • Data-centric web business applications
      • Scenario: End-to-End Small/Medium Web Business Applications
      • Mixed approach for small/medium business web applications
      • Data-centric desktop business applications
      • Scenario: Small/Medium 2-Tier Desktop Application
      • Scenario: Small/Medium 3-Tier Desktop Applications
      • Modernizing desktop business applications
      • Modernizing applications based on RIA containers
    • CLOUD APP MODEL FOR OFFICE AND SHAREPOINT
      • Apps for Office
      • Scenario: Connected Apps for Office
      • Apps for SharePoint
      • Scenario: Connected Apps for SharePoint
    • LARGE, MISSION-CRITICAL BUSINESS APPLICATIONS
      • NET in large, mission-critical and core-business applications
      • Technology selection for large mission-critical and core-business applications
      • Scenario: Large, Core-Business Applications
      • Approaches and trends for long-term core-business applications
      • Loosely coupled architecture and the dependency-inversion principle
      • Architectural styles for core-business applications
      • Modernizing mission-critical enterprise applications
      • Scenarios for custom large, mission-critical applications
      • Scenario: Domain-Driven Subsystem (Bounded Context)
      • Scenario: CQRS Subsystem (Bounded Context)
      • Scenario: Communicating Different Bounded Contexts
      • NET Technology Guide for Business Applications
      • Scenario: Modernizing Legacy Mission-Critical Enterprise Applications
  6. Conclusions
    • Appendix A: Silverlight migration paths
    • Appendix B: Positioning data-access technologies

O download está disponível neste link. (PDF 6.02 MB)

Referencias

Boa leitura a todos!

Workshop de ASP.Net MVC 5 – Microsoft Technology Center

Foi realizado no dia 09/09 o Workshop de ASP.Net MVC 5 Fundamentals no Microsoft Technology Center (MTC) em São Paulo, onde foi realizada uma imersão de alto impacto para profissionais da área.

ASP.Net MVC 5 Fundamentals

Compartilho que tive o prazer de ministrar e conduzir o conteúdo técnico deste workshop exclusivo, cerca de 20 profissionais se inscreveram e compareceram para uma imersão completa ao ASP.Net MVC, profissionais de diversas áreas de TI, em sua maioria desenvolvedores.

O conteúdo do workshop abordou toda a trajetória do ASP.Net onde foram feitas comparações técnicas entre WebForms e MVC. Benefícios e diferenças do padrão MVC foram colocadas em destaque para que os profissionais pudessem descobrir as inúmeras vantagens em optar pelo ASP.Net MVC em seus projetos.

ASP.Net MVC 5 Fundamentals

O ASP.Net MVC 5 é uma das novidades que acompanham o lançamento do Visual Studio 2013, escrevi um artigo dedicado a esse assunto, no workshop os profissionais além de serem apresentados aos conceitos do padrão MVC também conheceram todas as novidades presentes no ASP.Net MVC 5 em conjunto com o Visual Studio 2013.

ASP.Net MVC 5 Fundamentals

Foram 8 horas de apresentação de conteúdos que proporcionaram um conhecimento geral, foram eles:

  • Controllers
  • Views
  • Models
  • Bootstrap
  • HTML Helpers
  • Data Annotations e Validation
  • Rotas
  • jQuery, JSON e Ajax
  • OutputCache
  • View Model e AutoMapper
  • ASP.Net Identity
  • Segurança
  • One ASP.Net
  • Filters Overrides
  • Authentication Filters

Foi muito bom interagir e conhecer novos profissionais da área, seus projetos, experiências, poder compartilhar conhecimento e claro apresentar as novidades.

O workshop foi organizado e realizado pelo Ramon Durães – 2PC, onde fui convidado a conduzir o conteúdo, registro aqui minha satisfação pelo convite.

ASP.Net – Web Application Projects x Web Site Projects

No Visual Studio, você pode criar Web Application Projects ou Web Site Projects. É melhor escolher o tipo certo antes de criar um projeto web, porque pode ser demorado, difícil e propenso a erros para depois converter de um tipo para o outro.

Web Application Project

Web Application Project ou Web Site Project? Estas duas opções de criar uma aplicação web costumam gerar diversas dúvidas e problemas. Este artigo aborda todas as vantagens e desvantagens de cada uma para que a melhor escolha seja tomada conforme o seus cenários e necessidades.

Nota
Para um novo desenvolvimento é recomendado que seja escolhido o Web Application Project. Este artigo explica que Web Site Projects possuem algumas vantagens, mas muitos desenvolvedores que escolhem Web Site Projects, eventualmente descobrem que as desvantagens superam as vantagens percebidas. Além disso, à medida que novos recursos ASP.Net são desenvolvidos eles não vão estar sempre disponíveis para Web Site Projects. Por exemplo, a versão do Visual Studio 2013 possui novas ferramentas para a criação de projetos web e esta nova ferramenta vai trabalhar apenas com Web Application Projects. Para mais informações consulte Creating an ASP.NET Web Project in Visual Studio 2013.

Este artigo contém as seguintes seções:

Cenários

Cenários em que os Web Application Projects são uma escolha indicada incluem as condições:

    • Você quer ser capaz de usar o recurso Edit and Continue característico do depurador do Visual Studio.
    • Você deseja executar testes de unidade em código que está nos arquivos de classe que estão associados a páginas ASP.Net.
    • Você quer se referir às classes que estão associadas com as páginas e user controls a partir de classes standalone.
    • Você quer estabelecer dependências do projeto entre vários projetos web.
    • Você quer que o compilador crie um assembly único para todo o site.
    • Você quer controle sobre o nome do assembly e número de versão que é gerado para o site.
    • Você quer usar MSBuild ou Team Build para compilar o projeto. Por exemplo, você pode querer adicionar passos prebuild e postbuild.
    • Você quer evitar colocar o código-fonte em um servidor de produção.

Cenários em que Web Site Projects são uma escolha indicada incluem as condições:

    • Você deseja incluir o código C # e Visual Basic em um único projeto web. (Por padrão, uma aplicação web é compilada com base em configurações de idioma no arquivo de projeto. Exceções podem ser feitas, mas é relativamente difícil.)
    • Você deseja abrir o site em produção no Visual Studio e atualizá-lo em tempo real, utilizando FTP.
    • Você não quer ter que compilar explicitamente o projeto.
    • Se você pré-compilar o site, você quer que o compilador crie vários assemblies para o site, que pode incluir um assembly por página ou controle de usuário, ou um ou mais assemblies por pasta.
    • Você quer ser capaz de atualizar arquivos individuais na produção copiando apenas novas versões para o servidor de produção, ou editando os arquivos diretamente no servidor de produção.
    • Se você pré-compilar o site, você quer ser capaz de atualizar páginas da Web ASP.NET. Individuais (aspx) sem ter que recompilar todo o site.
    • Você gosta de manter seu código fonte no servidor de produção, pois pode servir como uma cópia de segurança adicional.

Resumo das Diferenças

A tabela a seguir resume as principais diferenças.

Área Web Application Projects Web Site Projects
Estrutura do arquivo de projeto
  • Um arquivo de projeto Visual Studio (. Csproj ou. Vbproj) armazena informações sobre o projeto, tais como a lista de arquivos que estão incluídos no projeto, e todas as referências de projeto a projeto.
  • Não há nenhum arquivo de projeto (. Csproj ou. Vbproj). Todos os arquivos em uma estrutura de pastas são automaticamente incluídas no site.
Compilação
  • O código fonte é compilado no computador que é usado para o desenvolvimento ou source control.
  • Por padrão, a compilação de arquivos de código (excluindo. Arquivos.ascx aspx e.) Produz um único assembly.
  • O código-fonte é normalmente compilado dinamicamente (automaticamente) pelo ASP.NET no servidor pela primeira vez quando um request é recebido depois que o site foi instalado ou atualizado. É possível pré-compilar o site (compilar com antecedência em um computador de desenvolvimento ou no servidor).
  • Por padrão, a compilação produz múltiplos assemblies.
Namespaces
  • Namespaces explícitos são adicionados a páginas, controles e classes por padrão.
  • Namespaces explícitos não são adicionados a páginas, controles e classes por padrão, mas você pode adicioná-los manualmente.
Desenvolvimento
  • Você copia o assembly para o servidor. O assembly é produzido através da compilação do aplicativo.
  • O Visual Studio fornece ferramentas que se integram com Web Deploy (ferramenta de deploy para IIS) para automatizar muitas tarefas de implantação.
  • Você copia os arquivos de origem do aplicativo em um computador que tem o IIS instalado.
  • Se você pré-compilar o site em um computador de desenvolvimento, você pode copiar os assemblies produzidas por compilação para o servidor IIS.
  • O Visual Studio fornece ferramentas que se integram com Web Deploy (ferramenta de deploy para IIS) para automatizar muitas tarefas de implantação.

Estrutura de Arquivos

Web Application Projects usam arquivos de projeto do Visual Studio (. Csproj ou. Vbproj) para acompanhar as informações sobre o projeto. Isso torna possível especificar quais arquivos são incluídos ou excluídos do projeto e, portanto, os arquivos que são criados durante uma compilação.

Para Web Site Projects todos os arquivos em uma estrutura de pastas são automaticamente considerados para serem incluídos no site. Se você quiser excluir algo da compilação, você deve remover o arquivo da pasta do projeto do web site ou alterar a sua extensão de nome de arquivo para uma extensão que não é compilado e não é enviado ao IIS.

Uma vantagem de usar arquivos de projeto em Web Application Projects é o seguinte:

  • É fácil de remover temporariamente os arquivos do site, mas ainda certificar-se de que você não perdê-los, porque eles permanecem na estrutura da pasta. Por exemplo, se uma página não está pronta para ser implantada, você pode excluí-la temporariamente a partir da compilação sem excluí-la da estrutura da pasta. Você pode implantar o assembly compilado e em seguida incluir o arquivo no projeto novamente. Isto é especialmente importante se você estiver trabalhando com um repositório de source control.

Uma vantagem de usar estrutura de pastas sem arquivos de projeto em Web Site Projects é o seguinte:

  • Você não tem que gerenciar a estrutura do projeto exclusivamente no Visual Studio. Por exemplo, você pode copiar os arquivos para o projeto ou excluí-los do projeto usando o File Explorer.

Compilação

Para Web Application Projects, você normalmente pode compilar o projeto no Visual Studio ou usando um ASP.Net batch compiler em um computador que não é o servidor IIS de produção. Todos os arquivos de classe code-behind e arquivos de classe standalone no projeto são compilados em um único assembly, que é então colocado na pasta Bin do Web Application Projects. (Os arquivos. Aspx e. Ascx são compilados dinamicamente de forma semelhante ao que é feito para Web Site Projects.)

Para Web Site Projects, você não tem que compilar manualmente o projeto. Web Site Projects normalmente são compilados dinamicamente pelo ASP.NET (tanto no computador de desenvolvimento e servidor IIS de produção). Você pode escolher entre o modo de compilação em lotes, que normalmente produz um assembly por pasta e modo de compilação fixa, que normalmente produz um assembly para cada página ou user control.

Vantagens do modelo de compilação de Web Application Projects incluem o seguinte:

    • Você pode usar o MSBuild para criar um custom batch-compilation process.
    • É fácil especificar os atributos do assembly, tais como nome e versão.
    • Compilando com antecedência garante que os usuários não tenham que esperar enquanto o site compila no servidor de produção. (Se o site é muito grande, compilação dinâmica de um Web Site Project pode levar uma quantidade considerável de tempo. Compilação dinâmica ocorre quando um request para um site é recebido após uma atualização, o request que desencadeia a compilação pode ser retardado enquanto os recursos necessários são compilados. Se o atraso for inaceitável, é possível pré-compilar o site. No entanto, em seguida, algumas das vantagens da compilação dinâmica são perdidas.)
    • Você tem o controle completo sobre onde colocar os arquivos de código fonte na estrutura de pasta do projeto e como as classes no projeto referem-se uns aos outros. (Compilação dinâmica requer que o código fonte para todas as classes que são usados em todo o site deve estar na pasta App_Code).

Vantagens do modelo de compilação para Web Site Projects incluem o seguinte:

    • Você pode testar as páginas específicas, independentemente do estado de outras páginas. Isso ocorre porque a rodar uma página individual não requer que todo o site seja compilado com sucesso, apenas a página e quaisquer componentes que depende, como o código na pasta App_Code ou no Global.asax. (Em um Web Application Project, se houver erros de compilação em qualquer lugar do site, você não pode criar os assemblies e, portanto, não pode testar até mesmo as partes do site que compilaram.)
    • É fácil atualizar um site em produção. Você pode atualizar os arquivos de código fonte individuais no servidor de produção sem ter que recompilar explicitamente o site. Você pode atualizar arquivos individuais que estão prontos para a implantação, mesmo que outros arquivos não estejam prontos devido a erros de compilação. Você também pode abrir o site no servidor IIS de produção diretamente no Visual Studio e atualizar o site em tempo real.
    • Pré-compilação de vários assemblies pode ter uma vantagem de desempenho em alguns cenários. Um exemplo típico é um site que tem muitas páginas com um monte de código escrito para eles. A maioria das páginas raramente são solicitadas e só algumas são usadas com freqüência. Se você compilar um site como este em várias assemblies o servidor de produção pode carregar apenas os assemblies que são necessários para as requisições atuais. Se uma página não é solicitada, a sua assembly correspondente não será carregada.
Nota
Não há diferença de desempenho entre um Web Site Project e um Web Application Project. As únicas exceções significativas são as que já foram observadas e por uma questão prática que se aplicam apenas aos sites muito grandes. O primeiro request para o web site pode requerer o site a ser compilado, o que pode resultar em um atraso. Se o site está sendo executado em um servidor IIS que possui pouca memória, possuindo todo o site em um único assembly pode usar mais memória do que seria necessário para vários assemblies.

Deploy

Para realizar o deploy de um Web Application Project, você pode copiar o assembly que é criado ao compilar o projeto para um servidor IIS. Em contraste, para realizar o deploy de um Web Site Project, você pode normalmente copiar os arquivos de origem do projeto para um servidor IIS. (Qualquer uma destas tarefas pode ser feita manualmente ou através de ferramentas de deploy).

Vantagens da estratégia de deploy de Web Application Projects incluem o seguinte:

    • Evitar a exposição de código-fonte no servidor IIS. Em alguns cenários, tais como ambientes de hospedagem compartilhada, você pode estar preocupado com o acesso não autorizado ao código fonte no servidor IIS. (Para um Web Site Project, você pode evitar este risco pré-compilando em um computador de desenvolvimento e realizando o deploy dos assemblies gerados em vez do código fonte. Entretanto, nesse caso, você perde alguns dos benefícios de facilidade de atualizações do site).
    • O deploy muitas vezes envolve outras tarefas além de copiar assemblies ou código para um servidor. Por exemplo, os scripts de banco de dados podem precisar serem executados em produção e connection strings no arquivo Web.config podem precisar serem alteradas para um servidor de produção. O Visual Studio fornece ferramentas que com um clique publicam que trabalham com Web Application Projects para automatizar muitas destas tarefas. Essas ferramentas não estão disponíveis para Web Site Projects.

Vantagens da estratégia de deploy para Web Site Projects incluem o seguinte:

    • Se você fizer uma pequena mudança em um site, você não tem que realizar o deploy de todo o site. Em vez disso, pode copiar apenas o arquivo alterado para o servidor IIS de produção. Você também pode editar arquivos diretamente no servidor de produção. (Como os arquivos de código fonte de um Web Application Projects são compilados em um único arquivo assembly, você deve realizar o deploy de todo o site, mesmo para pequenas mudanças, a menos que a única mudança é para um arquivo aspx ou ascx).

Fonte

Procurando Certificação ASP.Net? MCSD Web Applications

A Microsoft reconhece as habilidades de um profissional em diversas áreas e tecnologias através de certificações, elas são importantes para comprovar ao mercado o conhecimento e domínio de determinada tecnologia.

MCSD Web Applications

Me motivei a escrever este post, pois verifiquei que um dos maiores termos de pesquisa em meu site é sobre certificação.

Certificações são diferenciais no currículo de um profissional e podem muitas vezes ser o critério decisivo para uma contratação, apesar de certas descrenças sobre o conhecimento de um profissional certificado eu sempre defendi o mesmo pensamento:

“Entre ter uma certificação ou não, eu prefiro ter”

Muitas vezes para quem não conhece o programa de certificações da Microsoft pode ser complicado encontrar a certificação ideal, pois muitas delas não são mais atuais e irão ser descontinuadas, por isso para quem deseja certificar-se como desenvolvedor na plataforma ASP.Net eu recomendo a MCSD – Web Applications.

MCSD significa Microsoft Certified Solutions Developer.

A certificação MCSD – Web Applications é conquistada após passar em três exames:

Título do Exame Treinamento Exame
Programming in HTML5 with JavaScript and CSS3 20480B 70-480
Developing ASP.NET MVC 4 Web Applications 20486B 70-486
Developing Windows Azure and Web Services 20487B 70-487

Atenção, somente após ser aprovado nos três exames que é concedida a certificação MCSD Web Applications, estes exames separadamente não conferem esta certificação.

Além do curso oficial existem vários conteúdos preparatórios para estes exames, basta buscar na internet pelo número do exame que será fácil identificar o melhor para você.

A certificação MSCD é exclusivamente voltada desenvolvedores e possui quatro especializações, a especialização Web Applications é apenas uma delas, confira as demais especializações no site oficial da Microsoft:

Conheça também todas as certificações voltadas ao Visual Studio:

Espero que tenha sido útil, eu recomendo muito a certificação MCSD, pois considero um bom diferencial e costuma ser um bom critério decisivo de seleção.

Feedbacks ou dúvidas são sempre muito bem vindos e respondidos, utilize os comentários abaixo para continuarmos trocando informações.

ASP.Net MVC – Action Filters – Entendendo e Customizando

O ASP.Net MVC provê Action Filters que executam lógicas de filtragem antes ou depois que um Action Method é chamado. Action Filters são atributos personalizados que fornecem através de meios declarativos a possibilidade de adicionar um filtro que será executado para adicionar um comportamento aos métodos da Controller.

Action Filters fornecem uma técnica simples e poderosa de modificar ou melhorar o pipeline do ASP.Net MVC através da “injeção” de comportamento em determinados momentos ajudando a resolver diversas situações em algumas ou todas as partes da aplicação.

Os Action Filters são um dos tipos de filtros que o ASP.Net MVC 4 possui, estes filtros estão disponíveis para uso sem necessidade de customização, são eles:

  • Authorization Filter – Segurança e controle de usuários autenticados
  • Action Filter – Injeção de comportamento na execução de um ActionMethod
  • Result Filter – Injeção de comportamento na execução de um ActionResult
  • Exception Filter – Captura e tratamento na ocorrência de Exceptions

Um exemplo muito clássico do uso de Actions Filters é na Autorização de usuários logados:

[Authorize]
public class AccountController : Controller
{
    [AllowAnonymous]
    public ActionResult Login(string returnUrl)
    {
        ViewBag.ReturnUrl = returnUrl;
        return View();
    }
}

O uso dos Action Filters é feito decorando a Controller ou Action Method, no exemplo acima está sendo requerida a autorização de usuário para todos os métodos da Controller, caso isso seja necessário apenas para um método o Action Filter [Authorize] pode decorar apenas o método em questão, um exemplo disto é o próprio método de Login, pois nele é aplicado o filtro [AllowAnonymous] abrindo uma exceção para a regra geral aplicada na Controller.

O uso de Action Filters é muito comum, porém muitas vezes necessitamos de um comportamento diferenciado e nesses casos é possível criar o seu próprio Action Filter para definir um comportamento específico durante a chamada dos Actions Methods da aplicação.

Criando um Action Filter Customizado

O exemplo a ser abordado é muito simples, uma aplicação deve possuir um comportamento de exibir propagandas (conhecido como Advertising ou ADS) nas Views. Uma forma de atender este requisito é criando um Action Filter que fará este trabalho.

Roteiro

  1. Criar uma aplicação ASP.Net MVC 4 no Visual Studio chamada MvcFilterExample;
  2. Adicionar uma nova classe chamada ExibirAdsActionFilter na pasta Filters;
  3. Registrar o Action Filter de forma global ou utilizá-lo diretamente na Controller;
  4. Testar e validar o funcionamento do novo Action Filter.

A classe ExibirAdsActionFilter possui a seguinte estrutura

using System.Web.Mvc;

namespace MvcFilterExample.Filters
{
    public class ExibirAdsActionFilter : ActionFilterAttribute, IActionFilter
    {
        void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
        {
            filterContext.Controller.ViewBag.ConteudoAd = GerarConteudoAD();
        }

        void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext)
        {
            AtualizarExibicaoAD();
        }

        private string GerarConteudoAD()
        {
            return "<hr/><h2>Propaganda Aqui!<h2 /><hr/>";
        }

        private void AtualizarExibicaoAD()
        {
            // Neste método pode ser executada uma atualização
            // do contador de exibições de determinada propaganda.
        }
    }
}

Para construir o Action Filter proposto é necessário herdar a classe ActionFilterAttribute e implementar a interface IActionFilter.

A classe ActionFilterAttribute é a base para todos attribute filters, esta classe provê os seguintes métodos:

  • OnActionExecuting (ActionExecutedContext filterContext): Chamado um pouco antes do Action Method.
  • OnActionExecuted (ActionExecutingContext filterContext): Chamado após o Action Method e antes do Action Result ser executado (antes de renderizar a View).
  • OnResultExecuting (ResultExecutingContext filterContext): Chamado um pouco antes do Action Result (antes de renderizar a View).
  • OnResultExecuted (ResultExecutedContext filterContext): Chamado após o Action Result ser executado (após a View ter sido renderizada).

Pelo fato de estar sendo utilizada a interface IActionFilter apenas os métodos OnActionExecuting e OnActionExecuted necessitam ser implementados.
(Os últimos dois métodos atendem a filtros do tipo Result Filters e são implementados pela interface IResultFilter).

O exemplo é bem simples, o método OnActionExecuting gera o conteúdo de uma propaganda e armazena em uma ViewBag e o método OnActionExecuted contabiliza o número de visualizações.

Utilizando e Registrando Action Filters

Exitem 3 maneiras de utilizar este um novo Action Filter

  • Manualmente em uma Controller (todos os Actions Methods farão uso do filtro)
  • Manualmente nos Action Methods que farão uso do filtro
  • Registrando globalmente o filtro na aplicação (a aplicação inteira irá usar o filtro)

Para utilizar manualmente o Action Filter basta adicionar a referência do namespace da classe do filtro e decorar a Contoller ou Action Method com [ExibirAdsActionFilter]

using System.Web.Mvc;

// Referência das classes de filtro
using MvcFilterExample.Filters;

namespace MvcFilterExample.Controllers
{
    // Usando o filtro para toda Controller
    [ExibirAdsActionFilter]
    public class ClienteController : Controller
    {

        // Usando o filtro para cada Action Method
        [ExibirAdsActionFilter]
        public ActionResult Index()
        {
            return View();
        }
    }
}

OBS – Uma vez que a Controller foi decorada com o uso do filtro, todos os Action Methods assumem esse comportamento, não é necessário decorá-los.

Para registrar globalmente o Action Filter é necessário modificar a classe FilterConfig dentro da pasta App_Start

using System.Web.Mvc;

// Referência das classes de filtro
using MvcFilterExample.Filters;

namespace MvcFilterExample
{
    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());

            // Novo filtro adicionado
            filters.Add(new ExibirAdsActionFilter());
        }
    }
}

OBS – Ao registrar o Action Filter globalmente não é mais necessário manter a referencia MvcFilterExample.Filters e a decoração [ExibirAdsActionFilter] na Controller ou Action Methods, pois o registro aplicará o uso do filtro para toda a aplicação.

Para validar o funcionamento do filtro basta chamar o ViewBag ConteudoAd em uma View

<table>
    <tr>
        <td>
            @Html.Raw(@ViewBag.ConteudoAd)
        </td>
    </tr>
</table>

Atente-se ao modo de utilização do filtro, se foi registrado globalmente ou se está sendo utilizada em uma Controller específica, caso a ViewBag seja chamada através de uma Controller que não utiliza o Filtro ela retornará vazia. Abaixo o resultado da chamada da ViewBag criada dinamicamente pelo Action Filter customizado para propagandas.

ASP.NET MVC Action Filter

O Action Filter está implementado e em funcionamento.

Resumo

O uso de Action Filters customizados é muito comum e atendem a diversas necessidades rotineiras como:

  • Validação de regras de acesso de usuários
  • Log de atividades dos usuários
  • Captura de IP ou outras informações do cliente
  • Exibição de propagandas
  • Tratamento e notificações de exceptions
Referências

Espero que seja útil!
Feedbacks ou dúvidas são sempre muito bem vindos e respondidos, utilize os comentários abaixo para continuarmos trocando informações.

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.