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.