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

Franva picture Franva · Jun 1, 2014 · Viewed 47k times · Source

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?

Answer

Horizon_Net picture Horizon_Net · Jun 1, 2014

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.