ASP.NET MVC 4 JSON Binding to the View Model - Nested object error

Piotr Czarnecki picture Piotr Czarnecki · Aug 22, 2013 · Viewed 45.3k times · Source

I have got the problem with json binding to the view model. Here is my code:

part of my ViewModels (AddressViewModel has more properties):

public class AddressViewModel
{
        [Display(Name = "Address_Town", ResourceType = typeof(Resources.PartyDetails))]
        public string Town { get; set; }

        [Display(Name = "Address_Country", ResourceType = typeof(Resources.PartyDetails))]
        public Country Country { get; set; }
}

public class Country : EntityBase<string>
{
        public string Name { get; set; }

        protected override void Validate()
        {
            if (string.IsNullOrEmpty(Name))
            {
                base.AddBrokenRule(new BusinessRule("CountryName", "Required"));
            }
        }
}

Javascript:

$(document).on("click", "#addAddress", function () {
            var jsonData = {
                "Town": $('#txt-Town').val(),
                "District": $('#txt-District').val(),
                "Street": $('#txt-Street').val(),
                "PostCode": $('#txt-PostCode').val(),
                "FlatNumber": $('#txt-FlatNumber').val(),
                "PremiseName": $('#txt-PremiseName').val(),
                "PremiseNumber": $('#txt-Premisenumber').val(),
                "Country": {
                    "Name": $('#txt-Country').val(),
                }
            };
            var addressData = JSON.stringify(jsonData);
            $.ajax({
                url: '/Customer/SaveAddress',
                type: "POST",
                dataType: "json",
                contentType: "application/json; charset=utf-8",
                data: addressData,
                success: function (result) {
                    $("#addIndividualAddressDialog").data("kendoWindow").close();
                },
                error: function (result) {
                    alert("Failed");
                }

            });
        });

Header of controller:

[HttpPost]
 public ActionResult SaveAddress(AddressViewModel addressViewModel)

This is what I see with firebug:

enter image description here

And this is what I see in VS:

enter image description here

As you can see Plain properties are binded correct but my nested object (Country) is null. I read a lot of different articles and I still don't know what I'm doing wrong. Help me please!

Answer

Amin Saqi picture Amin Saqi · Aug 22, 2013

The problem is from your action method parameter:

[HttpPost]
public ActionResult SaveAddress(AddressViewModel addressViewModel)

As you use JSON.stringify(), you send a string to your controller, not an object! So, you need to do some works to achive your goal:

1) Change your action method parametter:

[HttpPost]
public ActionResult SaveAddress(string addressViewModel)

2) Deserialize that string to an object - that is AddressViewModel:

IList<AddressViewModel> modelObj = new 
JavaScriptSerializer().Deserialize<IList<AddressViewModel>>(addressViewModel);

So, your final action method should be like the following:

[HttpPost]
public ActionResult SaveAddress(string addressViewModel)
{
    IList<AddressViewModel> modelObj = new 
    JavaScriptSerializer().Deserialize<IList<AddressViewModel>>(addressViewModel);

    // do what you want with your model object ...
}