在我的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) {
}
});
}
我将不胜感激任何帮助。感谢
答案 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>
}
}