Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC 5 how to delete a user and its related data in Identity 2.0

I'm following this article to delete a user in Identity 2.0 http://www.asp.net/mvc/tutorials/mvc-5/introduction/examining-the-details-and-delete-methods

However, I need to delete all related records in AspNetUserRoles first and then delete the user.

I found an example which is written in Identity 1.0 and some of methods used inside this example don't exist.

   // POST: /Users/Delete/5         [HttpPost, ActionName("Delete")]         [ValidateAntiForgeryToken]         public async Task<ActionResult> DeleteConfirmed(string id)         {             if (ModelState.IsValid)             {                 if (id == null)                 {                     return new HttpStatusCodeResult(HttpStatusCode.BadRequest);                 }                  var user = await context.Users.FindAsync(id);                 var logins = user.Logins;                 foreach (var login in logins)                 {                     context.UserLogins.Remove(login);                 }                 var rolesForUser = await IdentityManager.Roles.GetRolesForUserAsync(id, CancellationToken.None);                 if (rolesForUser.Count() > 0)                 {                      foreach (var item in rolesForUser)                     {                         var result = await IdentityManager.Roles.RemoveUserFromRoleAsync(user.Id, item.Id, CancellationToken.None);                     }                 }                 context.Users.Remove(user);                 await context.SaveChangesAsync();                 return RedirectToAction("Index");             }             else             {                 return View();             }         } 

I cannot find IdentityManager from anywhere, and context.Users doesn't have FindAsync() method either.

How can I properly delete a User and its related records in Identity 2.0?

like image 927
Franva Avatar asked Jun 01 '14 05:06

Franva


People also ask

How do I remove someone from my identity?

To delete a user you should use the DeleteAsync method which accepts a user object as a parameter. To get the roles a user is member of Identity gives you the GetRolesAsync method where you pass in the ID of the user.

What is identity user in asp net?

ASP.NET Identity is the membership system for authentication and authorization of the users by building an ASP.NET application. ASP.NET Identity is the membership system for authentication and authorization of the users by building an ASP.NET application.


2 Answers

I think the classes you're looking for are the UserManager and the RoleManager. In my opinion they are the better way instead of going against the context directly.

The UserManager defines a method RemoveFromRoleAsync which gives you the ability to remove the user (identified by his key) from a given role. It also defines several Find methods, such as FindAsync, FindByIdAsync, FindByNameAsync, or FindByEmailAsync. They all can be used to retrieve a user. To delete a user you should use the DeleteAsync method which accepts a user object as a parameter. To get the roles a user is member of Identity gives you the GetRolesAsync method where you pass in the ID of the user. Also I see that you're trying to remove a login from a user. For this purpose you should use the RemoveLoginAsync method.

All in all your code would look similar to the following one:

// POST: /Users/Delete/5 [HttpPost, ActionName("Delete")] [ValidateAntiForgeryToken] public async Task<ActionResult> DeleteConfirmed(string id) {   if (ModelState.IsValid)   {     if (id == null)     {       return new HttpStatusCodeResult(HttpStatusCode.BadRequest);     }      var user = await _userManager.FindByIdAsync(id);     var logins = user.Logins;     var rolesForUser = await _userManager.GetRolesAsync(id);      using (var transaction = context.Database.BeginTransaction())     {       foreach (var login in logins.ToList())       {         await _userManager.RemoveLoginAsync(login.UserId, new UserLoginInfo(login.LoginProvider, login.ProviderKey));       }        if (rolesForUser.Count() > 0)       {         foreach (var item in rolesForUser.ToList())         {           // item should be the name of the role           var result = await _userManager.RemoveFromRoleAsync(user.Id, item);         }       }        await _userManager.DeleteAsync(user);       transaction.Commit();     }      return RedirectToAction("Index");   }   else   {     return View();   } } 

You'll need to adjust this snippet to your needs, because I don't have an idea how your IdentityUser implementation looks like. Remember to declare the UserManager as needed. An example how you could do this can be found when you create a new project in Visual Studio using Individual Accounts.

like image 188
Horizon_Net Avatar answered Oct 15 '22 01:10

Horizon_Net


  • Brad's point about requiring @Html.AntiForgeryToken() in views is not necessary if you are using latest versions of ASP.NET - see AntiForgeryToken still required
  • Why not create a SQL trigger for AspNetUsers so deleting a user also deletes the corresponding records for user from AspNetUserRoles and AspNetUserLogins?
  • I need to invoke DeleteUser from a number of places so I added a static method to AccountController (see below). I'm still learning about MVC, so should be grateful for comments, in particular 1) use of IdentityResult as a return code 2) wisdom of extending AccountController in this way 3) approach for putting password (cleartext) into the Model to validate the action (see sample invocation).

     public static async Task<IdentityResult> DeleteUserAccount(UserManager<ApplicationUser> userManager,                                                                           string userEmail, ApplicationDbContext context) {      IdentityResult rc = new IdentityResult();      if ((userManager != null) && (userEmail != null) && (context != null) )     {         var user = await userManager.FindByEmailAsync(userEmail);         var logins = user.Logins;         var rolesForUser = await userManager.GetRolesAsync(user);          using (var transaction = context.Database.BeginTransaction())         {           foreach (var login in logins.ToList())           {             await userManager.RemoveLoginAsync(user, login.LoginProvider, login.ProviderKey);           }            if (rolesForUser.Count() > 0)           {             foreach (var item in rolesForUser.ToList())             {               // item should be the name of the role               var result = await userManager.RemoveFromRoleAsync(user, item);             }           }           rc = await userManager.DeleteAsync(user);           transaction.Commit();         }     }     return rc; } 

Sample invocation - form passes the user's password (cleartext) in Model:

        // POST: /Manage/DeleteUser     [HttpPost]     [ValidateAntiForgeryToken]     public async Task<IActionResult> DeleteUser(DeleteUserViewModel account)     {         var user = await GetCurrentUserAsync();         if ((user != null) && (user.PasswordHash != null) && (account != null) && (account.Password != null))         {             var hasher = new Microsoft.AspNetCore.Identity.PasswordHasher<ApplicationUser>();             if(hasher.VerifyHashedPassword(user,user.PasswordHash, account.Password)  != PasswordVerificationResult.Failed)             {                 IdentityResult rc = await AccountController.DeleteUserAccount( _userManager, user.Email, _Dbcontext);                  if (rc.Succeeded)                 {                     await _signInManager.SignOutAsync();                     _logger.LogInformation(4, "User logged out.");                     return RedirectToAction(nameof(HomeController.Index), "Home");                 }             }         }         return View(account);     } 
like image 29
wpqs Avatar answered Oct 14 '22 23:10

wpqs