web-dev-qa-db-fra.com

Liaison JSON ASP.NET MVC 4 au modèle de vue - Erreur d'objet imbriqué

J'ai le problème avec la liaison json au modèle de vue. Voici mon code:

une partie de mes ViewModels (AddressViewModel a plus de propriétés):

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

            });
        });

En-tête du contrôleur:

[HttpPost]
 public ActionResult SaveAddress(AddressViewModel addressViewModel)

Voici ce que je vois avec Firebug:

enter image description here

Et voici ce que je vois dans VS:

enter image description here

Comme vous pouvez le voir, les propriétés Plain sont liées correctement, mais mon objet imbriqué (Country) est nul. J'ai lu beaucoup d'articles différents et je ne sais toujours pas ce que je fais mal. Aidez-moi s'il vous plaît!

15
Piotr Czarnecki

Le problème vient de votre paramètre de méthode d'action:

[HttpPost]
public ActionResult SaveAddress(AddressViewModel addressViewModel)

Lorsque vous utilisez JSON.stringify(), vous envoyez une chaîne à votre contrôleur, pas un objet! Donc, vous devez faire quelques travaux pour atteindre votre objectif:

1) Modifiez le paramètre de votre méthode d'action:

[HttpPost]
public ActionResult SaveAddress(string addressViewModel)

2) Désérialisez cette chaîne en un objet - c'est-à-dire AddressViewModel:

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

Ainsi, votre méthode d'action finale devrait être la suivante:

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

    // do what you want with your model object ...
}
17
Amin Saqi

Vous pouvez conserver votre ActionMethod existant sans avoir besoin de sérialiser json: Du côté client, créez un objet à partir de votre json:

JSON.parse(jsonData)

et l'envoyer dans la propriété de données $ .ajax.

Ou, au lieu de créer json, créez un objet:

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

Et encore une fois, envoyez cet objet dans la propriété de données $ .ajax.

18
graumanoz

En fait, la meilleure option consiste simplement à supprimer le

var addressData = JSON.stringify(jsonData);

ligne et envoyer jsonData lui-même. ASP.NET MVC le liera automatiquement s'il s'agit d'un objet réel et pas seulement d'une chaîne.

Rasoir d'Occam

3
Rap

Désolé de répondre pour l'ancien thread.ici, vous pourriez travailler avec JsonResult au lieu de ActionResult

c'est ta signature

 [HttpPost]
 public ActionResult SaveAddress(AddressViewModel addressViewModel)

ça devrait ressembler

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

l'avantage serait si vous utilisez JsonResult au lieu de ActionResult que vous n'avez pas besoin de Deserialize

voici le lien http://codeforcoffee.org/asp-net-mvc-intro-to-mvc-using-binding-json-objects-to-models/ à partir de ce lien, vous pouvez obtenir le idée.

2
Thomas

OU vous pouvez utiliser JsonConvert.DeserializeObject<>();

voici le code pour désérialiser le résultat JSON.stringify()

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

au lieu de

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