webentwicklung-frage-antwort-db.com.de

ASP.NET MVC 5 So löschen Sie einen Benutzer und die zugehörigen Daten in Identity 2.0

Hallo, ich folge diesem Artikel, um einen Benutzer in Identity 2.0 zu löschen http://www.asp.net/mvc/tutorials/mvc-5/einführung/examining-the-details-and-delete-methods

Ich muss jedoch zuerst alle zugehörigen Datensätze in AspNetUserRoles löschen und dann den Benutzer löschen.

Ich habe ein in Identity 1.0 geschriebenes Beispiel gefunden, und einige der in diesem Beispiel verwendeten Methoden sind nicht vorhanden.

   // 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();
            }
        }

Ich kann IdentityManager nicht überall finden, und context.Users hat auch keine FindAsync()-Methode.

Bitte helfen Sie, herauszufinden, wie Sie einen Benutzer und die zugehörigen Datensätze in Identity 2.0 ordnungsgemäß löschen

Vielen Dank.

29
Franva

Ich denke, die Klassen, nach denen Sie suchen, sind UserManager und RoleManager . Meiner Meinung nach sind sie der bessere Weg, anstatt direkt in den Kontext zu treten.

Der UserManager definiert eine Methode RemoveFromRoleAsync , mit der Sie den (durch seinen Schlüssel identifizierten) Benutzer aus einer bestimmten Rolle entfernen können. Es definiert auch mehrere Find-Methoden, wie FindAsync , FindByIdAsync , FindByNameAsync oder FindByEmailAsync . Sie können alle zum Abrufen eines Benutzers verwendet werden. Um einen Benutzer zu löschen, sollten Sie die Methode DeleteAsync verwenden, die ein Benutzerobjekt als Parameter akzeptiert. Um die Rollen zu erhalten, die ein Benutzer Mitglied von Identity ist, erhalten Sie die Methode GetRolesAsync , bei der Sie die ID des Benutzers übergeben. Ich sehe auch, dass Sie versuchen, ein Login von einem Benutzer zu entfernen. Zu diesem Zweck sollten Sie die Methode RemoveLoginAsync verwenden.

Alles in allem würde Ihr Code dem folgenden ähnlich aussehen:

// 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();
  }
}

Sie müssen dieses Snippet an Ihre Bedürfnisse anpassen, da ich keine Ahnung habe, wie Ihre IdentityUser -Implementierung aussieht. Denken Sie daran, den UserManager nach Bedarf zu deklarieren. Ein Beispiel, wie Sie dies tun können, finden Sie, wenn Sie ein neues Projekt in Visual Studio mit Individual Accounts erstellen.

55
Horizon_Net

Update für ASP.NET Core 2.0 - Ich hoffe, dies erspart jemandem etwas Zeit

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  
    }
}
2
wpqs
  • Brads Argument, dass in Ansichten @ Html.AntiForgeryToken () erforderlich ist, ist nicht erforderlich, wenn Sie die neuesten Versionen von ASP.NET verwenden - siehe AntiForgeryToken weiterhin erforderlich
  • Erstellen Sie einen SQL-Trigger für AspNetUser. Wenn Sie also einen Benutzer löschen, werden auch die entsprechenden Datensätze für den Benutzer aus AspNetUserRoles und AspNetUserLogins gelöscht.
  • Ich muss DeleteUser von einer Reihe von Stellen aus aufrufen, damit ich AccountController eine statische Methode hinzufüge (siehe unten). Ich lerne immer noch über MVC und bin daher für Kommentare dankbar. Insbesondere 1) Verwendung von IdentityResult als Rückkehrcode. 2) Weisheit, AccountController auf diese Weise zu erweitern Aktion (siehe Beispielaufruf).

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

Beispielaufruf - Formular übergibt das Passwort des Benutzers (Klartext) in Modell:

        // 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);
    }
2
wpqs

Ich war auch auf der Suche nach der Antwort, aber schließlich ist es das, was für mich gut funktioniert, sogar der alte Post, aber es kann für jemanden helfen.

// 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();
        }
    }
0
Alik