涉及到的 Model 和 ViewModel:

    1. namespace StudentManagement.Models
    2. {
    3. public class UserClaim
    4. {
    5. public string ClaimType { get; set; }
    6. public bool IsSelected { get; set; }
    7. }
    8. }
    9. namespace StudentManagement.ViewModels
    10. {
    11. public class UserClaimsViewModel
    12. {
    13. public string UserId { get; set; }
    14. public List<UserClaim> Claims { get; set; }
    15. public UserClaimsViewModel()
    16. {
    17. Claims = new List<UserClaim>();
    18. }
    19. }
    20. }

    为了方便调试,先制作一个内存中的 Claim 集合:

    1. namespace StudentManagement.Models
    2. {
    3. public class ClaimsStore
    4. {
    5. public static List<Claim> AllClaims = new List<Claim>
    6. {
    7. new Claim("Create Role","Create Role"),
    8. new Claim("Edit Role","Edit Role"),
    9. new Claim("Delete Role","Delete Role"),
    10. new Claim("Edit Student","Edit Student")
    11. };
    12. }
    13. }

    编辑用户声明的方法:

    1. [HttpGet]
    2. public async Task<IActionResult> ManageUserClaims(string userId)
    3. {
    4. var user = await _userManager.FindByIdAsync(userId);
    5. if (user == null)
    6. {
    7. ViewBag.ErrorMessage = $"无法找到 Id {userId} 的用户";
    8. return View("NotFound");
    9. }
    10. // 获取用户当前所有 Claim
    11. var existingUserClaims = await _userManager.GetClaimsAsync(user);
    12. var model = new UserClaimsViewModel
    13. {
    14. UserId = userId
    15. };
    16. foreach (var claim in ClaimsStore.AllClaims)
    17. {
    18. var userClaim = new UserClaim
    19. {
    20. ClaimType = claim.Type
    21. };
    22. if (existingUserClaims.Any(c => c.Type == claim.Type))
    23. {
    24. userClaim.IsSelected = true;
    25. }
    26. model.Claims.Add(userClaim);
    27. }
    28. return View(model);
    29. }
    30. [HttpPost]
    31. public async Task<IActionResult> ManageUserClaims(UserClaimsViewModel model)
    32. {
    33. var user = await _userManager.FindByIdAsync(model.UserId);
    34. if (user == null)
    35. {
    36. ViewBag.ErrorMessage = $"无法找到 Id {model.UserId} 的用户";
    37. return View("NotFound");
    38. }
    39. var claims = await _userManager.GetClaimsAsync(user);
    40. var removeClaimsResult = await _userManager.RemoveClaimsAsync(user, claims);
    41. if (!removeClaimsResult.Succeeded)
    42. {
    43. ModelState.AddModelError("", "无法删除当前用户的声明");
    44. return View(model);
    45. }
    46. var addClaimsResult = await _userManager.AddClaimsAsync(user,
    47. model.Claims.Where(c => c.IsSelected).Select(c => new Claim(c.ClaimType, c.ClaimType)));
    48. if (!addClaimsResult.Succeeded)
    49. {
    50. ModelState.AddModelError("", "无法向用户添加选定的声明");
    51. return View(model);
    52. }
    53. return RedirectToAction("EditUser", new { Id = model.UserId });
    54. }

    管理用户声明的视图(和管理用户角色的视图很相似):

    1. @model UserClaimsViewModel
    2. <form method="post">
    3. <div class="card">
    4. <div class="card-header">
    5. <h2>管理用户声明</h2>
    6. </div>
    7. <div class="card-body">
    8. @for (var i = 0; i < Model.Claims.Count; i++)
    9. {
    10. <div class="form-check m-1">
    11. <input type="hidden" asp-for="@Model.Claims[i].ClaimType" />
    12. <input asp-for="@Model.Claims[i].IsSelected" class="form-check-input" />
    13. <label class="form-check-label" asp-for="@Model.Claims[i].IsSelected">
    14. @Model.Claims[i].ClaimType
    15. </label>
    16. </div>
    17. }
    18. <div asp-validation-summary="All" class="text-danger"></div>
    19. </div>
    20. <div class="card-footer">
    21. <input type="submit" value="更新" class="btn btn-primary" style="width: auto" />
    22. <a class="btn btn-primary" style="width: auto" asp-action="EditUser" asp-route-id="@Model.UserId">取消</a>
    23. </div>
    24. </div>
    25. </form>