ASP.NET Identity UserManager UpdateAsync删除角色

时间:2018-08-15 11:51:46

标签: c# asp.net-core asp.net-core-identity

我们的应用程序中有一个屏幕,允许管理员角色的成员编辑用户帐户详细信息。

最终,任何用户对象都将发送到服务器并使用以下命令进行更新:

await userManager.UpdateAsync(user);

这正在按预期工作以更新用户记录。我们可以进行持久化到数据库的更改,例如用户名,电话号码等。

我看到的问题是,有时更新角色而不是向用户添加其他角色会删除所有角色。

在我们的ApplicationUser对象上,我们具有这样的属性:

public virtual ICollection<IdentityUserRole<string>> Roles { get; set; } = new List<IdentityUserRole<string>>();

因此,我们可以在客户端和服务器之间反弹角色,作为用户对象的一部分。

我正在努力了解的是我看到的userManager.UpdateAsync(user);方法的不一致行为。它显然可以正常工作,或者永远无法向用户添加任何角色。

每次提交对象时,正确地使用角色填充到达服务器的对象。基本流程是:

  1. 添加角色并提交
  2. 该角色已正确添加到用户
  3. 添加其他角色并提交
  4. 所有角色均已删除

如何防止其删除角色?

谢谢!

更新

如@amirani的答案中所述,我尝试过滤现有列表。我已经设置AutoMapper来完全忽略该属性。

.ForMember(x => x.Roles, opt => opt.Ignore());

现在我只是像这样过滤(仅此刻添加):

foreach (var userDtoRole in userDto.Roles)
{
  if (user.Roles.FirstOrDefault(x => x.RoleId == userDtoRole) == null)
  {
    user.Roles.Add(new IdentityUserRole<string> {RoleId = userDtoRole, UserId = user.Id });
  }
}

其他角色永远不会添加到基础数据库中。在执行UpdateUser方法之前,我已经确认要更新的用户对象具有正确的角色列表。

2 个答案:

答案 0 :(得分:1)

致电await userManager.UpdateAsync(user);时,您正在使用其所有相关数据更新用户模型。您需要将新角色添加到现有角色列表中,而不是创建新的空列表并添加新记录。

答案 1 :(得分:1)

在下面尝试添加新角色的代码

private readonly ApplicationDbContext _context;
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly RoleManager<IdentityRole> _roleManager;
    public HomeController(ApplicationDbContext context
        , UserManager<ApplicationUser> userManager
        , RoleManager<IdentityRole> roleManager)
    {
        _context = context;
        _userManager = userManager;
        _roleManager = roleManager;
    }
    public async Task<IActionResult> CreateUserAndRole()
    {
        await _userManager.CreateAsync(new ApplicationUser { UserName = "test@outlook.com", Email = "test@outlook.com" });
        await _roleManager.CreateAsync(new IdentityRole {  Name = "Admin" });
        await _roleManager.CreateAsync(new IdentityRole { Name = "Administrator" });
        return Ok();
    }
    public async Task<IActionResult> AddAdminRoleToUser()
    {
        ApplicationUser user = _context.Users.FirstOrDefault(u => u.UserName == "test@outlook.com");
        var role = await _roleManager.FindByNameAsync("Admin");
        user.Roles.Add(new IdentityUserRole<string> { RoleId = role.Id, UserId = user.Id });
        await _userManager.UpdateAsync(user);
        return Ok();
    }
    public async Task<IActionResult> AddAdministratorRoleToUser()
    {
        ApplicationUser user = _context.Users.FirstOrDefault(u => u.UserName == "test@outlook.com");
        var role = await _roleManager.FindByNameAsync("Administrator");
        user.Roles.Add(new IdentityUserRole<string> { RoleId = role.Id, UserId = user.Id });
        await _userManager.UpdateAsync(user);
        return Ok();
    }