Monday 10 November 2014

Customize User's Profile in ASP.NET Identity System

In this post you will learn how to customize User’s Profile and add some more fields like FirstName, LastName, EmailID etc with ASP.NET Identity System. In my last post I listed some of the great new features introduced with Identity system.

We are going to learn following things:

The demo I’m going to use will be on MVC but with other frameworks like Web Forms it will be exactly same.

Introduction

ASP.NET Identity System is a new Membership system for building ‘One ASP.NET’ applications. It allow us to add login features to our application and makes it really easy like never before to customize data about the logged in user, this is what we are going to learn in this post.

With Simple Membership it was a tough task to add other information while registering new user. Also, it was not possible to do some of the important task like database migrations, seeding user profile information’s etc etc. But now with this brand new ASP.NET Identity System, things are easier.

You can learn more about all the new features here.

Simple Membership and ASP.NET Identity System

Here I would like to show the table structure of Simple Membership and the new one ASP.NET Identity. We can see, there is a table ‘_MigrationHistory’ this helps Entity Framework Code First in migrating the database. We can also see few new tables got added, this will be used to manage other social login methods, and we will explore it later.



Customizing User’s Profile to add new fields in same database table

What about adding user’s First Name, Last Name and Email ID, while creating new user account in the application? It was really difficult before to add these extra information while registering new user. Now, with ASP.NET Identity System, it is easy to add extra information about the user.

Let’s follow the steps from here.

Step 1: Getting Ready

With Visual Studio 2013, these bits are already included with templates but in case if we want to migrate our existing application then we can download the bits from NuGet. Also note, with Visual Studio 2013 RC or RTM, we need to update packages given below.

We need to install these two packages:-

Microsoft.Aspnet.Identity.Core
This package contains the core interfaces of ASP.NET Identity.

Microsoft.Aspnet.Identity.EntityFramework
This package contains the implementation of ASP.NET Identity System which works with Entity Framework Code First. This means that if we use this package then we can store information in a SQL Server database. Also we can easily plug other databases if we wanted.

I had a bad experience on this because I were using RTM version of Visual Studio 2013, here is the error I was getting:

Mapping and metadata information could not be found for EntityType 'ProfileManagementMVC.Models.ApplicationUser'.

Then I updated my IDE and problem got solved. Alternatively, while creating new project we can update NuGet packages before proceeding, and it will also work.

Step 2: Create Project

Open Visual Studio 2013 and create a new ASP.NET Web Application from File | New | Project | .NET Framework 4.5 | ASP.NET Web Application by selecting MVC as a project template.

Step 3: Looking at Register Page

Run the application and navigate to register page. Assume how about adding First Name, Last Name and Email ID fields on this page? This can be done very easily now.


Step 4: Enable Entity Framework Code First Database Migrations

ASP.NET Identity System uses Entity Framework Code First approach to generate database tables. We are going to change the default schema of the database by adding new properties in code first model class that needs database migration to generate database tables. Also, if we use database migration then older database records will stay as it is in the database tables. I have recorded following videos and uploaded on YouTube on Code First Database Migrations, just watch it.


For this, I am going to execute following two commands from ‘Package Manager Console’, the NuGet power tool.

Just execute the command “Enable-Migrations”, as given below.


Once we enabled the database migrations, we can go ahead and add new properties First Name, Last Name and Email ID.

Step 5: Add new properties

Let’s add new properties First Name, Last Name and Email ID in Models | IdentityModels.cs file, as given below.

public class ApplicationUser : IdentityUser
{
    public string FirstName { getset; }
    public string LastName { getset; }
    public string EmailID { getset; }
}

Step 6: Add New Migration

Once we added the properties, bring the Package Manager Console and execute following command.

Add-Migration "NameEmailID"

This command will generate a big blog database script file, now execute following command to run this script file against database.

Update-Database

Now, all the new properties will turn into table fields in the same database table. We could generate new table also, we will explore this in next blog post.



Step 7: Update RegisterViewModel

Once we updated the database table, we can go and update the AccountViewModel.cs RegisterViewModel, we can find it inside Model folder.

public class RegisterViewModel
{
    [Required]
    [Display(Name = "Frist Name")]
    public string FirstName { getset; }

    [Required]
    [Display(Name = "Last Name")]
    public string LastName { getset; }

    [Required]
    [Display(Name = "Email ID")]
    [EmailAddress]
    public string EmailID { getset; }

    [Required]
    [Display(Name = "User name")]
    public string UserName { getset; }

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

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

I highlighted newly added codes above.

Step 8: Update Register View Page

Once we have the ViewModel ready, we are good to update its view page “Register” which can be found in View | Account | Register.cshtml.

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

Step 9: Update Account Controller’s Register action (Post Version)

Now one thing left is updating Post Version of Register action. Here I am using ApplicationUser() to map the properties with appropriate model.

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = new ApplicationUser() { UserName = model.UserName, FirstName = model.FirstName, LastName = model.LastName, EmailID = model.EmailID };

        var result = await IdentityManager.Users.CreateLocalUserAsync(user, model.Password);
        if (result.Success)
        {
            await IdentityManager.Authentication.SignInAsync(AuthenticationManager, user.Id, isPersistent: false);
            return RedirectToAction("Index""Home");
        }
        else
        {
            AddErrors(result);
        }
    }

    // If we got this far, something failed, redisplay form
    return View(model);
}

I highlighted newly added codes above.

Step 10: Run Application

Let’s go and run the application and try to create new user account. Look at the image given below, I success to login and I can see all the data (FirstName, LastName, EmailID) up in the database.





Step 11: Accessing User Profile Data

If user is logged in, we can access user’s profile information that we just added following way in the controller.


Or if we want to access these information directly on the view page, here is another way.

@using Microsoft.AspNet.Identity;
@using Microsoft.AspNet.Identity.EntityFramework;
@using ProfileManagement.Models;

<div>
    @{
        if (Request.IsAuthenticated)
        {
            var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(newApplicationDbContext()));
            var currentUser = manager.FindById(User.Identity.GetUserId());
            <p>@currentUser.EmailID</p>
            <p>@currentUser.FirstName @currentUser.LastName</p>
        }
    }

</div>

Please note I have used all the required namespaces.


No comments:

Post a Comment

Angular Tutorial (Update to Angular 7)

As Angular 7 has just been released a few days ago. This tutorial is updated to show you how to create an Angular 7 project and the new fe...