I am new to ASP.net, MVC4, and EF and find it difficult to jump from relatively simple patterns to something (just a little) more complicated. I simplified my model for the question, so consider the following. Forgive me if I have incorrect terminology.
I have an Employee object and a Division object. An employee can be in many departments, and a department can have many employees.
public class Employee { public int EmployeeId { get; set; } public String FirstName { get; set; } public String LastName { get; set; } public virtual ICollection<Division> Divisions { get; set; } } public class Division { public int DivisionId { get; set; } public String DivisionName { get; set; } public virtual ICollection<Employee> Employees { get; set; } }
I displayed them in the context file as follows:
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<Employee>() .HasMany(e => e.Divisions) .WithMany(d => d.Employees) .Map(m => { m.ToTable("EmployeesDivisionsId"); m.MapLeftKey("EmployeeId"); m.MapRightKey("DivisionId"); }); }
For my view controller, I have the following. I used the ViewBag (what name) for many-to-one relationships, and they worked great, so I'm trying to change this to work with many for many:
public ActionResult Index() { return View(db.Employees).ToList()); } // // GET: /Employees/Details/5 public ActionResult Details(int id = 0) { Employee employee = db.Employees.Find(id); if (employee == null) { return HttpNotFound(); } return View(employee); } // // GET: /Employees/Create public ActionResult Create() { ViewBag.Divisions = new MultiSelectList(db.Divisions, "DivisionId", "DivisionName"); return View(); } // // POST: /Employees/Create [HttpPost] public ActionResult Create(Employee employee) { ViewBag.Divisions = new MultiSelectList(db.Divisions, "DivisionId", "DivisionName"); if (ModelState.IsValid) { db.Employees.Add(employee); db.SaveChanges(); return RedirectToAction("Index"); } return View(employee); }
Finally, in the Edit View, I have the following code. Again, for a many-to-one relationship, a simple DropDownList works fine with the ViewBag in the controller, and with this many many multiselect / ListBox methods, the Views are displayed in the view, but when the Save button is clicked, the check '1, 2' is not displayed .
<div class="editor-label"> @Html.LabelFor(model => model.Divisions) </div> <div class="editor-field"> @Html.ListBox("Divisions") @Html.ValidationMessageFor(model => model.Divisions) </div>
So, as I understand it, the list of "Divisions" is correctly extracted from the database and correctly selected in the view, but when saved in the database, the association through the associated relation is not performed.
So my questions are: How do I make this work, so when I save, the correct "Divisions" are saved in Employee?
Also, I heard that people don't like to use ViewBags, is there an (better?) Alternative way?