Back to: ASP.NET Core Identity Tutorials
How to Edit ASP.NET Core Identity User
In this article, I will discuss How to Edit ASP.NET Core Identity User. Please read our previous article discussing How to Retrieve and Display All Registered Users from the ASP.NET Core Identity Database.
Edit ASP.NET Core Identity User:
Editing a user in ASP.NET Core Identity involves creating a form that allows users to submit their updated information, handling this data in a controller action, validating the updated information, and then applying the changes to the database using Entity Framework Core. We need to follow the following steps:
- Retrieve the User: First, we need to retrieve the user we want to edit. This is usually done through the UserManager class. To do this, we need to use a method like FindByIdAsync or FindByEmailAsync, depending on the requirement, i.e., whether we want to fetch the User by ID and Email.
- Update User Properties: Once we have the user object, we need to modify its properties. For example, we can change the user’s email, name, or other property in the IdentityUser class or the custom class that extends the IdentityUser class.
- Validate the Changes: It’s important to validate the changes before saving them into the database. ASP.NET Core Identity has built-in validation, but we can also implement custom validation logic.
- Update the User: After making and validating the changes, we need to save these changes to the database. This is done using the UserManager class UpdateAsync method.
- Check the Result: The UpdateAsync method returns an IdentityResult object. We need to check this object to see if the update was successful and handle errors, if any.
Let us proceed and see how we can implement this in our project.
Edit Button on List Users View
We created the following ListUsers view in our previous article, where we provided a button for editing the user information.
When we click the Edit button against any user in the ListUsers view, we want to redirect the user to the URL: /Administration/EditUser/UserId. So, please modify the ListUsers.cshtml view to add the Edit link to be redirected to the EditUser action method of the Administration controller by taking the UserId as a parameter.
@model IEnumerable<ApplicationUser> @{ ViewBag.Title = "All Users"; } <h1>All Users</h1> @if (Model.Any()) { <a asp-action="Register" asp-controller="Account" class="btn btn-primary mb-3" style="width:auto"> Add New User </a> foreach (var user in Model) { <div class="card mb-3"> <div class="card-header"> User Id : @user.Id </div> <div class="card-body"> <h5 class="card-title">@user.UserName</h5> </div> <div class="card-footer"> <a asp-action="EditUser" asp-controller="Administration" asp-route-UserId="@user.Id" class="btn btn-primary">Edit</a> <a href="#" class="btn btn-danger">Delete</a> </div> </div> } } else { <div class="card"> <div class="card-header"> No Users Added Yet </div> </div> }
EditUserViewModel Class:
Create a class file named EditUserViewModel.cs and then copy and paste the following code. This class is going to hold the user data needed by the Edit User View:
using System.ComponentModel.DataAnnotations; namespace ASPNETCoreIdentityDemo.Models { public class EditUserViewModel { //To avoid NullReferenceExceptions at runtime, //initialise Claims and Roles with a new list in the constructor. public EditUserViewModel() { Claims = new List<string>(); Roles = new List<string>(); } [Required] public string Id { get; set; } [Required] [Display(Name = "User Name")] public string UserName { get; set; } [Required] [EmailAddress] public string Email { get; set; } [Display(Name = "First Name")] public string? FirstName { get; set; } [Display(Name = "Last Name")] public string? LastName { get; set; } public List<string> Claims { get; set; } public IList<string> Roles { get; set; } } }
EditUser HttpGet Action Method
We need two actions in our Administration Controller: one to display the form (GET request) and another to process the form data (POST request). So, add the following EditUser Get Action method to the Administration Controller. This method will fetch all the user details and pass them to the EditUser view.
[HttpGet] public async Task<IActionResult> EditUser(string UserId) { //First Fetch the User Details by UserId var user = await _userManager.FindByIdAsync(UserId); //Check if User Exists in the Database if (user == null) { ViewBag.ErrorMessage = $"User with Id = {UserId} cannot be found"; return View("NotFound"); } // GetClaimsAsync retunrs the list of user Claims var userClaims = await _userManager.GetClaimsAsync(user); // GetRolesAsync returns the list of user Roles var userRoles = await _userManager.GetRolesAsync(user); //Store all the information in the EditUserViewModel instance var model = new EditUserViewModel { Id = user.Id, Email = user.Email, UserName = user.UserName, FirstName = user.FirstName, LastName = user.LastName, Claims = userClaims.Select(c => c.Value).ToList(), Roles = userRoles }; //Pass the Model to the View return View(model); }
We use the following three ASP.NET Core Identity methods in this example.
FindByIdAsync Method:
- This method finds a user based on their unique identifier, typically a string representing the user’s ID in the database. The method returns a Task<TUser>, which, when awaited, gives you the user entity if found or null if no user is found with that ID. Example: var user = await _userManager.FindByIdAsync(UserId);
GetClaimsAsync Method:
- This method retrieves all claims associated with a specific user. Claims are a way of adding additional data about the user, such as their roles or permissions. The AspNetUserClaims table stores all the claims. Currently, we have not stored any claims. The method returns a Task<IList<Claim>>, which, when awaited, returns a list of claims (System.Security.Claims.Claim) associated with the user. Example: var userClaims = await _userManager.GetClaimsAsync(user);
GetRolesAsync Method:
- This method retrieves all the roles associated with a specific user. The method returns a Task<IList<string>>, which, when awaited, returns a list of role names (string) that the user belongs to. Example: var userRoles = await _userManager.GetRolesAsync(user);
Edit User View
The look and feel of the EditUser view is shown below. Here, we have three sections. The first section is for updating the user’s basic information. The second section shows the list of roles assigned to the user and a link to Manage the roles. The third section shows the list of claims assigned to the user and a link to manage the claims. Currently, we have not added any claims, so the claim section is empty.
So, create a view named EditUser.cshtml within the Views/Administration directory and copy and paste the following code. The model for this view is EditUserViewModel.
@model EditUserViewModel @{ ViewBag.Title = "Edit User"; } <h1>Edit User</h1> <form method="post" class="mt-3"> <input type="hidden" asp-for="Id" /> <div class="form-group row"> <label asp-for="Id" class="col-sm-2 col-form-label"></label> <div class="col-sm-10"> <input asp-for="Id" disabled class="form-control"> </div> </div> <div class="form-group row"> <label asp-for="Email" class="col-sm-2 col-form-label"></label> <div class="col-sm-10"> <input asp-for="Email" class="form-control"> <span asp-validation-for="Email" class="text-danger"></span> </div> </div> <div class="form-group row"> <label asp-for="UserName" class="col-sm-2 col-form-label"></label> <div class="col-sm-10"> <input asp-for="UserName" class="form-control"> <span asp-validation-for="UserName" class="text-danger"></span> </div> </div> <div class="form-group row"> <label asp-for="FirstName" class="col-sm-2 col-form-label"></label> <div class="col-sm-10"> <input asp-for="FirstName" class="form-control"> </div> </div> <div class="form-group row"> <label asp-for="LastName" class="col-sm-2 col-form-label"></label> <div class="col-sm-10"> <input asp-for="LastName" class="form-control"> </div> </div> <div asp-validation-summary="All" class="text-danger"></div> <div class="form-group row"> <div class="col-sm-10"> <button type="submit" class="btn btn-primary">Update</button> <a asp-action="ListUsers" class="btn btn-primary">Cancel</a> </div> </div> <div class="card"> <div class="card-header"> <h3>User Roles</h3> </div> <div class="card-body"> @if (Model.Roles.Any()) { foreach (var role in Model.Roles) { <h5 class="card-title">@role</h5> } } else { <h5 class="card-title">None at the moment</h5> } </div> <div class="card-footer"> <a href="#" style="width:auto" class="btn btn-primary"> Manage Roles </a> </div> </div> <div class="card mt-3"> <div class="card-header"> <h3>User Claims</h3> </div> <div class="card-body"> @if (Model.Claims.Any()) { foreach (var claim in Model.Claims) { <h5 class="card-title">@claim</h5> } } else { <h5 class="card-title">None at the moment</h5> } </div> <div class="card-footer"> <a href="#" style="width:auto" class="btn btn-primary"> Manage Claims </a> </div> </div> </form>
EditUser HttpPost Action
Next, add the following EditUser Post Action method to the AdministrationController. Here, we are using the UserManager service’s UpdateAsync method to update the data in the Identity database. The following code is self-explained, so please go through the comment lines for a better understanding.
[HttpPost] public async Task<IActionResult> EditUser(EditUserViewModel model) { //First Fetch the User by Id from the database var user = await _userManager.FindByIdAsync(model.Id); //Check if the User Exists in the database if (user == null) { //If the User does not exists in the database, then return Not Found Error View ViewBag.ErrorMessage = $"User with Id = {model.Id} cannot be found"; return View("NotFound"); } else { //If the User Exists, then proceed and update the data //Populate the user instance with the data from EditUserViewModel user.Email = model.Email; user.UserName = model.UserName; user.FirstName = model.FirstName; user.LastName = model.LastName; //UpdateAsync Method will update the user data in the AspNetUsers Identity table var result = await _userManager.UpdateAsync(user); if (result.Succeeded) { //Once user data updated redirect to the ListUsers view return RedirectToAction("ListUsers"); } else { //In case any error, stay in the same view and show the model validation error foreach (var error in result.Errors) { ModelState.AddModelError("", error.Description); } } return View(model); } }
UserManager UpdateAsync Method
The UpdateAsync method in ASP.NET Core Identity is part of the UserManager<TUser> class, where TUser is the user entity type, typically derived from IdentityUser. This method is used to update a user’s details in the database. This method is important for operations like changing a user’s email, username, or other personal information stored in the user entity. The method returns an IdentityResult, which indicates whether the operation was successful.
With the above changes in place, run the application and update the user details, and it should work as expected. In our upcoming articles, we will implement the Manage Roles and Manage Claims functionality.
In the next article, I will discuss How to Delete Identity User in ASP.NET Core. In this article, I explain How to Edit Identity Users in ASP.NET Core. I hope you enjoy this article, How to Edit ASP.NET Core Identity User.