部分视图使用Html.BeginCollectionItem帮助器传递集合

我做了一个小的项目,在这里理解Stephen Muecke的答案:将相同的部分视图称为多次数据给控制器?

几乎一切正常。 javascript从Partial View中添加了新的字段,我可以通过控制器方法为partial视图插入“temp”值来告诉它们绑定到模型。

但是,当我提交新的字段时,AddRecord()方法会抛出一个exception,显示模型没有被传入(“对象引用未设置为对象的实例”)。

此外,当我查看页面源代码时,BeginCollectionItem帮助程序正在插入隐藏标记,因为它应该围绕主视图中的表格显示预先存在的logging,而不是围绕javascript添加的新字段。

我究竟做错了什么? 我很新,所以感谢您的耐心!

我的主要观点:

@model IEnumerable<DynamicForm.Models.CashRecipient> @using (Html.BeginForm("AddDetail", "CashRecipients", FormMethod.Post)) { @Html.AntiForgeryToken() <div id="CSQGroup"> </div> } <div> <input type="button" value="Add Field" id="addField" onclick="addFieldss()" /> </div> <script> function addFieldss() { //alert("ajax call"); $.ajax({ url: '@Url.Content("~/CashRecipients/RecipientForm")', type: 'GET', success:function(result) { //alert("Success"); var newDiv = document.createElement("div"); var newContent = document.createTextNode("Hi there and greetings!"); newDiv.appendChild(newContent); newDiv.innerHTML = result; var currentDiv = document.getElementById("div1"); document.getElementById("CSQGroup").appendChild(newDiv); }, error: function(result) { alert("Failure"); } }); } </script> 

我的部分观点:

 @model DynamicForm.Models.CashRecipient @using HtmlHelpers.BeginCollectionItem @using (Html.BeginCollectionItem("recipients")) { <div class="editor-field"> @Html.LabelFor(model => model.Id) @Html.LabelFor(model => model.cashAmount) @Html.TextBoxFor(model => model.cashAmount) @Html.LabelFor(model => model.recipientName) @Html.TextBoxFor(model => model.recipientName) </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="Save" class="btn btn-default" /> </div> </div> } 

我的模特:

 public class CashRecipient { public int Id { get; set; } public string cashAmount { get; set; } public string recipientName { get; set; } } 

在我的控制器中:

 [HttpPost] [ValidateAntiForgeryToken] public ActionResult AddDetail([Bind(Include = "Id,cashAmount,recpientName")] IEnumerable<CashRecipient> cashRecipient) { if (ModelState.IsValid) { foreach (CashRecipient p in cashRecipient) { db.CashRecipients.Add(p); } db.SaveChanges(); return RedirectToAction("Index"); } return View(cashRecipient); } public ActionResult RecipientForm() { var data = new CashRecipient(); data.cashAmount = "temp"; data.recipientName = "temp"; return PartialView(data); } 

首先创build一个视图模型来表示你想要编辑的内容。 我假设cashAmount是一个货币值,因此应该是一个小数(根据需要添加其他validation和显示属性)

 public class CashRecipientVM { public int? ID { get; set; } public decimal Amount { get; set; } [Required(ErrorMessage = "Please enter the name of the recipient")] public string Recipient { get; set; } } 

然后创build一个局部视图(比如说) _Recipient.cshtml

 @model CashRecipientVM <div class="recipient"> @using (Html.BeginCollectionItem("recipients")) { @Html.HiddenFor(m => m.ID, new { @class="id" }) @Html.LabelFor(m => m.Recipient) @Html.TextBoxFor(m => m.Recipient) @Html.ValidationMesssageFor(m => m.Recipient) @Html.LabelFor(m => m.Amount) @Html.TextBoxFor(m => m.Amount) @Html.ValidationMesssageFor(m => m.Amount) <button type="button" class="delete">Delete</button> } </div> 

以及返回该部分的方法

 public PartialViewResult Recipient() { return PartialView("_Recipient", new CashRecipientVM()); } 

那么你的主要的GET方法将会是

 public ActionResult Create() { List<CashRecipientVM> model = new List<CashRecipientVM>(); .... // add any existing objects that your editing return View(model); } 

其观点将是

 @model IEnumerable<CashRecipientVM> @using (Html.BeginForm()) { <div id="recipients"> foreach(var recipient in Model) { @Html.Partial("_Recipient", recipient) } </div> <button id="add" type="button">Add</button> <input type="submit" value="Save" /> } 

并将包括一个脚本来添加一个新的CashRecipientVM的HTML

 var url = '@Url.Action("Recipient")'; var form = $('form'); var recipients = $('#recipients'); $('#add').click(function() { $.get(url, function(response) { recipients.append(response); // Reparse the validator for client side validation form.data('validator', null); $.validator.unobtrusive.parse(form); }); }); 

和脚本来删除一个项目

 $('.delete').click(function() { var container = $(this).closest('.recipient'); var id = container.find('.id').val(); if (id) { // make ajax post to delete item $.post(yourDeleteUrl, { id: id }, function(result) { container.remove(); }.fail(function (result) { // Oops, something went wrong (display error message?) } } else { // It never existed, so just remove the container container.remove(); } }); 

然后表单会回传给

 public ActionResult Create(IEnumerable<CashRecipientVM> recipients)