I can't figure out why this won't work. Everything I've read (both here and across the web) says this is how to bind to a list for editing but I'm not having any success. I have two problems:
The HTML form elements emitted by the view are not being indexed (each one is named "Qty" and "BoxID" instead of "[0].Qty" and "[0].BoxID"). Everything I've read on this subjuct says the HTML.EditorFor and HiddenFor helpers should pick this up automatically.
Even when I manually change the view to spit out the correct HTML (form elements with the right names) model binding isn't happening correctly and the collection parameter in the controller action method is null.
Any ideas? Am I doing something wrong?
Here's the view:
@ModelType IEnumerable(of HonorBox)
@Code
ViewData("Title") = "Index"
End Code
<h2>Index</h2>
@Html.BeginForm("Index", "HonorBoxes")
@Html.AntiForgeryToken()
@For x = 0 To Model.Count - 1
@<tr>
<td>
@Html.DisplayFor(Function(i) Model(x).BoxID)
@Html.HiddenFor(Function(i) Model(x).BoxID)
</td>
<td>
@Html.TextBoxFor(Function(i) Model(x).Qty)
@Html.ValidationMessageFor(Function(i) Model(x).Qty)
</td>
</tr>
Next
And these are the controller methods:
Function Index() As ActionResult
Dim hb = From h In db.honorBoxes Select h Where Not h.Filled And Not h.Hold
Return View(hb.ToList())
End Function
<HttpPost>
Function Index(boxes As IEnumerable(Of HonorBox)) As ActionResult
If ModelState.IsValid Then
For Each box In boxes
Dim cbox = db.honorBoxes.Find(box.BoxID)
If Not IsDBNull(box.Qty) AndAlso cbox.Qty <> box.Qty Then
cbox.Qty = box.Qty
cbox.Filled = True
End If
Next
db.SaveChanges()
End If
Return RedirectToAction("Index")
End Function
Finally here's the model
Public Class HonorBox
<Key> Public Property BoxID As Integer
Public Property AssetID As Nullable(Of Integer)
Public Property Asset As Asset
Public Property BoxType As String
Public Property Hold As Nullable(Of Boolean)
Public Property Filled As Nullable(Of Boolean)
Public Property Qty As Nullable(Of Integer)
End Class