Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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!

like image 691
Piotr Czarnecki Avatar asked Aug 22 '13 06:08

Piotr Czarnecki


4 Answers

You can keep your existing ActionMethod untouched without the need of json serializing: In the client side create an object from your json:

JSON.parse(jsonData)

and send that in the $.ajax data property.

Or, instead of creating json, create an object:

var dataObject = new Object();
dataObject.Town = $('#txt-Town').val();
dataObject.District = $('#txt-District').val();
...

And again, send that object in the $.ajax data property.

like image 76
graumanoz Avatar answered Nov 20 '22 20:11

graumanoz


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 ...
}
like image 34
Amin Saqi Avatar answered Nov 20 '22 20:11

Amin Saqi


Actually the best option is just to remove the

var addressData = JSON.stringify(jsonData);

line and send jsonData itself. ASP.NET MVC will auto-bind it if it is an actual object and not just a string.

Occam's Razor

like image 3
Rap Avatar answered Nov 20 '22 19:11

Rap


Sorry to answer for old thread.here you could work with JsonResult instead of ActionResult

this is your signature

 [HttpPost]
 public ActionResult SaveAddress(AddressViewModel addressViewModel)

it should look like

[HttpPost]
 public JsonResult SaveAddress(AddressViewModel addressViewModel)
 {
    return Json(status);
 }

the advantage would be if you use JsonResult instead of ActionResult that u do not need to Deserialize

here is the link http://codeforcoffee.org/asp-net-mvc-intro-to-mvc-using-binding-json-objects-to-models/ from this link you can get the idea.

like image 2
Thomas Avatar answered Nov 20 '22 19:11

Thomas