我几天来一直在寻找解决方案,只找到与旧版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迁移应用于数据库。 谢谢你的帮助!
答案 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)