I'm trying to call an action with an ajax-beginform.
This is my model:
public class MyViewModel
{
public List<SubViewModel> SubViewModels {get;set;}
}
public class SubViewModel
{
public string Name {get;set;}
public int Age {get;set;}
public bool Active {get;set;}
}
My view looks like this: (I'm iterating over all SubViewModel-Items, and want to get those back later in my DoAction-Method)
@model MyViewModel
@using (Ajax.BeginForm("DoAction", "MyController", null, new AjaxOptions() { HttpMethod = "Post" }, new { @class = "search-form", enctype = "multipart/form-data" }))
{
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Active</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.SubViewModels)
{
<tr>
<td><input type="text" name="Name" value="@item.Name" /></td>
<td><input type="text" name="Age" value="@item.Age" /></td>
<td><input type="checkbox" name="Active" value="@item.Active" /></td>
</tr>
}
</tbody>
</table>
<input type="submit" value="OK" />
}
And this is my action:
[System.Web.Mvc.HttpPost]
public async Task DoAction([FromBody] MyViewModel model)
{
// here model is null
}
It always hits the breakpoint in DoAction but:
MyViewModel, the property SubViewModels is null.IEnumerable<SubViewModel>, the model is null.SubViewModel, the first dataset is in parameter.So I guess, the right parameter for this ajax-action is from type SubViewModel.
But I need either MyViewModel or IEnumerable<SubViewModel> to get all listed models items.
You need to name your inputs such that the modelbinder can bind the post data appropriately. As you have it now, every single item in the list is posted via the same property names: Name, Age, and Active. What you actually need are names like SubViewModels[N].Name, where N is an integer index value. The easiest way to do this to actually use the HTML helpers to generate your inputs, and you'll also need to use a for loop, rather than foreach:
@for (var i = 0; i < Model.SubViewModels.Count(); i++)
{
<tr>
<td>@Html.TextBoxFor(m => m.SubViewModels[i].Name)</td>
<td>@Html.TextBoxFor(m => m.SubViewModels[i].Age)</td>
<td>@Html.CheckBoxFor(m => m.SubViewModels[i].Name)</td>
</tr>
}