So I've read many of the questions already about this and can't seem to find a correlation. I have a view model that consists of another model with several collections of - you guessed it - more models:
Public Class FeeTemplateViewModel
Public Property FeeSetup As FeeSetupModel
Public Property TemplateId As Integer
Public Property Name As String
Public Property CompanyId As Integer
Public Property GroupId As Integer
Public Property Users As Integer
Public Property CreateDate As DateTime
Public Property Modified As DateTime
Public Property CreatedBy As String
End Class
Public Class FeeSetupModel
<DisplayName("Office Id")>
Property OfficeId() As String
<DisplayName("Office Name")>
Property OfficeName() As String
<DisplayName("Current Fees")>
Property CurrentFees() As IEnumerable(Of FeeItemModel)
<DisplayName("Minimum Preparer Fee")>
Public Property MinPFee As Decimal
Public Property AvailableFees As List(Of FeeListItem)
Public Property CustomFees As List(Of CustomFee)
End Class
When I post back to the controller from the view, FeeSetup
is null and I can't determine why.
Controller:
<HttpPost()>
Function Edit(model As FeeTemplateViewModel) As ActionResult
ModelState.Clear()
If String.IsNullOrEmpty(model.Name) Then
ModelState.AddModelError("Name", "Template name is required")
End If
If Not ModelState.IsValid Then
Return View("Edit", model)
End If
Save(model)
Return View("Edit")
End Function
ModelState error:
{"The parameter conversion from type 'System.String' to type 'ProAvalon.Models.Configuration.FeeSetupModel' failed because no type converter can convert between these types."}
View:
@Using Html.BeginForm("Edit", "FeeTemplate", Nothing, FormMethod.Post, Nothing)
@<div>
@Html.HiddenFor(Function(m) m.FeeSetup)
@If Model.TemplateId > 0 Then
@<p><strong>Last Modified:</strong>@Model.Modified.ToLocalTime</p>
End If
<div class="inputsection col-md-14" id="options">
<div class="row">
<div>
@Html.LabelFor(Function(m) m.Name, "Template Name")
@Html.EditorFor(Function(m) m.Name, "TemplateName")
</div>
</div>
@Html.ValidationMessageFor(Function(m) m.Name)
<div style="height:50px;line-height:50px;">
<div id="status-bar" style="display:none">
<span style="font-size:16px; margin-left:5px; font-weight:bold; color: #333;" />
</div>
</div>
<div class="clearfix" />
<div id="fee-grid-wrapper" style="min-height:500px;">
<table id="fee-grid" class="table table-striped table-condensed table-bordered table-fixed-header">
<thead>
<tr class="alert-info">
<th style="border:none;vertical-align:top;text-transform:uppercase;">
<strong>Filter Forms</strong>
</th>
<th style="border: none; vertical-align: top;" colspan="3">
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-12" style="padding:0 5px">
<input name="filter" type="radio" checked="checked" data-filter="" /> All forms
</div>
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-12" style="padding:0 5px">
<input name="filter" type="radio" data-filter="fd" /> Federal Forms <br />
<input name="filter" type="radio" id="state-forms" /> State Forms
<div style="display:none" id="state-form-picker" class="state-picker">
@Html.DropDownListFor(Function(m) i, ProAvalon.PageHelpers.StateSelectList)
</div>
</div>
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-12" style="padding:0 5px" id="search-target">
</div>
</th>
</tr>
<tr style="background:#eee">
<th style="cursor:pointer">No.</th>
<th style="cursor:pointer">Fed/St</th>
<th style="cursor:pointer">Form/Schedule Name</th>
<th style="cursor:pointer">Amount</th>
</tr>
</thead>
<tfoot>
<tr style="background:#eee">
<th>No.</th>
<th>Fed/St</th>
<th>Form/Schedule Name</th>
<th style="min-width:300px">Amount</th>
</tr>
</tfoot>
<tbody>
@If Model.FeeSetup.AvailableFees IsNot Nothing Then
For Each fee In Model.FeeSetup.AvailableFees
@Html.HiddenFor(Function(m) fee)
@Code
Dim tmp As ProAvalon.Models.Configuration.FeeItemModel = Model.FeeSetup.CurrentFees.Where(Function(x) x.FormName = fee.FormName).FirstOrDefault()
Dim amount = 0D
If (tmp IsNot Nothing) Then amount = tmp.FeeAmount
i = i + 1
Html.HiddenFor(Function(m) tmp)
End Code
@<tr data-id="@(fee.FormName)">
<td>@(i) </td>
<td>@(IIf(fee.FormType = "FD", fee.FormType, IIf(fee.FormType = "BS", fee.FormState + "-BS", fee.FormState)))</td>
<td>@(fee.FormDesc)</td>
<td style="min-width:300px">
<span style="display:none">@amount</span> @*to enable sorting*@
@Html.TextBoxFor(Function(m) amount)
@*@(New HtmlString("<span>" + _
Html.TextBox("Amount_" + fee.FormName.ToString(), CType(amount, Decimal), _
New With {.class = "pull-left currency_input currencyTB amount_" + fee.FormName}).ToHtmlString() + _
"<span id=""msg_" + fee.FormName + """ style='display:none; line-height:35px;padding-left:10px;'></span></span>"))*@
</td>
</tr>
Next
End If
</tbody>
</table>
</div>
</div>
</div>
@<br />
@<div>
<hr />
<div class="float-right" style="margin-left: 20pt">
@Html.SubmitButton()
</div>
<div>
@Html.CancelButton("Index", "FeeTemplate")
</div>
<div class="clear clearfix" />
</div>
End Using
I'm going to feel like a real jerk if one of you looks at this and finds a naming overlap, but I've looked through it several times and cannot determine that to be the cause.
To begin, list binding does not work on this:
You'll need to look through it using an
index
: