I’ve been struggling with creating and editing a model that contains another model as part of its model.
SubCategory contains Category as a variable because it needs to be able to reference back to it.
Now I solved the create part by exposing the view to a list of Categories, via the ViewBag and binding it to a dropdown (model => model.Category.ID, new SelectBox .. etc):
public ActionResult Create()
{
ViewBag.Categories = db.Category.ToList();
return View();
}
[HttpPost]
public ActionResult Create(SubCategory subcategory)
{
subcategory.Category = db.Category.Single(x => x.ID == subcategory.Category.ID);
if (ModelState.IsValid)
{
db.SubCategory.Add(subcategory);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(subcategory);
}
As you can see, I had to do a quickfix above to get the subcategory to correctly bind to the category (In the DB Subcategory as a column with CategoryID).
Now when i attempted the same for the Edit function it did not work. Below is my Edit code:
public ActionResult Edit(int id)
{
ViewBag.Categories = db.Category.ToList();
SubCategory subcategory = db.SubCategory.Find(id);
return View(subcategory);
}
[HttpPost]
public ActionResult Edit(SubCategory subcategory)
{
subcategory.Category = db.Category.Single(x => x.ID == subcategory.Category.ID);
if (ModelState.IsValid)
{
UpdateModel(subcategory);
db.Entry(subcategory).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(subcategory);
}
As you can see, same method as the create, Using a break-point i see that subcategory.Category is correctly populated, but for some reason it does not save the state and after the page has reloaded the reference to CategoryID is unchanged.
Any ideas or help will be much appriciated, thanks.
UPDATE
[HttpPost]
public ActionResult Edit(SubCategory subcategory)
{
subcategory.Category = db.Category.Single(x => x.ID == subcategory.Category.ID);
if (ModelState.IsValid)
{
db.SubCategory.Single(x => x.ID == subcategory.ID).Name = subcategory.Name;
db.SubCategory.Single(x => x.ID == subcategory.ID).Category = db.Category.Single(x => x.ID == subcategory.Category.ID);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(subcategory);
}
This works but makes my eyes bleed, so if you have a better suggestion :):
Normally in MVC you don’t bind the
Categoryproperty of yourSubCategorylike the way you shown. Instead you bind to scalar propertyCategoryIdThen in your view
This way you dont have to send an extra round-trip to the database to fetch the
Categoryof theSubCategoryobject.