ASP.NET MVC 4 JSON привязка к модели представления - ошибка вложенного объекта

У меня возникла проблема с привязкой json к модели представления. Вот мой код:

часть моих ViewModels (AddressViewModel имеет больше свойств):

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

            });
        });

Заголовок контроллера:

[HttpPost]
 public ActionResult SaveAddress(AddressViewModel addressViewModel)

Это то, что я вижу с помощью firebug:

enter image description here

И вот что я вижу в VS:

enter image description here

Как вы видите, свойства Plain привязаны правильно, но мой вложенный объект (Страна) имеет значение NULL. Я читал много разных статей, и я до сих пор не знаю, что я делаю неправильно. Помогите мне, пожалуйста!

Ответ 1

Проблема заключается в параметре метода действия:

[HttpPost]
public ActionResult SaveAddress(AddressViewModel addressViewModel)

Как вы используете JSON.stringify(), вы отправляете строку на свой контроллер, а не на объект! Итак, вам нужно сделать некоторые работы для достижения вашей цели:

1) Измените параметр метода действия:

[HttpPost]
public ActionResult SaveAddress(string addressViewModel)

2) десериализуем эту строку для объекта - это AddressViewModel:

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

Итак, ваш последний метод действий должен выглядеть следующим образом:

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

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

Ответ 2

Вы можете сохранить существующий ActionMethod без необходимости сериализации json: На стороне клиента создайте объект из вашего json:

JSON.parse(jsonData)

и отправить это значение в свойство $.ajax data.

Или, вместо создания json, создайте объект:

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

И снова отправьте этот объект в свойство $.ajax data.

Ответ 3

На самом деле лучшим вариантом является удаление

var addressData = JSON.stringify(jsonData);

и отправьте сам jsonData. ASP.NET MVC автоматически привяжет его, если это фактический объект, а не просто строка.

Оккамская бритва

Ответ 4

Извините, что ответили на старый thread.here, где вы могли бы работать с JsonResult вместо ActionResult

это ваша подпись

 [HttpPost]
 public ActionResult SaveAddress(AddressViewModel addressViewModel)

он должен выглядеть как

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

преимущество было бы, если вы используете JsonResult вместо ActionResult, что вам не нужно Deserialize

вот ссылка http://codeforcoffee.org/asp-net-mvc-intro-to-mvc-using-binding-json-objects-to-models/ по этой ссылке вы можете получить эту идею.

Ответ 5

ИЛИ вы можете использовать JsonConvert.DeserializeObject<>();

Ниже приведен код десериализации результата JSON.stringify()

IList<AddressViewModel> modelObj = JsonConvert.DeserializeObject<IList<AddressViewModel>>(addressViewModel);

вместо

JavaScriptSerializer().Deserialize<IList<AddressViewModel>>(addressViewModel);

Ответ 6

You must reference to Country object inside jsonData variable. The JSON POST binding will work correctly.

Old code:

    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(),
        }

New code:
    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(),
        }