Reputation: 1989
I have a model with a property of type List. I use this property to show values on my view. I use a foreach loop to go through each item in the list and displaying them using DisplayFor and TextBoxFor. That part is working fine; I've used TextBoxFor before and any user entered text gets past to the model on submit. However, when using a list, the list is null when the form is submitted. All the other properties in the model are updated and I can access them correctly. What is preventing the list from binding and how can I fix this?
ModelInstrumentListingDetail
public class ModelInstrumentListingDetail
{
public int InstrumentTagID { get; set; }
public string InstrumentTagDescription { get; set; }
public List<ModelInstrumentListingItem> items { get; set; }
}
ModelInstrumentListingItem
public class ModelInstrumentListingItem
{
public string Field { get; set; }
public string Label { get; set; }
}
View
@model GPC.Models.ModelInstrumentListingDetail
@using (Html.BeginForm("InstrumentListingAdd", "Home", FormMethod.Post, new { id = "InstrumentListingDetailForm" }))
{
<table>
<tr>
<td>
@Html.TextBoxFor(m => m.InstrumentTagDescription)
</td>
</tr>
@foreach (GPC.Models.ModelInstrumentListingItem item in Model.items)
{
<tr>
<td>
@Html.DisplayFor(m => item.Label)
</td>
<td>
@Html.TextBoxFor(m => item.Field)
</td>
</tr>
}
</table>
<input id="submitInstrumentListingAdd" name="submitInstrumentListingAdd" value="Add" type="submit" class="SaveButton" />
}
Controller
[HttpPost]
public ActionResult InstrumentListingAdd(ModelInstrumentListingDetail model, string submitInstrumentListingAdd)
{
...
}
On submit, the model posted to the controller has InstrumentDescription with a value, but items is null. I need to figure out how to fill items with the new values.
Upvotes: 0
Views: 1139
Reputation: 12491
You should use either EditorTemplates
and EditorFor
helper or for
loop if you want to bind your list right. Here is an example.
If you will use for
loop it should be like this:
@for (int i = 0; i< Model.items.Count(); i++)
{
<tr>
<td>
@Html.DisplayFor(m => Model.items[i].Label)
</td>
<td>
@Html.TextBoxFor(m => Model.items[i].Field)
</td>
</tr>
}
for
loop - short way, but using EditorTemplate
- more clean solution, so I recommend it.
Upvotes: 1
Reputation: 29186
Change the loop like so:
@for(int idx = 0;idx < Model.items.Count;idx++)
{
<tr>
<td>
@Html.DisplayFor(_ => Model.items[idx].Label)
</td>
<td>
@Html.TextBoxFor(_ => Model.items[idx].Field)
</td>
</tr>
}
The reason this works is that the <input>
elements will be generated like so:
<input id="Items_0_" name="Items[0]" type="text" value="Foo">
<input id="Items_1_" name="Items[1]" type="text" value="Bar">
When you POST the data, something like the following will be in the body:
Items[0]:Foo
Items[1]:Bar
The default ASP.NET MVC model binder will pick these Items
up from the request body and apply them to the viewmodel, in your case ModelInstrumentListingDetail.items
Upvotes: 3
Reputation: 1656
I think I had a similar problem earlier.
Maybe try:
[HttpPost]
public ActionResult InstrumentListingAdd([Bind(Prefix = "item")]ModelInstrumentListingItem model, string submitInstrumentListingAdd)
{
...
}
Upvotes: 0