Complex Nested Partial View Ajax Post to MVC 5 Controller

131
November 22, 2016, at 10:34 AM

TL;DR: I just need to figure out why i can't serialize() the partial view's parent div and receive the model. Coding this out manually will take forever as there are many parent partials I'd have to use the same logic on.

More info: I've tried EditorTemplate for binding purposes, but unfortunately there is no easy way to use them as variable lists as far as I've searched.

Begin:

Models

public class ContactModel 
{                
    public List<ContactDetailModel> Contacts { get; set; }
    ....

public class ContactDetailModel
{
    public ContactView Contact { get; set; }
    public PhoneModel PhoneModel { get; set; }
    ...
public class PhoneModel
{
    public int ContactId { get; set; }
    public int IsPrimaryPhoneNumberId { get; set; }
    public List<PhoneView> Phones { get; set; }
    public List<EmailPhoneTypeView> EmailPhoneTypes { get; set; }
...

To select & post inputs from just this partial view, I've implemented a variable class, and its relative template prefix to keep the MVC binding for the partial view.

@{
 var phoneClass = "phone" + @Model.Contacts[index].Contact.ContactId;
 var phoneTemplatePrefix = "Contacts[" + index + "].PhoneModel";
 }

This is ran inside of a loop, increasing indexes as needed to keep binding.

<div class="@phoneClass">
     @Html.Partial("_ContactPhone", Model.Contacts[index].PhoneModel, new ViewDataDictionary() { TemplateInfo = new TemplateInfo() { HtmlFieldPrefix = phoneTemplatePrefix } })
</div>

The partial I'm attempting to post. (Strongly Typed partial for PhoneModel)

@{var addNavigationClass = "AddContactPhone" + Model.ContactId;}
for (var phoneIndex = 0; phoneIndex < Model.Phones.Count(); phoneIndex++)
{
    @Html.HiddenFor(model => model.Phones[phoneIndex].ContactPhoneId)
    @Html.DropDownListFor...
    @Html.TextBoxFor(model => model.Phones[phoneIndex].PhoneNumber)
    <a href="#" class="removeMemberPhone">Trash</a>
    @Html.RadioButtonFor(model => model.IsPrimaryPhoneNumberId, Model.Phones[phoneIndex].ContactPhoneId) Primary</label>
}

Inside the View's click function

var model = $('.phone' + '@Model.ContactId' + ' :input').serialize();
console.log('model', model);
$.ajax({
   url: '/Contact/AddPhone',
   type: 'POST',
   data: model,
   success: function (data) {
     console.log(data.length);
    }
    ....

The log's output

model Contacts%5B1%5D.PhoneModel.Phones%5B0%5D.ContactPhoneId=3907&Contacts%5B1%5D.PhoneModel.Phones%5B0%5D.EmailPhoneTypeId=1&..........

My model never has any values in my controller (I've abbreviated ContactPhoneModel to PhoneModel in the above code)...

Answer 1

This is more pseudo code than actual code, you will need to tidy this up a bit.

Since you aren't posting back the full page, it seems overkill to jump through the Mvc model binders hoops when binding to a collection. If it was me doing this, I'd alter your click handler to the following:

var model = {};
$('.phone' + '@Model.ContactId' + ' :input').each(function(){
    model[/[^\.]+$/.exec($(this).prop("name"))[0]] = $(this).val();
};
console.log('model', model);
$.ajax({
   url: '/Contact/AddPhone',
   type: 'POST',
   data: model,
   contentType: "application/json; charset=UTF-8",
   success: function (data) {
      console.log(data.length);
    }

I would look at using editortemplates as mentioned in the comments, they will take some of the pain away of managing indexes and the like

Answer 2

Here's a bit of (unrefined, and early) code that I've written, that will take properly formatted serializeArray() data and re base the arrays for a good post to the MVC controller.

Top 2 lines will show how to call it once in your project.

READ ALSO
How to get selected Text Value in choosen.js dropdown list

How to get selected Text Value in choosen.js dropdown list

I have a problem in my dropdown list using choosen. js.

122
How to refresh the page upon successful submission using angularJS

How to refresh the page upon successful submission using angularJS

Hi how to refresh an html page upon successful submission?[nnn] I've tried as follows, but its not working. .

100