使用标识的实体框架 - 尝试更新AspNetUsers表中的用户

时间:2015-05-29 18:45:00

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

我很难弄清楚如何使用Entity Framework和Identity更新/修改AspNetUsers表中的用户。我收到的错误是:

  

“实体类型ManagerUserViewModel不是当前上下文模型的一部分。”

这是有道理的,因为我没有提到我正在使用的ManagerUserViewModel中的ApplicationDbContext。但是,我应该创建一个类似于ApplicationDBContext的新上下文并使用它吗?或者我以某种方式将ManagerUserViewModel添加到ApplicationDBContext

这是我的控制器方法,在点击“保存”时进行更新:

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();
    }

}

如果需要任何其他代码,请告诉我。

编辑:根据Steve的评论,我尝试创建一个新的上下文。

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()。现在它不会出错,但它仍然不会更新用户。

2 个答案:

答案 0 :(得分:1)

摆脱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。

答案 1 :(得分:1)

你几乎做对了。当UserManager存在时,无需使用DbContext更新用户。

您的代码应该是这样的:

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);
}