How to Create, Read, Update & Delete users in ASP.NET Core Identity

How to Create, Read, Update & Delete users in ASP.NET Core Identity

In this tutorial I will perform CRUD Operations for Creating, Reading, Updating and Deleting Users in ASP.NET Core Identity. Before continuing you must Setup and Configure ASP.NET Core Identity in your project.

Create Users in Identity

To create Users in ASP.NET Core Identity you will need to create a Model Class. So create a class called User.cs inside the Models folders.

Add 3 public properties to it, which are Name, Email & Password, of type string. Also add [Required] Model validations attributes to them:

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; }
    }
}
UserManager<T> class

Users are managed through the UserManager<T> class, where T is the class chosen to represent users in the database.

The below table describes the most useful UserManager<T> class members.

Name Description
Users This property returns a sequence containing the users stored in the Identity database.
FindByIdAsync(id) This method queries the database for the user object with the specified ID.
CreateAsync(user, password) This method stores a new user in the database using the specified password.
UpdateAsync(user) This method modifies an existing user in the Identity database.
DeleteAsync(user) This method removes the specified user from the Identity database.
AddToRoleAsync(user, name) Adds a user to a role
RemoveFromRoleAsync(user, name) Removes a user from a role
GetRolesAsync(user) Gives the names of the roles in which the user is a member
IsInRoleAsync(user, name) Returns true is the user is a member of a specified role, else returns false

When I created the Entity Framework Core context class, I specified AppUser as the class to represent users in the database.

The below table describes the most useful AppUser class properties.

Name Description
Id It contains the Unique Id of the user.
UserName It contains the user’s username.
Email It contains the email for the user.

Next, create Controllers folder on the root of your project, and there create a new Controller called AdminController. Inside the Admin Controller I will perform all the CRUD Operations.

The code for the Admin Controller is given below:

using Microsoft.AspNetCore.Mvc;
using Identity.Models;
using Microsoft.AspNetCore.Identity;

namespace Identity.Controllers
{
    public class AdminController : Controller
    {
        private UserManager<AppUser> userManager;

        public AdminController(UserManager<AppUser> usrMgr)
        {
            userManager = usrMgr;
        }

        public IActionResult Index()
        {
            return View();
        }
    }
}

In the Controller I get the instance of UserManager through Dependency Injection. Then I set the value of the variable called userManager to the UserManager<AppUser> object which I get in the constructor through DI.

Next, I need to add a Create Action method that will actually create a new user in the Identity database. So add this action to your Admin controller as highlighted.

using Microsoft.AspNetCore.Mvc;
using Identity.Models;
using Microsoft.AspNetCore.Identity;
using System.Threading.Tasks;

namespace Identity.Controllers
{
    public class AdminController : Controller
    {
        private UserManager<AppUser> userManager;

        public AdminController(UserManager<AppUser> usrMgr)
        {
            userManager = usrMgr;
        }

        public IActionResult Index()
        {
            return View();
        }

        public ViewResult Create() => View();

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

                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);
        }
    }
}

The HTTP POST Create Action method is the one which creates the new user. It takes an argument of the User class and checks if the Model State is valid or not.

I also have written a tutorial on previous version of Entity Framework, and in that tutorial I did CRUD Operations in ASP.NET WebForms. You can read this tutorial at – CRUD Operations in Entity Framework and ASP.NET

If the Model State is valid then it creates a new instance of AppUser class, and gives it the Username and Emails as provided in the User class object. The respective code for this is:

AppUser appUser = new AppUser
{
    UserName = user.Name,
    Email = user.Email
};

After this, I create the user from the CreateAsync method of the UserManager class. As you remember I get this class object through Dependency Injection. The CreateAsync method takes 2 parameters which are – AppUser class object and the password. Once the User is created it returns IdentityResult class type which represents the result of the operation. The code for this which I am talking about is:

IdentityResult result = await userManager.CreateAsync(appUser, user.Password);

