2015-05-29 28 views
1

我很難弄清楚如何使用實體框架和標識更新/修改AspNetUsers表中的用戶。我收到一條錯誤消息:使用身份的實體框架 - 嘗試更新AspNetUsers表中的用戶

「實體類型ManagerUserViewModel不是當前上下文的模型的一部分。」

這是有道理的,因爲我沒有提到我使用的ApplicationDbContext中的ManagerUserViewModel。但是,我應該創建一個類似於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(); 
    } 

} 

讓我知道是否需要其他代碼。

編輯:根據史蒂夫的評論,我試圖創建一個新的上下文。

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()。現在它不會出錯,但它仍不會更新用戶。

+0

另一種選擇是隻讓你的應用程序上下文繼承身份背景。 http://www.typecastexception.com/post/2014/04/20/ASPNET-MVC-and-Identity-20-Understanding-the-Basics.aspx#The-Heart-of-it-All---ApplicationDbContext –

+0

我試圖創建一個繼承'IdentityDbContext'的新上下文。我編輯了我的帖子。 – dmikester1

回答

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

在行'user = await manager.FindByIdAsync(model.UserID)'我得到錯誤''等待'操作符只能在異步方法中使用。考慮使用'async'修飾符標記此方法並將其返回類型更改爲'Task ' – dmikester1

+0

我已更新答案。該方法的用戶非異步版本:FindById –

+0

這個技巧!謝謝! – dmikester1

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。

+0

我在我的IdentityModel中找到了一個ApplicationUser類。這是你所指的課程嗎? – dmikester1

+0

你的'EditUserViewModel'中有什麼? – dmikester1

+0

你可以把'EditUserViewModel'放在哪裏? – dmikester1