I’m trying to get my head around related data for use with a master detail scenario using EF in MVC. Searching StackOverflow got me on the road for a good part, but I’m running into problems while saving my data. As more examples on StackOverflow i use a person/address set up, and for the person as well as the address (which is one-to-many) i only use part of the entities properties on my views. With the default scaffold this results in an error, but for the person entity i managed to solve that using the the code below. But for the Address entity I now get the same error and i don’t know how to solve this. Here’s what i’ve got so far:
The ContactController:
public ActionResult Edit(int id)
{
Contact contact = db.Contacts
.Include(c => c.Address)
.Include(c => c.Relation)
.Where(c => c.ContactId == id)
.Single();
return View(contact);
}
[HttpPost]
public ActionResult Edit(int id, FormCollection formCollection)
{
var contactToUpdate = db.Contacts
.Include(c => c.Address)
.Include(c => c.Relation)
.Where(c => c.ContactId == id)
.Single();
if (TryUpdateModel(contactToUpdate, "", null, new string[] { "Relation" }))
{
try
{
db.Entry(contactToUpdate).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
catch (DataException ex)
{
ModelState.AddModelError("", "Error while saving.");
return View();
}
}
return View(contactToUpdate);
}
The classes for my models:
namespace MyApp.Models
{
public class Contact
{
public int ContactId { get; set; }
public string Weergavenaam { get; set; }
public virtual ICollection<Address> Address{ get; set; }
public virtual ICollection<Relation> Relation { get; set; }
}
public class Address
{
public int AddressId { get; set; }
public string Street{ get; set; }
public string Postal{ get; set; }
public string Place{ get; set; }
public string State{ get; set; }
public DateTime Created { get; set; }
public DateTime Modified { get; set; }
public virtual Contact Contact { get; set; }
}
public class Relation
{
...
}
}
The view for the ContactController’s Edit action:
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Contact</legend>
@Html.HiddenFor(model => model.ContactId)
<div class="editor-label">
@Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
</div>
@Html.EditorFor(model => model.Address)
<div class="display-field">
Created: @Html.DisplayFor(model => model.Created)
</div>
<div class="display-field">
Modified: @Html.DisplayFor(model => model.Modiied)
</div>
<p><input type="submit" value="Save" /></p>
</fieldset>
}
The EditorTemplate for the Address model
@model MyApp.Models.Address
<fieldset>
<legend>Address</legend>
@Html.HiddenFor(model => model.AddressId)
<div class="editor-label">
@Html.LabelFor(model => model.Street)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Street)
@Html.ValidationMessageFor(model => model.Street)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Postal)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Postal)
@Html.ValidationMessageFor(model => model.Postal)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Place)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Place)
@Html.ValidationMessageFor(model => model.Place)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.State)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.State)
@Html.ValidationMessageFor(model => model.State)
</div>
</fieldset>
After struggling a bit with the code I figured that for now the only way to solve the problem was to add the missing properties to the editor template using @Html.HiddenFor.
Of course I’m sure there should be a more ellegant way to get my situation working, but for now it solves my problem.
Any better solution to the issue is welcome!