【问题标题】:Updating user role using asp.net identity使用 asp.net 身份更新用户角色
【发布时间】:2014-07-22 21:20:30
【问题描述】:

我有以下问题。在使用下面的代码更改用户的当前角色时,我收到异常消息,如下所示:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public virtual ActionResult Edit(User user, string role)
    {
        if (ModelState.IsValid)
        {
            var oldUser = DB.Users.SingleOrDefault(u => u.Id == user.Id);
            var oldRoleId = oldUser.Roles.SingleOrDefault().RoleId;
            var oldRoleName = DB.Roles.SingleOrDefault(r => r.Id == oldRoleId).Name;
            if (oldRoleName != role)
            {
                Manager.RemoveFromRole(user.Id, oldRoleName);
                Manager.AddToRole(user.Id, role);
            }
            DB.Entry(user).State = EntityState.Modified;

            return RedirectToAction(MVC.User.Index());
        }
        return View(user);
    }

附加类型为“Models.Entities.User”的实体失败,因为同一类型的另一个实体已经具有相同的主键值。如果图中的任何实体具有冲突的键值,则在使用“附加”方法或将实体的状态设置为“未更改”或“已修改”时,可能会发生这种情况。这可能是因为某些实体是新实体,尚未收到数据库生成的键值。在这种情况下,使用 'Add' 方法或 'Added' 实体状态来跟踪图形,然后将非新实体的状态适当地设置为 'Unchanged' 或 'Modified'。

有人知道解决这个问题的好方法吗?

【问题讨论】:

标签: asp.net asp.net-mvc asp.net-mvc-5 asp.net-identity


【解决方案1】:

问题在于您的 Manager 和 DB 没有使用相同的 DbContext。因此,当您将用户从数据库上下文发送到管理器时,它将作为“新”用户处理 - 然后您无法将其从角色中删除。你有两种方法可以去这里。最简单的方法是从您的经理那里获取用户。

[HttpPost]
[ValidateAntiForgeryToken]
public virtual ActionResult Edit(User user, string role)
{
    if (ModelState.IsValid)
    {
        // THIS LINE IS IMPORTANT
        var oldUser = Manager.FindById(user.Id);
        var oldRoleId = oldUser.Roles.SingleOrDefault().RoleId;
        var oldRoleName = DB.Roles.SingleOrDefault(r => r.Id == oldRoleId).Name;

        if (oldRoleName != role)
        {
            Manager.RemoveFromRole(user.Id, oldRoleName);
            Manager.AddToRole(user.Id, role);
        }
        DB.Entry(user).State = EntityState.Modified;

        return RedirectToAction(MVC.User.Index());
    }
    return View(user);
}

更优雅的方法是开始使用像 AutoFac (https://code.google.com/p/autofac/wiki/MvcIntegration) 这样的 DI 框架,并将 DbContext 设置为 InstancePerApiRequest。

builder.RegisterType<YourDbContext>().As<DbContext>().InstancePerApiRequest();

【讨论】:

    【解决方案2】:

    我的角色在我的 DbMigrationsConfiguration 类的种子方法中进行管理,我将其重命名为:

            if (context.Roles.Any(r => r.Name == "User"))
            {
                var store = new RoleStore<IdentityRole>(context);
                var manager = new RoleManager<IdentityRole>(store);
                var role = manager.Roles.First(r => r.Name == "User");
    
                role.Name = "NewNameForUser";
                manager.Update(role);
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-11
      • 2016-09-05
      • 2013-12-06
      相关资源
      最近更新 更多