MVC Model Binding with Dynamic Collection
<p>According to the seminal Scott Hanselman article on the complexities of the <a href="http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx" rel="noreferrer">ASP.NET Wire Format for Model Binding to Arrays, Lists, Collections, Dictionaries</a>:</p>

<blockquote>
  <p>We read in the properties by looking for <strong><code>parameterName[index].PropertyName</code></strong><br>
  The index must be zero-based and unbroke</p>
</blockquote>

<p>So this HTML:</p>

<pre class="lang-html prettyprint-override"><code>&lt;input type=&quot;text&quot; name=<b>&quot;People[0].FirstName&quot;</b> value=&quot;George&quot; /&gt;
&lt;input type=&quot;text&quot; name=<b>&quot;People[1].FirstName&quot;</b> value=&quot;Abraham&quot; /&gt;
&lt;input type=&quot;text&quot; name=<b>&quot;People[2].FirstName&quot;</b> value=&quot;Thomas&quot; /&gt;
</code></pre>

<p>Which will post like this:</p>

<p><img src="https://i.stack.imgur.com/ou0VH.png" alt="Post Data - People%5B0%5D.FirstName=George&amp;People%5B1%5D.FirstName=Abraham&amp;People%5B2%5D.FirstName=Thomas"></p>

<p>However, if I load a new person into my model over AJAX, I lose the context for building that person into the model and get the following output:</p>

<pre class="lang-html prettyprint-override"><code>&lt;input type=&quot;text&quot; name=<b>&quot;FirstName&quot;</b> value=&quot;New&quot; /&gt;
</code></pre>

<p><img src="https://i.stack.imgur.com/PcE5l.png" alt="Post Data - People%5B0%5D.FirstName=George&amp;People%5B1%5D.FirstName=Abraham&amp;People%5B2%5D.FirstName=Thomas&amp;FirstName=John"></p>

<p>Which won't get picked up by the model binder.</p>

<p><strong>Q</strong>: <em>How can I preserve the expression tree when dynamically adding new elements over AJAX?</em></p>

<h3>Here's an MVCE</h3>

<p><strong>Model: <code>/Model/Person.cs</code></strong></p>

<pre class="lang-cs prettyprint-override"><code>public class PersonViewModel
{
    public List&lt;Person&gt; People { get; set; }
}
public class Person
{
    public String FirstName { get; set; }
    public String LastName { get; set; }
}
</code></pre>

<p><strong>Controller: <code>Controllers/PersonController.cs</code></strong></p>

<pre class="lang-cs prettyprint-override"><code>[HttpGet]
public ActionResult Index()
{
    List&lt;Person&gt; people = new List&lt;Person&gt; {
        new Person { FirstName = "George" , LastName = "Washington"},
        new Person { FirstName = "Abraham" , LastName = "Lincoln"},
        new Person { FirstName = "Thomas" , LastName = "Jefferson"},
    };
    PersonViewModel model = new PersonViewModel() {People = people};
    return View(model);
}

[HttpPost]
public ActionResult Index(PersonViewModel model)
{
    return View(model);
}

public ActionResult AddPerson(String first, String last)
{
    Person newPerson = new Person { FirstName = first, LastName = last };
    return PartialView("~/Views/Person/EditorTemplates/Person.cshtml", newPerson);
}
</code></pre>

<p><strong>View: <code>Views/Person/Index.cshtml</code></strong></p>

<pre class="lang-html prettyprint-override"><code>@model PersonViewModel

@using (Html.BeginForm()) {
    &lt;table id="table"&gt;
        &lt;thead&gt;
            &lt;tr&gt;
                &lt;th&gt;@Html.DisplayNameFor(model =&gt; model.People.First().FirstName)&lt;/th&gt;
                &lt;th&gt;@Html.DisplayNameFor(model =&gt; model.People.First().LastName)&lt;/th&gt;
            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
            @for (int i = 0; i &lt; Model.People.Count; i++)
            {
                @Html.EditorFor(model =&gt; model.People[i])
            }
        &lt;/tbody&gt;
    &lt;/table&gt;

    &lt;input type="button" value="Add Person" id="add"/&gt;
    &lt;input type="submit" value="Save" /&gt;
}

&lt;script type="text/javascript"&gt;

    $("#add").click(function() {
        var url = "@Url.Action("AddPerson")?" + $.param({ first: "", last: "" });
        $.ajax({
            type: "GET",
            url: url,
            success: function(data) {
                $("#table tbody").append(data);
            }
        });
    });

&lt;/script&gt;
</code></pre>

<p><strong>View: <code>Views/Person/EditorTemplates/Person.cshtml</code></strong></p>

<pre class="lang-html prettyprint-override"><code>@model Person

&lt;tr&gt;
    &lt;td&gt;@Html.EditorFor(model =&gt; model.FirstName)&lt;/td&gt;
    &lt;td&gt;@Html.EditorFor(model =&gt; model.LastName)&lt;/td&gt;
&lt;/tr&gt;
</code></pre>

<p><strong>NOTE</strong>: There are other complexities when deleting an item that I'm not looking to address here per se.  I'd just like to add an element and know that it belongs in a nested context alongside other properties.</p>