The IdentityResult Class has the following properties:

  • Succeeded – this property returns true if the create user operation completes successfully.
  • Errors – this property returns an object of type IEnumerable that contains the errors occurred while performing the Identity operation. The IdentityError has a description property which gives the description of each of the error that happened.

I used the Succeeded property of the IdentityResult class to find out if the create user operation completed successfully or not.

Do you want to understand everything about how Controllers work in ASP.NET Core then check out my tutorial called Controllers in ASP.NET Core which covers each part of it in full details & examples.

If it completed successfully then I am redirecting to the Index View else I am adding all the error descriptions to the Model State. The code that does this is:

if (result.Succeeded)
    return RedirectToAction("Index");
else
{
    foreach (IdentityError error in result.Errors)
        ModelState.AddModelError("", error.Description);
}

On the last line of I am returning the user to the Create Viewreturn View(user). Here the errors will be shown to him so that he can correct them and try creating the user once again.

Now it’s time to add the Create View file inside the Views ➤ Admin folder with the following code:

@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>
    <button type="submit" class="btn btn-primary">Create</button>
</form>

The View has a simple form which allows to create a user by entering his Name, Email and Password. These values are received in the Admin Controller’s Create Action method and then the user’s account is created in Identity.

You can now create a new user by running your project and go to the URL – https://localhost:44395/Admin/Create.

Fill Name, Email and Password (as shown in the below image), and click the Create button.

create user identity

Once the User is created you will be redirected to the Index View. The Index View will show every User accounts stored in the Identity database. I will create this feature next.

You cannot create a same user again. If you again go to the Create user page and fill details of a User who already exists then Identity will send you an error message saying – User name ‘xxx’ is already taken.

Read all Users in Identity

All the Users accounts of Identity can be fetched from the Identity database by the use of Users property of the UserManager class. The Users property will return an IEnumerable object.

So change the Index Action method’s code of the Admin Controller to as shown in the below code:

using Microsoft.AspNetCore.Mvc;
using Identity.Models;
using Microsoft.AspNetCore.Identity;
using System.Threading.Tasks;

namespace Identity.Controllers
{
    public class AdminController : Controller
    {
        private UserManager<AppUser> userManager;

        public AdminController(UserManager<AppUser> usrMgr)
        {
            userManager = usrMgr;
        }

        public IActionResult Index()
        {
            return View(userManager.Users);
        }

        // removed for brevity
    }
}

Now, create an Index View inside the Views ➤ Admin folder. In this View all the details of the Identity Users will be shown. It’s code is given below.

@model IEnumerable<AppUser>
 
<h1 class="bg-info text-white">All Users</h1>
<a asp-action="Create" class="btn btn-secondary">Create a User</a>
 
<table class="table table-sm table-bordered">
    <tr><th>ID</th><th>Name</th><th>Email</th></tr>
    @foreach (AppUser user in Model)
    {
    <tr>
        <td>@user.Id</td>
        <td>@user.UserName</td>
        <td>@user.Email</td>
    </tr>
    }
</table>

The View receives a Model of type IEnumerable<AppUser>. I looping over all the users using for each loop and showing their details inside a table.

You can now test this functionality by going to the URL – https://localhost:44395/Admin, which will invoke the Index Action method.

The Image below shows all the User records that are currently there in the Identity Database:

all users identity

Update Users in Identity

Now I will perform the Update of the Records of Identity Users. I will need to update the Index View to add a new column called Update in the HTML table. In this column I will create an anchor tag that will link to the Update Action method.

The updated code of the Index View is highlighted and shown below:

@model IEnumerable<AppUser>

<h1 class="bg-info text-white">All Users</h1>
<a asp-action="Create" class="btn btn-secondary">Create a User</a>

<table class="table table-sm table-bordered">
    <tr><th>ID</th><th>Name</th><th>Email</th><th>Update</th></tr>
    @foreach (AppUser user in Model)
    {
        <tr>
            <td>@user.Id</td>
            <td>@user.UserName</td>
            <td>@user.Email</td>
            <td>
                <a class="btn btn-sm btn-primary" asp-action="Update" asp-route-id="@user.Id">
                    Update
                </a>
            </td>
        </tr>
    }
