How to add Custom User Properties in Identity Membership System

How to add Custom User Properties in Identity Membership System

If you want to add more information to the Users in Identity System then you can do this by adding Custom User Properties to the User class (i.e. which inherit from the IdentityUser parent class).

In my previous tutorial on Create, Read, Update & Delete users in Identity Membership System I created the User class which does not have any custom property. Now in this tutorial I will teach you how to add new properties to the User class.

I have added 3 new Custom Properties to my AppUser class:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;

namespace Identity.Models
{
    public class AppUser : IdentityUser
    {
        public Country Country { get; set; }

        public int Age { get; set; }

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

    public enum Country
    {
        USA, UK, France, Germany, Russia
    }
}

The Country Properties is of an Enum type, the Age property is of type int, and lastly the Salary property is of type string. I have also made the Salary property as a required one.

Now with the properties in place I will need to update my Identity Database. For this I will have to run the Entity Framework Migration commands.

On your Package Manager Console window, go to the directory of the Startup.cs class, and run the following 2 commands:

  • 1. dotnet ef migrations add MigrationNew
  • 2. dotnet ef database update

When the commands complete, the table in the Identity Database, that stores user data will contain 3 new columns that represent the custom properties.

Updating Create and Update User methods

Now I will update the Create and Update User Action methods, of my ‘Admin’ Controller, to add the support for the Custom Properties that I have added.

First I added these 3 new properties to the User.cs class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;

namespace Identity.Models
{
    public class User
    {
        [Required]
        public string Name { get; set; }

        [Required]
        [RegularExpression("^[a-zA-Z0-9_\\.-][email protected]([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,6}$", ErrorMessage = "E-mail is not valid")]
        public string Email { get; set; }

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

        public Country Country { get; set; }

