web-dev-qa-db-ja.com

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でユーザーとその関連レコードを適切に削除する方法を理解するのを手伝ってください

ありがとう。

32
Franva

探しているクラスは serManagerRoleManager であると思います。私の意見では、それらはコンテキストに直接反するのではなく、より良い方法です。

UserManagerはメソッドを定義します RemoveFromRoleAsync 指定されたロールからユーザー(キーで識別)を削除する機能を提供します。また、 FindAsyncFindByIdAsyncFindByNameAsync 、または FindByEmailAsync などのいくつかのFindメソッドも定義しています。これらはすべて、ユーザーを取得するために使用できます。ユーザーを削除するには、ユーザーオブジェクトをパラメーターとして受け入れる DeleteAsync メソッドを使用する必要があります。ユーザーがIdentityのメンバーであるロールを取得するには、ユーザーのIDを渡す GetRolesAsync メソッドを提供します。また、ユーザーからログインを削除しようとしていることがわかります。このためには、 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で新しいプロジェクトを作成するときに見つけることができます。

59
Horizon_Net

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  
    }
}
2
wpqs
  • ASP.NETの最新バージョンを使用している場合、ビューで@ Html.AntiForgeryToken()を要求することについてのBradの要点- AntiForgeryTokenがまだ必要です
  • ユーザーを削除すると、AspNetUserRolesおよびAspNetUserLoginsからユーザーの対応するレコードも削除されるように、AspNetUsersのSQLトリガーを作成しないのはなぜですか?
  • いくつかの場所から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;
    }
    

サンプル呼び出し-フォームは、モデルでユーザーのパスワード(クリアテキスト)を渡します。

        // 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

私も答えを探していましたが、最終的にこれは私にとってはうまくいくものです、その古い投稿でも、それは誰かのために役立つかもしれません。

// 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