</table>

Before creating the Update Action method in the Admin controller, I will need to add a dependency of IPasswordHasher in it’s constructor. It is used to get the hashed value of the user password. This is because Identity stores the passwords in Hashed value instead of plain text. This gives added security.

So update the Admin Controller as shown below:

using Microsoft.AspNetCore.Mvc;
using Identity.Models;
using Microsoft.AspNetCore.Identity;
using System.Threading.Tasks;

namespace Identity.Controllers
{
    public class AdminController : Controller
    {
        private UserManager<AppUser> userManager;
        private IPasswordHasher<AppUser> passwordHasher;

        public AdminController(UserManager<AppUser> usrMgr, IPasswordHasher<AppUser> passwordHash)
        {
            userManager = usrMgr;
            passwordHasher = passwordHash;
        }

        // removed for brevity
    }
}

Next, add the Update action to the Admin controller. The code is highlighted and given below:

using Microsoft.AspNetCore.Mvc;
using Identity.Models;
using Microsoft.AspNetCore.Identity;
using System.Threading.Tasks;

namespace Identity.Controllers
{
    public class AdminController : Controller
    {
        private UserManager<AppUser> userManager;
        private IPasswordHasher<AppUser> passwordHasher;

        public AdminController(UserManager<AppUser> usrMgr, IPasswordHasher<AppUser> passwordHash)
        {
            userManager = usrMgr;
            passwordHasher = passwordHash;
        }

        // removed for brevity

        public async Task<IActionResult> Update(string id)
        {
            AppUser user = await userManager.FindByIdAsync(id);
            if (user != null)
                return View(user);
            else
                return RedirectToAction("Index");
        }

        [HttpPost]
        public async Task<IActionResult> Update(string id, string email, string password)
        {
            AppUser user = await userManager.FindByIdAsync(id);
            if (user != null)
            {
                if (!string.IsNullOrEmpty(email))
                    user.Email = email;
                else
                    ModelState.AddModelError("", "Email cannot be empty");

                if (!string.IsNullOrEmpty(password))
                    user.PasswordHash = passwordHasher.HashPassword(user, password);
                else
                    ModelState.AddModelError("", "Password cannot be empty");

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

        private void Errors(IdentityResult result)
        {
            foreach (IdentityError error in result.Errors)
                ModelState.AddModelError("", error.Description);
        }
    }
}
Explanation

The HTTP GET version of the Update Action takes a string value called id. It will contains the User Id value.

The User’s record is fetched from the Identity database using the FindByIdAsync() method of the UserManager class. The FindByIdAsync() method is provided with the Id of the User in string format.

The associated code is:

AppUser user = await userManager.FindByIdAsync(id);

Once the User’s information is fetched, it is then send to the Update View as model.

The HTTP POST version of the Update Action is where the updation of the User’s record is done. This action is invoked when the user click the submit button on the form given on the Update View.

First I fetch the User’s information in an AppUser object by using the FindByIdAsync() method:

AppUser user = await userManager.FindByIdAsync(id);

Then, if the AppUser object is not null, I proceed by checking if the new email and password values are not empty. If they contain some value then I update the Email and PasswordHash property values of the AppUser object to the new ones.

See the below code which does this work:

if (!string.IsNullOrEmpty(email))
    user.Email = email;
else
    ModelState.AddModelError("", "Email cannot be empty");
 
if (!string.IsNullOrEmpty(password))
    user.PasswordHash = passwordHasher.HashPassword(user, password);
else
    ModelState.AddModelError("", "Password cannot be empty");

Note that I use the HashPassword() method to get the Hashed representation of the supplied password for the specified user.

user.PasswordHash = passwordHasher.HashPassword(user, password);

Finally, I update them using the UpdateAsync method. This method takes the AppUser object. The associated code is given below:

if (!string.IsNullOrEmpty(email) && !string.IsNullOrEmpty(password))
{
    IdentityResult result = await userManager.UpdateAsync(user);
    if (result.Succeeded)
        return RedirectToAction("Index");
    else
        Errors(result);
}

In case if the UpdateAsync() method does not completes successfully then the Errors method is called to add the IdentityResult errors to the Model State. This code is:

void Errors(IdentityResult result)
{
    foreach (IdentityError error in result.Errors)
        ModelState.AddModelError("", error.Description);
}

Now, create the Update View inside the Views ➤ Admin folder with the following code:

@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>
    <button type="submit" class="btn btn-primary">Save</button>
</form>

You can now test the update feature by initiating the Index action of Admin Controller having the URL – https://localhost:44395/Admin. There click the Update button which will take you to the update page.

Related tutorial: Views in ASP.NET Core

Add new Email and password and click the save button. This will update the User’s record stored in the Identity database.

The below images illustrates the Update feature:

update user identity

Delete Users in Identity

The final CRUD operation is the Delete users from Identity database. It is done by the Delete Action method of the Admin Controller. The code of the Delete Action method is given below.

using Microsoft.AspNetCore.Mvc;
using Identity.Models;
using Microsoft.AspNetCore.Identity;
using System.Threading.Tasks;

namespace Identity.Controllers
{
    public class AdminController : Controller
    {
        private UserManager<AppUser> userManager;
        private IPasswordHasher<AppUser> passwordHasher;

