更新用户商店标识框架3.0

时间:2015-11-04 08:13:02

标签: c# asp.net-mvc entity-framework asp.net-identity

我几天来一直在寻找解决方案,只找到与旧版Identity Framework相关的答案。

项目使用c#Asp.net MVC 6实体框架7 beta8和Identity Framework 3.0.0-beta代码优先数据。 在一个简单的项目中,我尝试实现仅限管理员的用户信息/编辑器页面,该页面允许通过访问UserStore或UserManager来编辑所有用户属性,并将更改保存到DBcontext中的标准Identity Framework用户存储。

这里是带有额外字段的ApplicationUser Model代码:

public class ApplicationUser : IdentityUser
{
    [Display(Name = "Last Name")]
    [DataType(DataType.Text)]
    [StringLength(50)]
    public string UserLastName { get; set; }

    [Display(Name = "First Name")]
    [DataType(DataType.Text)]
    [StringLength(50)]
    public string UserFirstName { get; set; }

    [Display(Name = "User")]
    public override string UserName { get; set; }
}

索引视图的相应控制器代码:

public class UserListController : Controller
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly SignInManager<ApplicationUser> _signInManager;

    public UserListController(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager)
    {
        _userManager = userManager;
        _signInManager = signInManager;
    }

    // GET: Index
    public IActionResult Index()
    {
        var userStore = new UserStore<ApplicationUser>(new ApplicationDbContext());

        var listofUsers = userStore.Users.ToList();

        if (listofUsers == null)
        {
            return new HttpStatusCodeResult(404);
        }

        return View(listofUsers);
    }

索引视图有一个编辑操作,用于传递所选用户的ID:

@Html.ActionLink("Edit", "Edit", new { id = item.Id })

其余的Controller代码:

    // GET: Edit
    [HttpGet]
    public IActionResult Edit(Guid? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(404);
        }
        var userStore = new UserStore<ApplicationUser>(new ApplicationDbContext());

        ApplicationUser userforEdit = userStore.Users.SingleOrDefault(x => x.Id == id.ToString());

        if (userforEdit == null)
        {
            return new HttpStatusCodeResult(404);
        }
        return View(userforEdit);
    }


    // POST: Edit
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Edit(ApplicationUser editedUser)
    {
        if (ModelState.IsValid)
        {
            var UpdateUserResult = await _userManager.UpdateAsync(editedUser);

            return RedirectToAction("Index");
        }
        return View(editedUser);
    }
}

}

执行

期间出现错误
var UpdateUserResult = await _userManager.UpdateAsync(editedUser);

InvalidOperationException:实体类型的实例&#39; UserManagement.Models.ApplicationUser&#39;无法跟踪,因为已经跟踪了具有相同密钥的此类型的另一个实例。对于新实体,请考虑使用IIdentityGenerator生成唯一键值。

我部分理解两次实例化的问题,但找不到合适的方法或至少找不到解决方法。每次数据库迁移都已更新,并通过dnvm ef迁移应用于数据库。 谢谢你的帮助!

2 个答案:

答案 0 :(得分:7)

没关系,我设法解决了它! 首先,我进行了GET Edit异步任务以遵循工作流程

// GET: Edit
    [HttpGet]
    public async Task<IActionResult> Edit(Guid? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(404);
        }

        ApplicationUser userforEdit = await _userManager.FindByIdAsync(id.ToString());

        if (userforEdit == null)
        {
            return new HttpStatusCodeResult(404);
        }

        return View(userforEdit);
    }

然后我创建了一个新的ApplicationUser并手动传递了字段:

// POST: Edit
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Edit(ApplicationUser editedUser)
    {
        if (ModelState.IsValid)
        {
            ApplicationUser userforEdit = await _userManager.FindByIdAsync(editedUser.Id.ToString());

            userforEdit.UserFirstName = editedUser.UserFirstName;
            userforEdit.UserLastName = editedUser.UserLastName;
            userforEdit.UserName = editedUser.UserName;
            userforEdit.Email = editedUser.Email;

            var UpdateUserResult = await _userManager.UpdateAsync(userforEdit);

            return RedirectToAction("Index");
        }
        return View(editedUser);
    }

我发布它以防其他人卡在那里! 如果还有另一种更优雅或更安全的方式,请告诉我们。

答案 1 :(得分:0)

做同一件事的更好方法:

 ApplicationUser userToEdit = await _userManager.FindByIdAsync(applicationUser.Id.ToString());

 foreach (System.Reflection.PropertyInfo property in typeof(ApplicationUser).GetProperties()) {
                property.SetValue(userToEdit, property.GetValue(applicationUser));
 }

而不是:

 ApplicationUser userforEdit = await _userManager.FindByIdAsync(editedUser.Id.ToString());

 userforEdit.UserFirstName = editedUser.UserFirstName;
 userforEdit.UserLastName = editedUser.UserLastName;
 userforEdit.UserName = editedUser.UserName;
 userforEdit.Email = editedUser.Email;

(userToEdit = userforEdit&applicationUser = editedUser)