我正在尝试将Steve Sanderson's blog post用于将集合项绑定到模型。但是,我看到一些奇怪的行为,我在帖子或其他讨论中找不到答案。
在我的模型BankListMaster
中,我有一个单独模型ICollection
的{{1}}个对象。 BankAgentId
和BankListMaster
在我们的SQL数据库中具有一对多关系。
我在BankListAgentId
页面上遇到了这个问题。当页面加载时,我们当前与正在处理的Edit
项关联的三个代理ID正确加载。但是,如果我点击“保存”,我会看到BankListMaster
对象(ICollection
)有三个项目,但每个相应的字段都包含bankListAgentId
值。
如果我选择null
,那么按照blog post上的说明,Ajax会调用部分视图,该视图会正确附加到表中。
现在,如果我点击“保存”,我会看到Add another
对象计数增加了一个项目,计数为4.所有最初使用ICollection
加载的项目都包含{ {1}}字段值,但新附加项的GET
和null
字段包含正确的信息(新项目的所有其他字段均为AgentId
)。
对于ASP MVC来说还是比较新的,所以我不确定发生了什么或者看什么方向。
以下是主视图中的表单。我在使用和不使用StateCode
项目的情况下尝试了此操作并获得了相同的结果。
null
这是局部视图。我再次尝试使用和不使用@Html.Hidden
项并获得相同的结果。
@model Monet.Models.BankListMaster
@{
ViewBag.Title = "Edit";
}
<fieldset>
<legend>Stat(s) Fixed</legend>
<table id="fixedRows">
<thead>
<tr>
<th>State Code</th>
<th>Agent ID</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
@for (int i = 0; i < Model.Fixed.Count; i++)
{
using (Html.BeginCollectionItem("BankListAgentId"))
{
@Html.HiddenFor(m => Model.Fixed[i].BankID)
@Html.HiddenFor(m => Model.Fixed[i].TableId)
@Html.HiddenFor(m => Model.Fixed[i].FixedOrVariable)
<tr>
<td>
@Html.DropDownListFor(m => Model.Fixed[i].StateCode,
(SelectList)ViewBag.StateCodeList, Model.Fixed[i].StateCode)
</td>
<td>
@Html.TextBoxFor(m => Model.Fixed[i].AgentId)
@Html.ValidationMessageFor(m => Model.Fixed[i].AgentId)
</td>
<td>
<a href="javascript:void(0)" class="deleteRow">delete</a>
</td>
@*<td><a href="#" onclick="$('#item-@Model.AgentId').parent().remove();" style="float:right;">Delete</a></td>*@
</tr>
}
}
</tbody>
</table>
<br />
<a href="javascript:void(0)" class="addFixed">Add Another</a>
</fieldset>
这是Ajax调用
@Html.Hidden
这是调用局部视图的控制器方法
@model Monet.Models.BankListAgentId
@{
Layout = null;
}
@using (Html.BeginCollectionItem("BankListAgentId"))
{
@Html.HiddenFor(model => model.TableId)
@Html.HiddenFor(model => model.BankID)
@Html.HiddenFor(model => model.FixedOrVariable)
<tr>
<td>
@Html.DropDownListFor(model => model.StateCode,
(SelectList)ViewBag.StateCodeList, Model.StateCode)
</td>
<td>
@Html.EditorFor(model => model.AgentId)
@Html.ValidationMessageFor(model => model.AgentId)
</td>
<td>
<a href="javascript:void(0)" class="deleteRow">delete</a>
</td>
@*<td><a href="#" onclick="$('#item-@Model.AgentId').parent().remove();" style="float:right;">Delete</a></td>*@
</tr>
}
这是$(document).ready(function () {
$(".addFixed").click(function () {
$.ajax({
url: '@Url.Action("BlankFixedRow", "BankListMaster")',
dataType: 'html',
cache: false,
success: function (html) {
$("#fixedRows > tbody").append('<tr>' + html + '</tr>');
}
});
});
});
型号
public ViewResult BlankFixedRow()
{
SelectList tmpList = new SelectList(new[] { "AL", "AK", "AS", "AZ", "AR", "CA", "CO", "CT", "DE", "DC", "FM", "FL", "GA", "GU", "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MH", "MD", "MA", "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ", "NA", "NM", "NY", "NC", "ND", "MP", "OH", "OK", "OR", "PW", "PA", "PR", "RI", "SC", "SD", "TN", "TX", "UT", "US", "VT", "VI", "VA", "WA", "WV", "WI", "WY" });
ViewBag.StateCodeList = tmpList;
return View("FixedPartialView", new BankListAgentId());
}
这是BankListMaster
模型
public partial class BankListMaster
{
public BankListMaster()
{
this.BankListAttachments = new HashSet<BankListAttachments>();
this.BankListAgentId = new HashSet<BankListAgentId>();
}
public int ID { get; set; }
public string BankName { get; set; }
public string LastChangeOperator { get; set; }
public Nullable<System.DateTime> LastChangeDate { get; set; }
public virtual ICollection<BankListAttachments> BankListAttachments { get; set; }
public virtual ICollection<BankListAgentId> BankListAgentId { get; set; }
}
这是从帖子上的表单通过fiddler发送回控制器的内容。索引为1,2和3的项目是最初从数据库中提取的项目。最后一项是通过jQuery / Ajax调用添加到局部视图的。
答案 0 :(得分:1)
我的解决方案是:html.beginCollectionItem中使用的所有内容都必须在局部视图中。 所以你的解决方案可能是这样的:
主视图
@model Monet.Models.BankListMaster
@{
ViewBag.Title = "Edit";
}
<fieldset>
<legend>Stat(s) Fixed</legend>
<table id="fixedRows">
<thead>
<tr>
<th>State Code</th>
<th>Agent ID</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
@for (int i = 0; i < Model.Fixed.Count; i++)
{
@Html.Partial("name", item)
}
</tbody>
</table>
<br />
<a href="javascript:void(0)" class="addFixed">Add Another</a>
</fieldset>
部分视图“名称”
@model Monet.Models.BankListMaster
using (Html.BeginCollectionItem("BankListAgentId"))
{
@Html.HiddenFor(m => Model.Fixed[i].BankID)
@Html.HiddenFor(m => Model.Fixed[i].TableId)
@Html.HiddenFor(m => Model.Fixed[i].FixedOrVariable)
<tr>
<td>
@Html.DropDownListFor(m => Model.Fixed[i].StateCode,
(SelectList)ViewBag.StateCodeList, Model.Fixed[i].StateCode)
</td>
<td>
@Html.TextBoxFor(m => Model.Fixed[i].AgentId)
@Html.ValidationMessageFor(m => Model.Fixed[i].AgentId)
</td>
<td>
<a href="javascript:void(0)" class="deleteRow">delete</a>
</td>
@*<td><a href="#" onclick="$('#item-@Model.AgentId').parent().remove();" style="float:right;">Delete</a></td>*@
</tr>
}
这不是完整的解决方案,但你必须这样做,它对我有用。 希望这会有所帮助!
答案 1 :(得分:0)
我在几个小时内遇到了类似的问题。当我的项目集合(Choices)包含多个项目时,它将返回null。但是,就像你一样,我的数据看起来很好:
{
"QuestionTemplateId":"1",
"Position":"0",
"CardId":"1",
"Label":"Question#1",
"AdminComments":"",
"Type":"ComboBox",
"ModelType":"MyProject.Areas.DGM.Models.ViewModels.Controls.ComboBoxViewModel",
"ComboQuestionId":"1",
"Choices.Index": ["dc0e6eea-5a8e-4971-8f9f-4d6e1c290300","52f2b780-c21e-4633-b880-bdff5d815eaf"],
"Choices[dc0e6eea-5a8e-4971-8f9f-4d6e1c290300].Label":"Choice #1",
"Choices[dc0e6eea-5a8e-4971-8f9f-4d6e1c290300].Score":"4",
"Choices[52f2b780-c21e-4633-b880-bdff5d815eaf].Label":"Choice #2",
"Choices[52f2b780-c21e-4633-b880-bdff5d815eaf].Score":"7"
}
然后我意识到我的问题可能与数据POST有关。当用户提交表单时,我会进行以下AJAX
调用:
$("#questionForm").on('submit', function () {
if ($(this).valid()) {
var data = $(this).serializeObject(); // from here: http://stackoverflow.com/a/1186309/2835243
$.ajax({
type: 'POST',
url: this.action,
contentType: 'application/json',
data: JSON.stringify(data) // this is what generated the above JSON
});
}
}
似乎为我解决的问题是将数据作为x-www-form-urlencoded
(jQuery的AJAX的默认contentType
)而不是json
发送。所以我改变了我的AJAX调用以下内容:
$.ajax({
type: 'POST',
url: this.action,
data: $(this).serialize()
});