Una vista parziale che passa una raccolta utilizzando l’helper Html.BeginCollectionItem

Ho fatto un piccolo progetto per comprendere la risposta di Stephen Muecke qui: Invia la stessa vista parziale chiamata più volte i dati al controller?

Quasi tutto funziona. Javascript aggiunge nuovi campi dalla vista parziale e posso dire che sono legati al modello dai valori “temp” inseriti dal metodo controller per la vista parziale.

Tuttavia, quando invio i nuovi campi, il metodo AddRecord () genera un’eccezione che mostra che il modello non viene passato (“Riferimento dell’object non impostato su un’istanza di un object”).

Inoltre, quando visualizzo il sorgente della pagina, l’helper BeginCollectionItem sta inserendo un tag nascosto come dovrebbe intorno alla tabella nella vista principale che visualizza i record preesistenti, ma non attorno ai nuovi campi aggiunti dal javascript.

Che cosa sto facendo di sbagliato? Sono piuttosto nuovo in questo modo grazie per la vostra pazienza!

La mia opinione principale:

@model IEnumerable @using (Html.BeginForm("AddDetail", "CashRecipients", FormMethod.Post)) { @Html.AntiForgeryToken() 
}
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"); } }); }

La mia vista parziale:

 @model DynamicForm.Models.CashRecipient @using HtmlHelpers.BeginCollectionItem @using (Html.BeginCollectionItem("recipients")) { 
@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)
}

Il mio modello:

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

Nel mio controller:

 [HttpPost] [ValidateAntiForgeryToken] public ActionResult AddDetail([Bind(Include = "Id,cashAmount,recpientName")] IEnumerable 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); } 

    Innanzitutto, crea un modello di visualizzazione per rappresentare ciò che desideri modificare. cashAmount che cashAmount sia un valore monetario, quindi dovrebbe essere un decimale (aggiungi altri attributi di validazione e visualizzazione come richiesto)

     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; } } 

    Quindi creare una vista parziale (ad esempio) _Recipient.cshtml

     @model CashRecipientVM 
    @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) }

    e un metodo per restituire quello parziale

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

    Allora il tuo metodo GET principale sarà

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

    e il suo punto di vista sarà

     @model IEnumerable @using (Html.BeginForm()) { 
    foreach(var recipient in Model) { @Html.Partial("_Recipient", recipient) }
    }

    e includerà uno script per aggiungere l’html per un nuovo CashRecipientVM

     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); }); }); 

    e lo script per eliminare un elemento

     $('.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(); } }); 

    E il modulo invierà di nuovo a

     public ActionResult Create(IEnumerable recipients)