Подтвердить что ты не робот

ASP.NET MVC 5 как удалить пользователя и связанные с ним данные в Identity 2.0

Привет, Я следую этой статье, чтобы удалить пользователя в 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

Спасибо.

4b9b3361

Ответ 1

Я думаю, что классы, которые вы ищете, это UserManager и RoleManager. На мой взгляд, это лучший способ, а не прямо против контекста.

UserManager определяет метод RemoveFromRoleAsync, который дает вам возможность удалить пользователя (идентифицированного его ключом) от заданной роли. Он также определяет несколько методов поиска, таких как FindAsync, FindByIdAsync, FindByNameAsync или FindByEmailAsync. Все они могут быть использованы для извлечения пользователя. Чтобы удалить пользователя, вы должны использовать метод DeleteAsync, который принимает объект пользователя в качестве параметра. Чтобы получить роли, которые пользователь является членом Identity, вы получаете метод 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 с помощью Индивидуальные учетные записи.

Ответ 2

  • Brad указывает на необходимость использования @Html.AntiForgeryToken() в представлениях не требуется, если вы используете последние версии ASP.NET - см. AntiForgeryToken по-прежнему требуется
  • Почему бы не создать триггер SQL для AspNetUsers, поэтому удаление пользователя также удаляет соответствующие записи для пользователей из AspNetUserRoles и AspNetUserLogins?
  • Мне нужно вызвать DeleteUser из нескольких мест, поэтому я добавил статический метод в AccountController (см. ниже). Я все еще узнаю о MVC, поэтому должен быть благодарен за комментарии, в частности: 1) использование IdentityResult в качестве кода возврата 2) мудрость расширения AccountController таким образом 3) подход для ввода пароля (cleartext) в модель для проверки действие (см. пример вызова).

     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;
    }
    

Образец вызова - форма передает пароль пользователя (cleartext) в 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);
    }