Entity Framework 使用身份 - 尝试更新 AspNetUsers 中的用户 table
Entity Framework using Identity - Trying to update a user in the AspNetUsers table
我很难弄清楚如何 update/modify 我的 AspNetUsers
table 中的用户使用 Entity Framework 和身份。我收到一条错误消息:
"The entity type ManagerUserViewModel is not part of the model for the current context."
这是有道理的,因为我没有在我使用的 ApplicationDbContext
中提到 ManagerUserViewModel
。但是我应该创建一个类似于 ApplicationDBContext
的新上下文并使用它吗?或者我是否以某种方式将我的 ManagerUserViewModel
添加到 ApplicationDBContext
?
这是我的控制器方法,它在单击 'Save' 时进行更新:
public ActionResult EditUser([Bind(Include = "UserID, Email, UserName, Roles, RoleID, RoleName")] ManagerUserViewModel model)
{
if (ModelState.IsValid)
{
using (var context = new ApplicationDbContext())
{
var store = new UserStore<ApplicationUser>(context);
var manager = new UserManager<ApplicationUser>(store);
ApplicationUser user = new ApplicationUser();
user.Email = model.Email;
user.UserName = model.UserName;
if (model.UserID == "")
{
// Since it didn't have a UserID, we assume this is a new User
Task.WaitAny(manager.CreateAsync(user, "Password12"));
}
else
{
// Since EF doesn't know about this product (it was instantiated by
// the ModelBinder and not EF itself, we need to tell EF that the
// object exists and that it is a modified copy of an existing row
context.Entry(model).State = EntityState.Modified;
Task.WaitAny(manager.UpdateAsync(user));
}
if (model.RoleName != null && model.RoleName != "")
{
Task.WaitAny(manager.AddToRoleAsync(model.UserID, model.RoleName));
}
Task.WaitAny(context.SaveChangesAsync());
return RedirectToAction("ControlPanel");
}
}
return View(model);
}
这是我的 ManagerUserViewModel:
public class ManagerUserViewModel
{
public String UserID { get; set; }
public String Email { get; set; }
public String UserName { get; set; }
[Display(Name = "Role(s)")]
public IEnumerable<String> Roles { get; set; }
public String RoleID { get; set; }
public String RoleName { get; set; }
public IEnumerable<SelectListItem> RoleList { get; set; }
public static IEnumerable<SelectListItem> getRoles(string id = "")
{
using (var db = new ApplicationDbContext())
{
List<SelectListItem> list = new List<SelectListItem>();
foreach (var role in db.Roles)
{
SelectListItem sli = new SelectListItem { Value = role.Name, Text = role.Name};
list.Add(sli);
}
return list;
}
}
public static String getRoleID(string role)
{
using (var db = new IdentityDbContext())
{
string roleID = db.Roles.Where(r => r.Name == role).First().Id;
return roleID;
}
}
}
这是我的 ApplicationDBContext:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public DbSet<RegisterViewModel> RegisterUsers { get; set; }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
如果需要任何其他代码,请告诉我。
编辑: 根据史蒂夫的评论,我尝试创建一个新的上下文。
public class ManageUserDbContext : IdentityDbContext<ApplicationUser>
{
public ManageUserDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public DbSet<ManagerUserViewModel> Users { get; set; }
public static ManageUserDbContext Create()
{
return new ManageUserDbContext();
}
}
然后在 Controller 方法中,我将使用上下文切换为 new ManageUserDbContext()
。现在它不报错了,但它仍然不更新用户。
摆脱 ManagerUserViewModel。通过继承,您可以自动访问用户,这样的代码应该可以工作:
[HttpPost]
[Authorize(Roles = "Admin")]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(EditUserViewModel editUserViewModel)
{
if (!ModelState.IsValid) return View(editUserViewModel);
ApplicationUser user = _db.Users.First(u => u.UserName == editUserViewModel.UserName);
user = Mapper.Map(editUserViewModel, user);
await _db.SaveChangesAsync();
return RedirectToAction("Index").WithSuccess("User updated.");
}
请注意,我不需要用户的 DbSet 或任何映射等。我可以将自定义字段添加到我的 ApplicationUser 模型:
public class ApplicationUser : IdentityUser
{
[Required]
[MaxLength(50)]
public string FirstName { get; set; }
[Required]
[MaxLength(50)]
public string LastName { get; set; }
[MaxLength(5)]
public string PhoneExtension { get; set; }
[Required]
[MaxLength(4)]
public string DefaultDistrictNumber { get; set; }
}
要创建用户,您需要调用 UserManager 和 RoleManager。
你几乎做对了。当您有 UserManager 时,无需使用 DbContext 来更新 User。
您的代码应该是这样的:
public ActionResult EditUser([Bind(Include = "UserID, Email, UserName, Roles, RoleID, RoleName")] ManagerUserViewModel model)
{
if (ModelState.IsValid)
{
using (var context = new ApplicationDbContext())
{
var store = new UserStore<ApplicationUser>(context);
var manager = new UserManager<ApplicationUser>(store);
ApplicationUser user = new ApplicationUser();
user.Email = model.Email;
user.UserName = model.UserName;
if (model.UserID == "")
{
// Since it didn't have a UserID, we assume this is a new User
Task.WaitAny(manager.CreateAsync(user, "Password12"));
}
else
{
// here we fetch existing user, update properties and call manager update
user = manager.FindById(model.UserID)
user.Email = model.Email;
user.UserName = model.UserName;
Task.WaitAny(manager.UpdateAsync(user));
}
if (model.RoleName != null && model.RoleName != "")
{
Task.WaitAny(manager.AddToRoleAsync(model.UserID, model.RoleName));
}
Task.WaitAny(context.SaveChangesAsync());
return RedirectToAction("ControlPanel");
}
}
return View(model);
}
我很难弄清楚如何 update/modify 我的 AspNetUsers
table 中的用户使用 Entity Framework 和身份。我收到一条错误消息:
"The entity type ManagerUserViewModel is not part of the model for the current context."
这是有道理的,因为我没有在我使用的 ApplicationDbContext
中提到 ManagerUserViewModel
。但是我应该创建一个类似于 ApplicationDBContext
的新上下文并使用它吗?或者我是否以某种方式将我的 ManagerUserViewModel
添加到 ApplicationDBContext
?
这是我的控制器方法,它在单击 'Save' 时进行更新:
public ActionResult EditUser([Bind(Include = "UserID, Email, UserName, Roles, RoleID, RoleName")] ManagerUserViewModel model)
{
if (ModelState.IsValid)
{
using (var context = new ApplicationDbContext())
{
var store = new UserStore<ApplicationUser>(context);
var manager = new UserManager<ApplicationUser>(store);
ApplicationUser user = new ApplicationUser();
user.Email = model.Email;
user.UserName = model.UserName;
if (model.UserID == "")
{
// Since it didn't have a UserID, we assume this is a new User
Task.WaitAny(manager.CreateAsync(user, "Password12"));
}
else
{
// Since EF doesn't know about this product (it was instantiated by
// the ModelBinder and not EF itself, we need to tell EF that the
// object exists and that it is a modified copy of an existing row
context.Entry(model).State = EntityState.Modified;
Task.WaitAny(manager.UpdateAsync(user));
}
if (model.RoleName != null && model.RoleName != "")
{
Task.WaitAny(manager.AddToRoleAsync(model.UserID, model.RoleName));
}
Task.WaitAny(context.SaveChangesAsync());
return RedirectToAction("ControlPanel");
}
}
return View(model);
}
这是我的 ManagerUserViewModel:
public class ManagerUserViewModel
{
public String UserID { get; set; }
public String Email { get; set; }
public String UserName { get; set; }
[Display(Name = "Role(s)")]
public IEnumerable<String> Roles { get; set; }
public String RoleID { get; set; }
public String RoleName { get; set; }
public IEnumerable<SelectListItem> RoleList { get; set; }
public static IEnumerable<SelectListItem> getRoles(string id = "")
{
using (var db = new ApplicationDbContext())
{
List<SelectListItem> list = new List<SelectListItem>();
foreach (var role in db.Roles)
{
SelectListItem sli = new SelectListItem { Value = role.Name, Text = role.Name};
list.Add(sli);
}
return list;
}
}
public static String getRoleID(string role)
{
using (var db = new IdentityDbContext())
{
string roleID = db.Roles.Where(r => r.Name == role).First().Id;
return roleID;
}
}
}
这是我的 ApplicationDBContext:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public DbSet<RegisterViewModel> RegisterUsers { get; set; }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
如果需要任何其他代码,请告诉我。
编辑: 根据史蒂夫的评论,我尝试创建一个新的上下文。
public class ManageUserDbContext : IdentityDbContext<ApplicationUser>
{
public ManageUserDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public DbSet<ManagerUserViewModel> Users { get; set; }
public static ManageUserDbContext Create()
{
return new ManageUserDbContext();
}
}
然后在 Controller 方法中,我将使用上下文切换为 new ManageUserDbContext()
。现在它不报错了,但它仍然不更新用户。
摆脱 ManagerUserViewModel。通过继承,您可以自动访问用户,这样的代码应该可以工作:
[HttpPost]
[Authorize(Roles = "Admin")]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(EditUserViewModel editUserViewModel)
{
if (!ModelState.IsValid) return View(editUserViewModel);
ApplicationUser user = _db.Users.First(u => u.UserName == editUserViewModel.UserName);
user = Mapper.Map(editUserViewModel, user);
await _db.SaveChangesAsync();
return RedirectToAction("Index").WithSuccess("User updated.");
}
请注意,我不需要用户的 DbSet 或任何映射等。我可以将自定义字段添加到我的 ApplicationUser 模型:
public class ApplicationUser : IdentityUser
{
[Required]
[MaxLength(50)]
public string FirstName { get; set; }
[Required]
[MaxLength(50)]
public string LastName { get; set; }
[MaxLength(5)]
public string PhoneExtension { get; set; }
[Required]
[MaxLength(4)]
public string DefaultDistrictNumber { get; set; }
}
要创建用户,您需要调用 UserManager 和 RoleManager。
你几乎做对了。当您有 UserManager 时,无需使用 DbContext 来更新 User。
您的代码应该是这样的:
public ActionResult EditUser([Bind(Include = "UserID, Email, UserName, Roles, RoleID, RoleName")] ManagerUserViewModel model)
{
if (ModelState.IsValid)
{
using (var context = new ApplicationDbContext())
{
var store = new UserStore<ApplicationUser>(context);
var manager = new UserManager<ApplicationUser>(store);
ApplicationUser user = new ApplicationUser();
user.Email = model.Email;
user.UserName = model.UserName;
if (model.UserID == "")
{
// Since it didn't have a UserID, we assume this is a new User
Task.WaitAny(manager.CreateAsync(user, "Password12"));
}
else
{
// here we fetch existing user, update properties and call manager update
user = manager.FindById(model.UserID)
user.Email = model.Email;
user.UserName = model.UserName;
Task.WaitAny(manager.UpdateAsync(user));
}
if (model.RoleName != null && model.RoleName != "")
{
Task.WaitAny(manager.AddToRoleAsync(model.UserID, model.RoleName));
}
Task.WaitAny(context.SaveChangesAsync());
return RedirectToAction("ControlPanel");
}
}
return View(model);
}