我将按照本文删除Identity 2.0中的一个用户http://www.asp.net/mvc/tutorials/mvc-5/introduction/examining-the-details-and-delete-methods
但是,我需要先删除AspNetUserRoles中的所有相关记录,然后再删除用户。
我发现了一个用Identity 1.0编写的例子,其中使用的一些方法不存在。
// 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();
}
}
我找不到IdentityManager
, context.Users
也没有FindAsync()
方法。
如何在Identity 2.0中正确删除User及其相关记录?
我认为你正在寻找的类是UserManager和RoleManager。在我看来,比起直接违背上下文,它们是更好的方法。
UserManager定义了一个方法RemoveFromRoleAsync,它使您能够从给定的角色中删除用户(由其密钥标识)。它还定义了几个Find方法,如FindAsync、FindByIdAsync、FindByNameAsync或FindByEmailAsync。它们都可以用来检索用户。要删除一个用户,你应该使用DeleteAsync方法,该方法接受一个用户对象作为参数。要获取用户作为Identity成员的角色,您可以使用GetRolesAsync方法,在该方法中传入用户的ID。此外,我看到你试图从用户删除登录。为此,您应该使用RemoveLoginAsync方法。总之,你的代码看起来就像下面这个:
// 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();
}
}
您需要根据您的需要调整这个代码片段,因为我不知道您的IdentityUser实现是什么样的。记住根据需要声明UserManager。当您在Visual Studio中使用Individual Accounts创建一个新项目时,可以找到一个如何做到这一点的示例。
更新为ASP。. NET Core 2.0 -希望这能节省一些时间
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
}
}
- 如果你使用的是最新版本的ASP, Brad关于在视图中要求@Html.AntiForgeryToken()的观点是没有必要的。. NET -参见AntiForgeryToken仍然需要
- 为什么不为AspNetUsers创建一个SQL触发器,这样删除一个用户也会从AspNetUserRoles和AspNetUserLogins中删除相应的用户记录?
我需要从许多地方调用DeleteUser,所以我添加了一个静态方法到AccountController(见下文)。我仍然在学习MVC,所以应该感谢您的评论,特别是1)使用IdentityResult作为返回代码2)以这种方式扩展AccountController的智慧3)将密码(明文)放入模型以验证操作的方法(参见示例调用)。
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; }
示例调用-表单在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);
}
我也在寻找答案,但最后这是什么对我来说很好,即使是旧的帖子,但它可能对某人有帮助。
// GET: Users/Delete/5
public ActionResult Delete(string id)
{
using (SqlConnection sqlCon = new SqlConnection(connectionString))
{
sqlCon.Open();
string query = "DELETE FROM AspNetUsers WHERE Id = @Id";
SqlCommand sqlCmd = new SqlCommand(query, sqlCon);
sqlCmd.Parameters.AddWithValue("@Id", id);
sqlCmd.ExecuteNonQuery();
}
return RedirectToAction("Index");
}
// POST: Users/Delete/5
[HttpPost]
public ActionResult Delete(string id, FormCollection collection)
{
try
{
// TODO: Add delete logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}