在asp.net mvc 4中回发后没有绑定到模型的对象列表

时间:2015-03-09 18:17:42

标签: jquery asp.net-mvc asp.net-mvc-4

在我的MVC 4应用程序中,我有一个可以拥有多个站点并且可以订阅多个服务包的客户。我的视图模型的简短版本如下所示

public class SubscriptionModel
{        
    public int MemberId { get; set; }
    public List<SitePackage> SitePackges { get; set; }
    public SubscriptionModel()
    {
        SitePackges=new List<SitePackage>();
    }
}

public class SitePackage
{
    public int SiteId { get; set; }
    public List<PackageDisplayItem> LstPackageDisplayItems { get; set; }
    public SitePackage()
    {
        LstPackageDisplayItems=new List<PackageDisplayItem>();

    }
}

public class PackageDisplayItem
{
    public int PackageId { get; set; }

    [Display(Name = "Package")]
    public string Name { get; set; }        

    [DataType(DataType.Date)]
    [Display(Name = "Start Date")]
    public DateTime? StartDate { get; set; }

}

在我的控制器中,我填写模型,然后传递给View Model进行渲染

 @using (@Html.BeginForm("CalculateCost", "HelpDesk", FormMethod.Post, new { @class = "form", id = "PackageSubscription", name = "PackageSubscription" }))
 {
 @Html.HiddenFor(x=>x.MemberId)

 <table class="table">
  @foreach (var site in Model.SitePackges)
  {
    <input name="SiteId" id="SiteId" type="hidden" value=@site.SiteId.ToString() />
           <tr><td class="col-sm-3">@site.SiteId</td></tr>
           <tr>
               <th class="col-sm-3">
                   Name
               </th>

               <th class="col-sm-2">
                   Start Date
               </th>
           </tr>
           @Html.Partial("_Packages",site.LstPackageDisplayItems)               

       }

我的部分观点就像

@model List<PackageDisplayItem>

@for (int i = 0; i < Model.Count; i++)
{
    @Html.HiddenFor(x => x[i].PackageId)
    <tr id="@Model[i].PackageId">
        <td>
            @Html.DisplayFor(x => x[i].Name)
        </td>

        <td>
            @Html.TextBoxFor(x => x[i].StartDate, "{0:d MMM yyyy}", new { @class = "jquery_datepicker form-control", autocomplete = "off" })
        </td>
    </tr>

}

每件事情都很好,但在表单上,​​模型绑定器不绑定SitePackges列表,其计数始终为0.我的控制器具有以下签名。

[HttpPost]
    public ActionResult CalculateCost(SubscriptionModel subscriptionModel )
    {
        var receivedModel = subscriptionModel;         
    }

不确定我设计的模型是否是处理此要求的最佳方法(要求是显示单个网站,下方显示包,然后显示第二个网站和包等)。控件似乎生成了唯一的索引。

Jquery Post

function SubmitForm() {
console.log($("#PackageSubscription").serialize());
$.ajax({
    url: '/HelpDesk/CalculateCost',
    cache: false,
    dataType: 'json',
    data: $("#PackageSubscription").serialize(),
    type: 'POST',
    success: function (data) {
    }

});

}

我将不胜感激任何帮助。感谢

2 个答案:

答案 0 :(得分:11)

您当前的实现是渲染输入,如下所示:

<input ... name="[0].Name" .../>
<input ... name="[1].Name" .../>

但是为了绑定到你的模型,他们需要看起来像这样:

<input ... name="SitePackges[0].LstPackageDisplayItems[0].Name" .../>
<input ... name="SitePackges[0].LstPackageDisplayItems[1].Name" .../>
<input ... name="SitePackges[1].LstPackageDisplayItems[0].Name" .../>
<input ... name="SitePackges[1].LstPackageDisplayItems[1].Name" .../>

A :您需要在嵌套for循环中呈现控件

for(int i = 0; i < Model.SitePackges.Count; i++)
{
  @Html.HiddenFor(m => m.SitePackges[i].SiteId)
  for(int j = 0; j < Model.SitePackges[i].LstPackageDisplayItems.Count; j++)
  {
    @Html.TextBoxFor(m => m.SitePackges[i].LstPackageDisplayItems[j].Name)
  }
}

B :或为模型类型使用自定义 EditorTemplates

查看/共享/ EditorTemplates / SitePackage.cshtml

@model SitePackage
@Html.HiddenFor(m => m.SiteId)
@Html.EditorFor(m => m.LstPackageDisplayItems)

查看/共享/ EditorTemplates / PackageDisplayItem.cshtml

@model PackageDisplayItem
@Html.TextBoxFor(m => m.Name)

并在主视图中

@model SubscriptionModel
@using (@Html.BeginForm())
{
  @Html.HiddenFor(m => m.MemberId)
  @Html.EditorFor(m => m.SitePackges)
  <input type="submit" />
}

答案 1 :(得分:0)

我发现您需要在包含父级面板中的项目ID。

int pos = Model.Products.Count - 1;
for (int j = 0, a = Model.Products.Count; j < a; j++) {
    // I exclude the last one because the users is adding it 
    // and will be displayed in another section.  else causes problems
    if (j != pos) {  
    <div>
        @Html.HiddenFor(m => m.Products[j].Id)

        <span>
            @Html.DisplayTextFor(m => m.Products[j].Description)
            @Html.HiddenFor(m => m.Products[j].Description)
        </span>
        <span>
            @Html.DisplayTextFor(m => m.Products[j].Style)
            @Html.HiddenFor(m => m.Products[j].Style)
        </span>
    </div>
    }
}

以下
for (int j = 0, a = Model.Products.Count; j < a; j++) {
    if (j != pos) {
    <div>
        @Html.HiddenFor(m => m.Products[j].Id)
        @Html.HiddenFor(m => m.Products[j].Description)
        @Html.HiddenFor(m => m.Products[j].Style)
    </div>
    }
}

或者

for (int j = 0, a = Model.Products.Count; j < a; j++) {
    if (j != pos) {  
    <div>
        <span>
            @Html.HiddenFor(m => m.Products[j].Id)
        </span>

        <span>
            @Html.DisplayTextFor(m => m.Products[j].Description)
            @Html.HiddenFor(m => m.Products[j].Description)
        </span>
        <span>
            @Html.DisplayTextFor(m => m.Products[j].Style)
            @Html.HiddenFor(m => m.Products[j].Style)
        </span>
    </div>
    }
}