title: MVC5 Parent Child Single Edit Form
body: <p>I am trying to have single page for editing and creating record with parent and child data.</p>
  
  <p>Like a page to add employee record along with his list of experiences.
  Sample: <a href="https://i.stack.imgur.com/VHNd9.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/VHNd9.png" alt="enter image description here"></a></p>
  
  <p><strong>It works fine except when user deletes 1st child record while in edit page.</strong></p>
  
  <ul>
  <li>When we open page in edit mode, and add new experiences, it is fine.</li>
  <li>when we open page in edit mode, and delete experience records at index 4,5 or any other than 0, it is fine</li>
  <li>when we open page in edit mode, and delete experience records at index 0, it is generates error saying in experience is null</li>
  </ul>
  
  <p>Controller Code for Employee:</p>
  
  <pre><code>public class EmployeeController : Controller
  {
      private DBEntities db = new DBEntities();
  
      // GET: Employee/Create
      public ActionResult Create()
      {
          ViewBag.caste_id = new SelectList(db.tbl_caste, "caste_id", "caste_name");
          ViewBag.emp_grade = new SelectList(db.tbl_grade, "grade_id", "grade_title");
          ViewBag.emp_position_title = new SelectList(db.tbl_position, "id", "position");
          ViewBag.emp_project_name = new SelectList(db.tbl_project, "id", "project_name");
          return View();
      }
  
  
      // POST: Employee/Create
      // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
      // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
      [HttpPost]
      [ValidateAntiForgeryToken]
      public ActionResult Create(employee employee)
      {
          if (ModelState.IsValid)
          {
              db.employee.Add(employee);
              db.SaveChanges();
              return RedirectToAction("Index");
          }
  
          ViewBag.caste_id = new SelectList(db.tbl_caste, "caste_id", "caste_name", employee.caste_id);
          ViewBag.emp_grade = new SelectList(db.tbl_grade, "grade_id", "grade_title", employee.emp_grade);
          ViewBag.emp_position_title = new SelectList(db.tbl_position, "id", "position", employee.emp_position_title);
          ViewBag.emp_project_name = new SelectList(db.tbl_project, "id", "project_name", employee.emp_project_name);
          return View(employee);
      }
  
      // GET: Employee/Edit/5
      public ActionResult Edit(int? id)
      {
          if (id == null)
          {
              return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
          }
          employee employee = db.employee.Find(id);
          if (employee == null)
          {
              return HttpNotFound();
          }
          ViewBag.caste_id = new SelectList(db.tbl_caste, "caste_id", "caste_name", employee.caste_id);
          ViewBag.emp_grade = new SelectList(db.tbl_grade, "grade_id", "grade_title", employee.emp_grade);
          ViewBag.emp_position_title = new SelectList(db.tbl_position, "id", "position", employee.emp_position_title);
          ViewBag.emp_project_name = new SelectList(db.tbl_project, "id", "project_name", employee.emp_project_name);
          return View(employee);
      }
  
      // POST: Employee/Edit/5
      // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
      // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
      [HttpPost]
      [ValidateAntiForgeryToken]
      public ActionResult Edit(employee employee)
      {
          if (ModelState.IsValid)
          {
              //For some reason children are brought in with Parent_Id = null.
              //Manually resetting it fixes this issue.
              //Needs to be set before parent = modified for referential integrity
              int cnt = 0;
              if(employee.tbl_experience != null)
              {
                  foreach (var c in employee.tbl_experience)
                  {
                      c.employeeid = employee.employeeid;
                      if (!(c.exp_id &gt; 0))
                      {
                          c.exp_id = cnt;
                          cnt--;
                      }
                  }
              }
              db.Entry(employee).State = EntityState.Modified;
  
              //Remove deleted child
              //employee.tbl_experience.Where(m =&gt; m.).ToList().ForEach(m =&gt; p.Children.Remove(m));
              List&lt;tbl_experience&gt; childToDelete = db.tbl_experience.Where(item =&gt; item.employeeid == employee.employeeid).ToList();
              foreach (var item in childToDelete)
              {
                  if (employee.tbl_experience.IndexOf(item) &gt; 0)
                  {
                      db.Entry(item).State = EntityState.Deleted;
                  }
              }
              //db.Entry(childToDelete).State = EntityState.Deleted;
  
              for (int i = 0; i &lt; employee.tbl_experience.Count; i++)
              {
  
                      db.Entry(employee.tbl_experience[i]).State = employee.tbl_experience[i].exp_id &gt; 0 ? EntityState.Modified : EntityState.Added;
                  //}
              }
              db.SaveChanges();
  
              return RedirectToAction("Index");
          }
          ViewBag.caste_id = new SelectList(db.tbl_caste, "caste_id", "caste_name", employee.caste_id);
          ViewBag.emp_grade = new SelectList(db.tbl_grade, "grade_id", "grade_title", employee.emp_grade);
          ViewBag.emp_position_title = new SelectList(db.tbl_position, "id", "position", employee.emp_position_title);
          ViewBag.emp_project_name = new SelectList(db.tbl_project, "id", "project_name", employee.emp_project_name);
          return View(employee);
      }
  }
  </code></pre>
  
  <p>Code of Edit View:</p>
  
  <pre><code>@model App.Models.employee
  
  @{
      ViewBag.Title = "Edit";
  }
  
  &lt;h2&gt;Edit&lt;/h2&gt;
  
  
  @using (Html.BeginForm())
  {
      @Html.AntiForgeryToken()
  
      &lt;div class="form-horizontal"&gt;
          &lt;h4&gt;employee&lt;/h4&gt;
          &lt;hr /&gt;
          @Html.ValidationSummary(true, "", new { @class = "text-danger" })
          @Html.HiddenFor(model =&gt; model.employeeid)
  
          &lt;div class="form-group"&gt;
              @Html.LabelFor(model =&gt; model.emp_no, htmlAttributes: new { @class = "control-label col-md-2" })
              &lt;div class="col-md-10"&gt;
                  @Html.EditorFor(model =&gt; model.emp_no, new { htmlAttributes = new { @class = "form-control" } })
                  @Html.ValidationMessageFor(model =&gt; model.emp_no, "", new { @class = "text-danger" })
              &lt;/div&gt;
          &lt;/div&gt;
  
          &lt;div class="form-group"&gt;
              @Html.LabelFor(model =&gt; model.emp_name, htmlAttributes: new { @class = "control-label col-md-2" })
              &lt;div class="col-md-10"&gt;
                  @Html.EditorFor(model =&gt; model.emp_name, new { htmlAttributes = new { @class = "form-control" } })
                  @Html.ValidationMessageFor(model =&gt; model.emp_name, "", new { @class = "text-danger" })
              &lt;/div&gt;
          &lt;/div&gt;
  
  
          &lt;div class="form-group"&gt;
              &lt;div class="col-md-offset-2 col-md-10"&gt;
                  &lt;input type="submit" value="Save" class="btn btn-default" /&gt;
              &lt;/div&gt;
          &lt;/div&gt;
          &lt;div class="form-group"&gt;
              &lt;div class="col-md-12"&gt;
      &lt;h3&gt;Experience List &lt;input type="button" value="add" id="addExp" /&gt;&lt;/h3&gt;
      &lt;table class="table"&gt;
          &lt;tr&gt;
              &lt;th&gt;@Html.LabelFor(model =&gt; model.tbl_experience.ElementAt(0).exp_organization)&lt;/th&gt;
              &lt;th&gt;@Html.LabelFor(model =&gt; model.tbl_experience.ElementAt(0).exp_position)&lt;/th&gt;
              &lt;th&gt;@Html.LabelFor(model =&gt; model.tbl_experience.ElementAt(0).exp_fromyear)&lt;/th&gt;
              &lt;th&gt;@Html.LabelFor(model =&gt; model.tbl_experience.ElementAt(0).exp_toyear)&lt;/th&gt;
              &lt;th&gt;&amp;nbsp;&lt;/th&gt;
          &lt;/tr&gt;
              @for (int i = 0; i &lt; Model.tbl_experience.Count; i++)
              {
                  &lt;tr class="item"&gt;
                      &lt;td&gt;
                          @Html.HiddenFor(model =&gt; model.tbl_experience.ElementAt(i).exp_id, new { @Name = string.Format("tbl_experience[{0}].exp_id", i) })
                          @Html.TextBoxFor(model =&gt; model.tbl_experience.ElementAt(i).exp_organization, new { @Name = string.Format("tbl_experience[{0}].exp_organization", i) })
                          @Html.ValidationMessageFor(model =&gt; model.tbl_experience.ElementAt(i).exp_organization)
                      &lt;/td&gt;
                      &lt;td&gt;
                          @Html.TextBoxFor(model =&gt; model.tbl_experience.ElementAt(i).exp_position, new { @Name = string.Format("tbl_experience[{0}].exp_position", i) })
                          @Html.ValidationMessageFor(model =&gt; model.tbl_experience.ElementAt(i).exp_position)
                      &lt;/td&gt;
                      &lt;td&gt;
                          @Html.TextBoxFor(model =&gt; model.tbl_experience.ElementAt(i).exp_fromyear, new { @Name = string.Format("tbl_experience[{0}].exp_fromyear", i) })
                          @Html.ValidationMessageFor(model =&gt; model.tbl_experience.ElementAt(i).exp_fromyear)
                      &lt;/td&gt;
                      &lt;td&gt;
                          @Html.TextBoxFor(model =&gt; model.tbl_experience.ElementAt(i).exp_toyear, new { @Name = string.Format("tbl_experience[{0}].exp_toyear", i) })
                          @Html.ValidationMessageFor(model =&gt; model.tbl_experience.ElementAt(i).exp_toyear)
                      &lt;/td&gt;
                      &lt;td&gt;
                          &lt;a href="#" class="rem"&gt;Delete&lt;/a&gt;
                      &lt;/td&gt;
                  &lt;/tr&gt;
              }
          &lt;tbody id="expTable"&gt;
  
          &lt;/tbody&gt;
      &lt;/table&gt;
          &lt;/div&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  }
  
  &lt;div&gt;
      @Html.ActionLink("Back to List", "Index")
  &lt;/div&gt;
  
  @section Scripts {
      @Scripts.Render("~/bundles/jqueryval")
      &lt;script&gt;
          last = @Model.tbl_experience.Count;
          $('#addExp').click(function () {
              var newRow = '&lt;tr class="item"&gt;&lt;input type="hidden" name="tbl_experience[' + last + '].exp_id" value="0"&gt;';
              newRow += '&lt;td class="col"&gt;&lt;input type="text" name="tbl_experience[' + last + '].exp_organization"&gt;&lt;/td&gt;';
              newRow += '&lt;td class="col"&gt;&lt;input type="text" name="tbl_experience[' + last + '].exp_position"&gt;&lt;/td&gt;';
              newRow += '&lt;td class="col"&gt;&lt;input type="text" name="tbl_experience[' + last + '].exp_fromyear"&gt;&lt;/td&gt;';
              newRow += '&lt;td class="col"&gt;&lt;input type="text" name="tbl_experience[' + last + '].exp_toyear"&gt;&lt;/td&gt;';
              newRow += '&lt;td class="col"&gt;&lt;a href="#" class="rem"&gt;Rem&lt;/a&gt;&lt;/td&gt;';
              newRow += '&lt;/tr&gt;';
  
              $('#expTable').append(newRow);
              last++;
          });
          $(document).on('click', '.item .rem', function (e) {
              //console.log('removed');
              e.preventDefault();
              $(this).closest('.item').remove();
          });
  
      &lt;/script&gt;
  }
  </code></pre>