1

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)...

enter image description here

9
  • You should be using EditorTemplates not partials to ensure your form controls are correctly named. Your view appears to be based on ContactModel but you posting back ContactPhoneModel so the names of your form data do not match the names of your model properties so it cannot be bound Commented Oct 9, 2015 at 4:44
  • You also have a property public PhoneModel PhoneModel but I assume that's supposed to be public ContactPhoneModel PhoneModel? Commented Oct 9, 2015 at 4:46
  • @StephenMuecke As i've stated above EditorTemplates won't work for the variable type list I'm implementing with this view. Also I'm aware of the Model name differences I've tried to abbreviate them, and wil edit the post to fix them. Commented Oct 9, 2015 at 4:47
  • This certainly does not :) And you should be using an EditorTemplate. The model in your view is ContactPhoneModel which mean your form data needs to be ContactPhoneId=3907 not Contacts[1].PhoneModel.Phones[0].ContactPhoneId=3907 which would never work anyway since indexers must start at zero and be consecutive. Commented Oct 9, 2015 at 4:51
  • @StephenMuecke I'm just saying I've had no luck finding a way to update an editor template with an additional phoneModel (recommended on many of the stack's posts, is the partial view). The log returned Contacts[1] as it is the second contact that i clicked on to add the phoneModel too. Commented Oct 9, 2015 at 4:56

2 Answers 2

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

Sign up to request clarification or add additional context in comments.

1 Comment

That's actually really cool, and I've tested this out, and 'modified' works as far as only this partial goes, however binding any parenting 'partial' model will get increasingly harder just managing the code to grab the data, using this methodology. I appreciate the time you took for the reply and the code.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.