        public AdminController(UserManager<AppUser> usrMgr, IPasswordHasher<AppUser> passwordHash)
        {
            userManager = usrMgr;
            passwordHasher = passwordHash;
        }

        // removed for brevity

        [HttpPost]
        public async Task<IActionResult> Delete(string id)
        {
            AppUser user = await userManager.FindByIdAsync(id);
            if (user != null)
            {
                IdentityResult result = await userManager.DeleteAsync(user);
                if (result.Succeeded)
                    return RedirectToAction("Index");
                else
                    Errors(result);
            }
            else
                ModelState.AddModelError("", "User Not Found");
            return View("Index", userManager.Users);
        }
    }
}

This ASP.NET Core Action method receives the User Id and it fetches the user details using the FindByIdAsync() method.

I get the User details in an AppUser object. Then I use the DeleteAsync method to delete the user from the Identity database. The below code does the delete work:

IdentityResult result = await userManager.DeleteAsync(user);

If the delete operation completes successfully then user is redirected to the Index Action method else the Errors() function is called to show the errors to the user.

The delete button needs to be added to the HTML table of the Index View. This is shown in the highlighted code given below.

@model IEnumerable<AppUser>

<h1 class="bg-info text-white">All Users</h1>
<a asp-action="Create" class="btn btn-secondary">Create a User</a>

<table class="table table-sm table-bordered">
    <tr><th>ID</th><th>Name</th><th>Email</th><th>Update</th><th>Delete</th></tr>
    @foreach (AppUser user in Model)
    {
        <tr>
            <td>@user.Id</td>
            <td>@user.UserName</td>
            <td>@user.Email</td>
            <td>
                <a class="btn btn-sm btn-primary" asp-action="Update" asp-route-id="@user.Id">
                    Update
                </a>
            </td>
            <td>
                <form asp-action="Delete" asp-route-id="@user.Id" method="post">
                    <button type="submit" class="btn btn-sm btn-danger">
                        Delete
                    </button>
                </form>
            </td>
        </tr>
    }
</table>

Run your application and go to the URL- https://localhost:44395/Admin. Here you will see the User records have a delete button. When you click the delete button then the corresponding user record will be deleted from the Identity database.

See the below image:

delete record identity

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

Download

Conclusion

This completes the procedure to manage user in Identity. You can now add, update, read and delete users from Identity database.

In the next tutorial on Identity I created Username, Email & Password Policy which will help you to create your own custom rules in Identity.

Share this article -

yogihosting

ABOUT THE AUTHOR

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