Customizing profile information in ASP.NET Identity in VS 2013 templates

Customizing profile information in ASP.NET Identity in VS 2013 templates

Rate This
  • Comments 46

ASP.NET Identity is the new membership system for ASP.NET applications. To learn more about ASP.NET Identity please visit http://blogs.msdn.com/b/webdev/archive/2013/06/27/introducing-asp-net-identity-membership-system-for-asp-net-applications.aspx

One of the mainline features about ASP.NET Identity is to make it easy to add profile information about the user. In the existing ASP.NET Membership system, User and Profile were separate tables and Profile information about the user was retrieved by using the Profile provider. This made it difficult to customize the Profile information and associate it with the User and application data.  ASP.NET Identity makes it really easy to add profile data for your User.

[Update] Adding information on how to store profile information in a different table

[Update] Rick Anderson has a tutorial on asp.net site which also shows how you can add Social Logins to the template as well. Please refer to the tutorial for an entire walkthrough

http://www.asp.net/mvc/tutorials/mvc-5/create-an-aspnet-mvc-5-app-with-facebook-and-google-oauth2-and-openid-sign-on


This post shows how you can customize profile information about the user when you start with the project templates in Visual Studio 2013. Following are the steps to follow to add profile information about the user.

    • In Visual Studio 2013, create a new ASP.NET MVC application.
      • You can create a Web Forms application and follow the same steps to add profile information.
    • Run the application and register a user
      • You would notice that at the registration screen, the application only asks for a UserName and password. Let’s say that you wanted to add one more field called BirthDate that the users should specify when registering a user.
    • Enable Entity Framework Migrations
      • Migrations are recommended to use when you are modifying the schema of the database or you are changing the Code First Model. ASP.NET Identity uses Entity Framework Code First as an underlying framework. For more information on EF migrations please visit http://msdn.microsoft.com/en-us/data/jj591621
      • Open Package Manager Console by doing Tools – Library Package Manager – Package Manager Console
      • image
      • Type in “Enable-Migrations” and press enter
    • Add properties for the Profile information that you want to store.
      • In our example we will add BirthDate as a property
      • Goto Models\IdentityModels.cs and add the following property to ApplicationUser
