title: Correct way to edit and update complex viewmodel objects using asp.net-mvc2 and entity framework
body: <p>I have a table in my database with a one to many relationship to another table, which has a relationship to a third table:</p>
  
  <p>ParentObject</p>
  
  <ul>
  <li>ID
  <li>Name
  <li>Description
  </ul>
  
  <p>ChildObject</p>
  
  <ul>
  <li>ID
  <li>Name
  <li>Description
  <li>ParentObjectID
  <li>AnotherObjectID
  </ul>    
  
  <p>AnotherObject</p>
  
  <ul>
  <li>ID
  <li>Name
  </ul>
  
  <p>The objects are mapped into Entity Framework and exposed through a data access class.</p>
  
  <p>It seemed like ViewModels are recommended when the data to be displayed greatly differs from the domain object, so I created a ViewModel as follows:</p>
  
  <pre><code>public class ViewModel {
      public IList&lt;ParentObject&gt; ParentObjects { get; set; }
      public ParentObject selectedObject { get; set; }
      public IList&lt;ChildObject&gt; ChildObjects { get; set; }
  }
  </code></pre>
  
  <p>I have a view that displays a list of ParentObjects and when clicked will allow a ChildObject to be modified saved.    </p>
  
  <pre><code>&lt;% using (Html.BeginForm()) { %&gt; 
  &lt;table&gt;
      &lt;% foreach (var parent in Model.ParentObjects) { %&gt;
      &lt;tr&gt;
          &lt;td&gt;
              ObjectID [&lt;%= Html.Encode(parent.ID)%&gt;]
          &lt;/td&gt;
          &lt;td&gt;
              &lt;%= Html.Encode(parent.Name)%&gt;
          &lt;/td&gt;
          &lt;td&gt;
              &lt;%= Html.Encode(parent.Description)%&gt;
          &lt;/td&gt;
      &lt;/tr&gt;
      &lt;% } %&gt;
  &lt;/table&gt;
  &lt;% if (Model.ParentObject != null) { %&gt;
  &lt;div&gt;
      Name:&lt;br /&gt;
      &lt;%= Html.TextBoxFor(model =&gt; model.ParentObject.Name) %&gt;
      &lt;%= Html.ValidationMessageFor(model =&gt; model.ParentObject.Name, "*")%&gt;
  &lt;/div&gt;
  &lt;div&gt;
      Description:&lt;br /&gt;
      &lt;%= Html.TextBoxFor(model =&gt; model.ParentObject.Description) %&gt;
      &lt;%= Html.ValidationMessageFor(model =&gt; model.ParentObject.Description, "*")%&gt;
  &lt;/div&gt;
  &lt;div&gt;
      Child Objects
  &lt;/div&gt;
  &lt;% for (int i = 0; i &lt; Model.ParentObject.ChildObjects.Count(); i++) { %&gt;
      &lt;div&gt;
          &lt;%= Html.DisplayTextFor(sd =&gt; sd.ChildObjects[i].Name) %&gt;
      &lt;/div&gt;
      &lt;div&gt;
          &lt;%= Html.HiddenFor(sd =&gt; sd.ChildObjects[i].ID )%&gt;
          &lt;%= Html.TextBoxFor( sd =&gt; sd.ChildObjects[i].Description) %&gt;
          &lt;%= Html.ValidationMessageFor(sd =&gt; sd.ChildObjects[i].Description, "*") %&gt;
      &lt;/div&gt;
      &lt;% }
  }
  } %&gt;  
  </code></pre>
  
  <p>This all works fine.  My question is around the best way to update the EF objects and persist the changes back to the database.  I initially tried:</p>
  
  <pre><code>[HttpPost]
      public ActionResult Edit(ViewModel viewModel) {
          ParentObject parent = myRepository.GetParentObjectByID(viewModel.SelectedObject.ID);
  
          if ((!ModelState.IsValid)
              || !TryUpdateModel(parent, "SelectedObject", new[] { "Name", "Description" })) {
              || !TryUpdateModel(parent.ChildObjects, "ChildObjects", new[] { "Name", "Description" })) {
  
  
              //Code to handle failure and return the current model snipped
  
              return View(viewModel);
          }
  
          myRepository.Save();
  
          return RedirectToAction("Edit");
      }
  </code></pre>
  
  <p>When I try to save a change to the child object, I get this exception: Entities in 'MyEntities.ChildObject' participate in the 'FK_ChildObject_AnotherObject' relationship. 0 related 'AnotherObject' were found. 1 'AnotherObject' is expected. </p>
  
  <p>Investigation on StackOverflow and general googling led me to <a href="http://www.codetuning.net/blog/post/Binding-Model-Graphs-with-ASPNETMVC.aspx" rel="nofollow noreferrer">this blog post</a> that seems to describe my problem: TryUpdateModel() does not correctly handle nested collections.  Apparently, (and stepping through the debugger confirms this) it creates a new ChildObject instead of associating with the EF objects from my instantiated context.</p>
  
  <p>My hacky work around is this:</p>
  
  <pre><code>if (viewModel.ChildObjects.Count &gt; 0) {
      foreach (ChildObject modelChildObject in viewModel.ChildObjects) {
          ChildObject childToUpdate = ParentObject.ChildObject.Where(a =&gt; a.ID == modelChildObject.ID).First();
          childToUpdate.Name = modelChildObject.Name;
      }
  }
  </code></pre>
  
  <p>This seems to work fine.  My question to you good folks: Is there a correct way to do this?  I tried following the suggestion for making a custom model binder per the blog link I posted above but it didn't work (there was an issue with reflection, the code expected certain properties to exist) and I needed to get something going ASAP.</p>
  
  <p>PS - I tried to cleanup the code to hide specific information, so beware I may have hosed something up. I mainly just want to know if other people have solved this problem.</p>