        public int Age { get; set; }

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

Next, I have to add 3 new controls for these properties in the ‘Create’ and ‘Update’ Views, of the ‘/Views/Admin’ folder. I will use the input control for the Age and Salary properties, and for the Salary property I will use the select control.

The updated code of these 2 Views are given below:

1. Create.cshtml

@model User

<h1 class="bg-info text-white">Create User</h1>
<a asp-action="Index" class="btn btn-secondary">Back</a>
<div asp-validation-summary="All" class="text-danger"></div>

<form method="post">
    <div class="form-group">
        <label asp-for="Name"></label>
        <input asp-for="Name" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="Email"></label>
        <input asp-for="Email" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="Password"></label>
        <input asp-for="Password" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="Age"></label>
        <input asp-for="Age" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="Country"></label>
        <select asp-for="Country" class="form-control" asp-items="@new SelectList(Enum.GetNames(typeof(Country)))">
            <option selected disabled value="Select">Select Country</option>
        </select>
    </div>
    <div class="form-group">
        <label asp-for="Salary"></label>
        <input asp-for="Salary" class="form-control" />
    </div>
    <button type="submit" class="btn btn-primary">Create</button>
</form>

2. Update.cshtml

@model AppUser

<h1 class="bg-info text-white">Update User</h1>
<a asp-action="Index" class="btn btn-secondary">Back</a>
<div asp-validation-summary="All" class="text-danger"></div>

<form asp-action="Update" method="post">
    <div class="form-group">
        <label asp-for="Id"></label>
        <input asp-for="Id" class="form-control" disabled />
    </div>
    <div class="form-group">
        <label asp-for="Email"></label>
        <input asp-for="Email" class="form-control" />
    </div>
    <div class="form-group">
        <label for="password">Password</label>
        <input name="password" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="Age"></label>
        <input asp-for="Age" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="Country"></label>
        <select asp-for="Country" class="form-control" asp-items="@new SelectList(Enum.GetNames(typeof(Country)))">
            <option selected disabled value="Select">Select Country</option>
        </select>
    </div>
    <div class="form-group">
        <label asp-for="Salary"></label>
        <input asp-for="Salary" class="form-control" />
    </div>
    <button type="submit" class="btn btn-primary">Save</button>
</form>

Finally, I will update the Create and Update action methods of the Admin controller.

The updated code for the ‘Create’ Action method is:

[HttpPost]
public async Task<IActionResult> Create(User user)
{
    if (ModelState.IsValid)
    {
        AppUser appUser = new AppUser
        {
            UserName = user.Name,
            Email = user.Email,
            Country = user.Country,
            Age = user.Age,
            Salary = user.Salary
        };

        IdentityResult result = await userManager.CreateAsync(appUser, user.Password);
        if (result.Succeeded)
            return RedirectToAction("Index");
        else
        {
            foreach (IdentityError error in result.Errors)
                ModelState.AddModelError("", error.Description);
        }
    }
    return View(user);
}

There is just one change where I am adding the new properties values of the AppUser class object:

Country = user.Country,
Age = user.Age,
Salary = user.Salary

The updated code for the ‘Update’ Action method is:

[HttpPost]
public async Task<IActionResult> Update(string id, string email, string password, int age, string country, string salary)
{
    AppUser user = await userManager.FindByIdAsync(id);
    if (user != null)
    {
        IdentityResult validEmail = null;
        if (!string.IsNullOrEmpty(email))
        {
            validEmail = await userValidator.ValidateAsync(userManager, user);
            if (validEmail.Succeeded)
                user.Email = email;
            else
                Errors(validEmail);
        }
        else
            ModelState.AddModelError("", "Email cannot be empty");

        IdentityResult validPass = null;
        if (!string.IsNullOrEmpty(password))
        {
            validPass = await passwordValidator.ValidateAsync(userManager, user, password);
            if (validPass.Succeeded)
                user.PasswordHash = passwordHasher.HashPassword(user, password);
            else
                Errors(validPass);
        }
        else
            ModelState.AddModelError("", "Password cannot be empty");

        user.Age = age;

        Country myCountry;
        Enum.TryParse(country, out myCountry);
        user.Country = myCountry;

        if (!string.IsNullOrEmpty(salary))
            user.Salary = salary;
        else
            ModelState.AddModelError("", "Salary cannot be empty");

        if (validEmail != null && validPass != null && validEmail.Succeeded && validPass.Succeeded && !string.IsNullOrEmpty(salary))
        {
            IdentityResult result = await userManager.UpdateAsync(user);
            if (result.Succeeded)
                return RedirectToAction("Index");
            else
                Errors(result);
        }
    }
    else
        ModelState.AddModelError("", "User Not Found");

    return View(user);
}

The changes which I have done to this action are:

1. Added the 3 new parameters

int age, string country, string salary

2. Setting the values of these 3 new properties of the AppUser class object.

user.Age = age;

Country myCountry;
Enum.TryParse(country, out myCountry);
user.Country = myCountry;

if (!string.IsNullOrEmpty(salary))
    user.Salary = salary;
else
    ModelState.AddModelError("", "Salary cannot be empty");

3. Checking if salary value is ‘not null or empty’, in the if condition.

if (validEmail != null && validPass != null && validEmail.Succeeded && validPass.Succeeded && !string.IsNullOrEmpty(salary))
{
...
}

Testing the Custom User Properties

To test these newly added Custom User Properties, run your project.

Go to the Create User URL – ‘/Admin/Create’, where you will see these 3 new properties, as shown by the below image. Create a new user with the following details:

1. Name – mary
2. Email – [email protected]
3. Password – [email protected]
4. Age – 20
5. Country – USA
6. Salary – 5000

custom user properties in add user view

Once the user is created, click to update its records. You will be taken to the Update View where you will see all the value of the Custom Property bound to the new controls. See the below image:

custom user properties in update view

You can download the full codes of this tutorial from the below link:

Download

Conclusion

This completes the tutorial on Custom User Properties in Identity. Now you can easily add new properties to the User Class based on your requirements.

Share this article -

yogihosting

ABOUT THE AUTHOR

This article has been written by the Technical Staff of YogiHosting. Check out other articles on "WordPress, SEO, jQuery, HTML" and more.