public class ApplicationUser : IdentityUser { public DateTime BirthDate { get; set; } }
      • Add using System; at the top of the class.
    • Add-Migrations to modify the database
      • Since we have added a new property to the User, we need to update the database to reflect this change. This is where EF migrations is really useful. You can use migrations to update the database schema by doing the following
      • Goto Package Manager console and do the following
      • Add-Migration "Birthdate"
        • This will add a migration file to your project
      • Update-Database
        • This command will run all the migration files and update the database schema to add a BirthDate column
    • Modify the application to add a BirthDate field
      • The steps here are specific to how you would add a view to MVC, but you can do similar view specific rendering in Web Forms as well
      • Add BirthDate to RegisterViewModel in Models\AccountViewModels.cs
   1:  public class RegisterViewModel { 
   2:  [Required] [Display(Name = "User name")] 
   3:  public string UserName { get; set; }  
   4:   
   5:  [Required] 
   6:  [StringLength(100, ErrorMessage = "The {0} must be 
       at least {2} characters long.", MinimumLength = 6)] 
   7:  [DataType(DataType.Password)] [Display(Name = "Password")] 
   8:  public string Password { get; set; }  [DataType(DataType.Password)]
        [Display(Name = "Confirm password")] 
   9:   
  10:  [Compare("Password", ErrorMessage = 
       "The password and confirmation password do not match.")] 

11: public string ConfirmPassword { get; set; }

public DateTime BirthDate { get; set; } }

        • Add using System; at the top of the class.
      • Update the Register view in Views\Account to add a field to enter BirthDate.
   1:  <div class="form-group">
   2:   @Html.LabelFor(m => m.BirthDate, new { @class = "col-md-2 control-label" }) 
   3:  <div class="col-md-10"> @Html.TextBoxFor(m => m.BirthDate, new { @class = "form-control" }) 
   4:  </div>
   5:   </div>
      • Update the Register Action in AccountController to store the BirthDate as well for the User
var user = new ApplicationUser() { UserName = model.UserName, BirthDate=model.BirthDate };
  • Run the application and register a user again. You will see the BirthDate field as shown below

 

    • image
  • Display the profile infromation on the page
    • When the User Logs in, you can display the profile information by doing the following
    • Get the current logged in UserId, so you can look the user up in ASP.NET Identity system
      • var currentUserId = User.Identity.GetUserId();
    • Instantiate the UserManager in ASP.Identity system so you can look up the user in the system
      • var manager = new UserManager<MyUser>(new UserStore<MyUser>(new MyDbContext()));
    • Get the User object
      • var currentUser = manager.FindById(User.Identity.GetUserId());
    • Get the profile information about the user
      • currentUser.BirthDate

Adding Profile information in a different table.

While this post shows you a way where you can easily add profile properties to the User Table itself. Since ASP.NET Identity uses Entity Framework, you can customize profile information as you would like to. For eg. let’s say that you want to add profile information in a different table rather than the same table then you can do the following to your model

Add a new class to store Profile information

Code Snippet
  1. public class MyUser : IdentityUser
  2.     {
  3.         public virtual MyUserInfo MyUserInfo { get; set; }
  4.     }
  5.  
  6.     public class MyUserInfo{
  7.         public int Id { get; set; }
  8.         public string FirstName { get; set; }
  9.         public string LastName { get; set; }
  10.     }
  11.     public class MyDbContext : IdentityDbContext<MyUser>
  12.     {
  13.         public MyDbContext()
  14.             : base("DefaultConnection")
  15.         {
  16.         }
  17.         public System.Data.Entity.DbSet<MyUserInfo> MyUserInfo { get; set; }
  18.      }

In this case when you run the application you will get the FirstName and LastName in a different table called MyUserInfo

image

Getting Profile information

  • When the User Logs in, you can display the profile information by doing the following
  • Get the current logged in UserId, so you can look the user up in ASP.NET Identity system
    • var currentUserId = User.Identity.GetUserId();
  • Instantiate the UserManager in ASP.Identity system so you can look up the user in the system
    • var manager = new UserManager<MyUser>(new UserStore<MyUser>(new MyDbContext()));
  • Get the User object
    • var currentUser = manager.FindById(User.Identity.GetUserId());
  • Get the profile information about the user
    • currentUser.MyUserInfo.FirstName

Conclusion

This post shows how you can customize the profile information about the user. If you have any questions, please leave comments or reach me at twitter (@rustd)

Leave a Comment
  • Please add 6 and 5 and type the answer here:
  • Post
  • How do I allow the user to update their profile? Like if I added a Bio field, and wanted them to be able to update it?

  • Hi Pranav,

    I wanted to change the data type of the column "ID" in "AspNetUsers" from String(GUID) to Int. I checked msdn.microsoft.com/.../jj591617, but could not find any breakthrough. Though there was a topic explaining about "Configuring the Data Type of a Database Column".

    modelBuilder.Entity<Department>()  

       .Property(p => p.Name)  

       .HasColumnType("varchar");

    or

    modelBuilder.Entity<AspNetUsers>()  

       .Property(p => p.ID)  

       .HasColumnType("int");

    But this did not work?  Can you help me out?

  • Thank you for this tutorial!

    I was able to follow the first half without any issue, however the second half "Adding Profile information in a different table" could use some more details for us newbies.

    Specifically, when we edit the code in AccountController.cs, it's easy to save the birthday info, but how do you save the First Name and Last Name?  I've tried 20+ variations of what seems like it might work.

    The closest I came was with Notso's sample code in the Comments below.  First I tried:

    var userInfo = new MyUserInfo() { FirstName = model.FirstName, LastName = model.LastName };

    var user = new ApplicationUser() { UserName = model.UserName, BirthDate = model.BirthDate, MyUserInfo = userInfo };

    but that threw a "System.Data.Entity.Validation.DbEntityValidationException: Validation failed for one or more entities" error (because it's looking for an Id for the MyUserInfo table.

    Then I tried:

    var userInfo = new MyUserInfo() { FirstName = model.FirstName, LastName = model.LastName, Id = "foo" };

    var user = new ApplicationUser() { UserName = model.UserName, BirthDate = model.BirthDate, MyUserInfo = userInfo };

    which worked, except I have Id hard-coded and I really want to get the 'actual' Id in that field, not "foo".

    I'm assuming AspNetUsers and MyUserInfoes are joined by Id, correct?

    Thank you,

    Laura

    PS.  One change I made in the example above was to make MyUserInfo.Id a string, because Id is a string in AspNetUsers.  Once again I am assuming that the two tables are joined on Id.

  • Of course, right after I post, I got it to work ...

    I'm not sure if this is the best way to do it, but this worked for me:

    var userInfo = new MyUserInfo() { FirstName = model.FirstName, LastName = model.LastName };

    var user = new ApplicationUser() { UserName = model.UserName, BirthDate = model.BirthDate, MyUserInfo = userInfo };

    user.MyUserInfo.Id = user.Id;

    var result = await UserManager.CreateAsync(user, model.Password);

    (In the /Account/Register section of AccountController.cs)

  • Hi Pranav,

    I run the ASP.NET Identity wizard, can I change the database by editing connectionstring in Web.config?

    It seems that coupling to the EntityFramework is very strong, will need to get my hands dirty.

    Thanks in advance.

  • How do you update profile data once it has been created?

  • Update profile data after it has been created:

    Dim currentUser As ApplicationUser = manager.FindById(User.Identity.GetUserId())

    currentUser.FirstName = FirstName.Text

    Dim result As IdentityResult = manager.Update(currentUser)

    This worked for me.

  • Is it possible to change the schema that the tables are stored in? I don't use dbo and prefer to use app or something else.

  • Hi,thanks a lot for you tutor,i would like to ask if it's possible to use it in pure asp.net web api application with individual account?Thanks

  • Hi Pranav, great explanation :)

    But I reached this page from website project. And in website project all of these not work.

    In Web Application project yes but in website no.

    How can I do?

    This exception is thrown:

    System.ArgumentException: The parameter is incorrect. (Exception from HRESULT: 0x80070057 (E_INVALIDARG))

    Server stack trace:

      at EnvDTE.Properties.Item(Object index)

      at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Object[]& outArgs)

      at System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg)

    Exception rethrown at [0]:

      at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)

      at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)

      at EnvDTE.Properties.Item(Object index)

      at System.Data.Entity.Migrations.Extensions.ProjectExtensions.GetPropertyValue[T](Project project, String propertyName)

      at System.Data.Entity.Migrations.MigrationsDomainCommand.GetFacade(String configurationTypeName, Boolean useContextWorkingDirectory)

      at System.Data.Entity.Migrations.UpdateDatabaseCommand.<>c__DisplayClass2.<.ctor>b__0()

      at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)

    The parameter is incorrect. (Exception from HRESULT: 0x80070057 (E_INVALIDARG))

  • thanx for this info.

    Used it on webforms and vb and works great.

    The only problem i have with it now is that i can't

    log in with facebook anymore because of the birthdayfield.

    this is the error i get:

    An exception of type 'System.Data.ConstraintException' occurred in mscorlib.dll but was not handled in user code

    Additional information: The 'Birthday' property on 'ApplicationUser' could not be set to a 'null' value. You must set this property to a non-null value of type 'System.DateTime'.

    can somebody help me with this?

    tx steve

  • Hi!

    I followed the steps that you have listed but I ran into an issue with edit and delete.

    Edit:  If I try to edit the user that has profile information stored in separate table by doing this

    currentUser.MyUserInfo = editUser.MyUserInfo   // Where edituser is the model passed from the edit view

    Above code create a new record in the MyUserinfo table. and both records are associated with the foreign key relationship. Similarly when we delete the user it only delete it from the AspNetUsers table and leave a record behind in the MyUserInfo table.... Please help... Thanks.

  • Thanks Pranav for the code.

    Although I'm new to all this, I followed your instructions and it worked well for me.

    However in my case the user will type a screen name to register. The screen name should be UNIQUE and should not exist in the database.  How can I check that the screen name doesn't exist in the database before I register the user? Any code would be appreciated because I'n still not familiar with this system. Thanks

    Gloria

  • I am trying to add two tables that are exactly like the role tables.  (Roles and UserRoles tables)  I have tried following what you said above, but it adds a field in the user table with that tableID.  I would like to set it up just like the UserRoles table where it stores the UserID and the RolesID.  How would I go by setting up these 2 tables simular to the roles tables?  Also how would you set up relationships between the tables?

  • Hello everybody, I want to get the properties by declared the Generics collection and without declare the one by one property in the web.config page then want to get these customize properties in the "ProductsCollection.cs" page.

Page 3 of 4 (46 items) 1234