ASP.NET MVC 5 how to delete a user and its related data in Identity 2.0
Update for ASP.NET Core 2.0 - hope this saves someone a bit of time
ApplicationDbContext context,
UserManager<ApplicationUser> userManager,
ApplicationUser user
var logins = await userManager.GetLoginsAsync(user);
var rolesForUser = await userManager.GetRolesAsync(user);
using (var transaction = context.Database.BeginTransaction())
{
IdentityResult result = IdentityResult.Success;
foreach (var login in logins)
{
result = await userManager.RemoveLoginAsync(user, login.LoginProvider, login.ProviderKey);
if (result != IdentityResult.Success)
break;
}
if (result == IdentityResult.Success)
{
foreach (var item in rolesForUser)
{
result = await userManager.RemoveFromRoleAsync(user, item);
if (result != IdentityResult.Success)
break;
}
}
if (result == IdentityResult.Success)
{
result = await userManager.DeleteAsync(user);
if (result == IdentityResult.Success)
transaction.Commit(); //only commit if user and all his logins/roles have been deleted
}
}
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.