MVC在表单提交后从视图返回填充的模型

时间:2013-04-23 10:42:45

标签: c# asp.net-mvc razor

我的模特:

 public class SendFileDeviceViewModel
  {
    public SendFileDeviceViewModel()
    {
      PolicyList = new List<SendFileDevicePoliciesViewModel>();
    }
    public string DeviceName { get; set; }
    public int DeviceId { get; set; }
    public string ManagementGroupName { get; set; }
    public int ManagementGroupId { get; set; }
    public bool ReloadConfiguration { get; set; }
    public bool ImmediateSend { get; set; }
    public DateTime TimeToSend { get; set; }
    public List<SendFileDevicePoliciesViewModel> PolicyList { get; set; }
  }
  public class SendFileDevicePoliciesViewModel
  {
    public int PackageTemplateId { get; set; }
    public string PolicyName { get; set; }
    public string PolicyType { get; set; }
    public string DefinedAt { get; set; }
    public bool ResendPolicy { get; set; }
  }

我的观点:

<h2>Send files to a Device @Model.DeviceName</h2>
  <h3>Reload configuration settings</h3>
  @Html.CheckBoxFor(m => m.ReloadConfiguration) @Html.LabelFor(m => m.ReloadConfiguration)
  <h3>Select the policies to reload</h3>
  @using (Html.BeginForm())
  {

    @Html.HiddenFor(m => m.DeviceId)
    @Html.HiddenFor(m => m.ManagementGroupId)

    @Html.ValidationSummary(true)

    if (Model.PolicyList.Count() > 0)
    {
    <table>
      <caption>
        Policies available for this device</caption>
      <thead>
        <tr>
          <th scope="col">
            &nbsp;
          </th>
          <th scope="col">
            Policy Name
          </th>
          <th scope="col">
            Policy Type
          </th>
          <th scope="col">
            Defined At
          </th>
        </tr>
      </thead>
      <tbody>
        @foreach (var policies in Model.PolicyList)
        {
          <tr>
            @*<td>@Html.CheckBox("PackageTemplateId", new { value = policies.PackageTemplateId })</td>*@
            <td>@Html.CheckBoxFor(m => policies.ResendPolicy)</td>
            <td>@policies.PolicyName</td>
            <td>@policies.PolicyType</td>
            <td>@policies.DefinedAt</td>
          </tr>
        }
      </tbody>
    </table>
    }

    <div class="editor-label">
      @Html.LabelFor(m => m.ImmediateSend)
    </div>
    <div class="editor-field">
      @Html.CheckBoxFor(m => m.ImmediateSend)
    </div>

    <div class="editor-label">
      @Html.LabelFor(m => m.TimeToSend)
    </div>
    <div class="editor-field">
      @Html.EditorFor(m => m.TimeToSend)
    </div>
    <p>
      <input type="submit" value="Send files" /></p>

我的问题是从控制器检索模型时,PolicyList始终为空。我在这里错过了一些简单的东西吗?

2 个答案:

答案 0 :(得分:5)

两个问题:

您的第一个问题是您正在构造函数中重置列表,因此当发布表单并且模型绑定器实例化模型的实例时,您将重新设置列表。如果列表为null,则将其更改为合并以仅重新分配:

public SendFileDeviceViewModel()
{
    PolicyList = PolicyList ?? new List<SendFileDevicePoliciesViewModel>();
}

您的下一个问题是foreach。为了正确索引name属性(因此模型绑定器可以执行此操作),您需要使用for循环。另外,请将Id保存在HiddenFor

尝试使用此代替foreach

@for (int i = 0; i < Model.PolicyList.Count; i++)
{
    <tr>
        <td>
            @Html.HiddenFor(m => m.PolicyList[i].PackageTemplateId)
            @Html.CheckBoxFor(m => m.PolicyList[i].ResendPolicy)
        </td>
        <td>@Model.PolicyList[i].PolicyName</td>
        <td>@Model.PolicyList[i].PolicyType</td>
        <td>@Model.PolicyList[i].DefinedAt</td>
    </tr>
}

答案 1 :(得分:3)

原因是您不尊重输入字段的naming convention。您应该使用foreach循环或自定义编辑器模板替换视图中的for循环:

<tbody>
    @for (var i = 0; i < Model.PolicyList.Count; i++)
    {
        <tr>
            <td>@Html.CheckBoxFor(x => x.PolicyList[i].ResendPolicy)</td>
            <td>@Html.DisplayFor(x => x.PolicyList[i].PolicyName)</td>
            <td>@Html.DisplayFor(x => x.PolicyList[i].PolicyType)</td>
            <td>@Html.DisplayFor(x => x.PolicyList[i].DefinedAt)</td>
        </tr>
    }
</tbody>

此外,现在只会绑定ResendPolicy属性,因为这是唯一具有相应输入字段的属性(在您的情况下为复选框)。如果你想绑定其他的,你可能需要包含相应的隐藏字段:

<tbody>
    @for (var i = 0; i < Model.PolicyList.Count; i++)
    {
        <tr>
            <td>
                @Html.HiddenFor(x => x.PolicyList[i].PackageTemplateId)
                @Html.CheckBoxFor(x => x.PolicyList[i].ResendPolicy)
            </td>
            <td>
                @Html.HiddenFor(x => x.PolicyList[i].PolicyName)
                @Html.DisplayFor(x => x.PolicyList[i].PolicyName)
            </td>
            <td>
                @Html.HiddenFor(x => x.PolicyList[i].PolicyType)
                @Html.DisplayFor(x => x.PolicyList[i].PolicyType)
            </td>
            <td>
                @Html.HiddenFor(x => x.PolicyList[i].DefinedAt)
                @Html.DisplayFor(x => x.PolicyList[i].DefinedAt)
            </td>
        </tr>
    }
</tbody>