2013-08-22 29 views
12

Mam problem z powiązaniem json z modelem widoku. Tu jest mój kodu:ASP.NET MVC 4 JSON Powiązanie z modelem widoku - błąd obiektu zagnieżdżonego

część moich ViewModels (AddressViewModel ma więcej właściwości):

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 kontrolera:

[HttpPost] 
public ActionResult SaveAddress(AddressViewModel addressViewModel) 

to co Widzę z firebug:

enter image description here

I to jest to, co widzę w VS:

enter image description here

Jak widać właściwości ślizgowe są zbindowanych poprawne, ale moja zagnieżdżony obiekt (kraj) jest nieważna. Czytałem wiele różnych artykułów i nadal nie wiem, co robię źle. Pomóż mi proszę!

Odpowiedz

16

Problem jest z parametrem metody działania:

[HttpPost] 
public ActionResult SaveAddress(AddressViewModel addressViewModel) 

Podczas korzystania JSON.stringify(), wysłać ciąg do kontrolera, a nie przedmiot! Tak, trzeba zrobić kilka prac do achive swój cel:

1) Zmień swoje działania metody parametter:

[HttpPost] 
public ActionResult SaveAddress(string addressViewModel) 

2) deserializowania ten ciąg do obiektu - czyli AddressViewModel:

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

Więc twój ostateczny sposób działania powinien być tak:

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

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

Po zmianie nagłówka akcji i niewielkich zmianach javascript działa! –

+7

To nie jest tak naprawdę idiomatyczne rozwiązanie, ponieważ ominie możliwości walidacji i wiązania MVC. O wiele lepszym rozwiązaniem jest dodanie JsonModelBinder i umieszczenie tam logiki deserializacji. Jeśli można to zrobić przez przesłonięcie kilku metod w DefaultModelBinder –

+0

Jeśli twoje wartości znajdują się wewnątrz 'formy', po prostu serializuj je i wysyłaj je z ajaxem o' contentType' z 'application/x-www-form-urlencoded; charset = UTF-8'. Jeśli nie, po prostu umieść swoje pola wejściowe za pomocą 'form action =" javascript: void (0); ">", aby można było przekształcić do postaci szeregowej na przykład [jQuery $ .serialize()] (https: //api.jquery .com/serialize /) i używać jako ładunku żądania. –

17

można zachować swój dawny isting ActionMethod nietknięte bez konieczności szeregowania json: Na stronie klienta utworzyć obiekt z json:

JSON.parse(jsonData) 

i wysłać który we właściwości danych $ .ajax.

Albo, zamiast tworzyć json, utworzenie obiektu:

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

I znowu wysłać ten obiekt we właściwości danych $ .ajax.

+4

to jest odpowiednia odpowiedź na to pytanie. nie ma potrzeby modyfikowania kodu po stronie serwera, wystarczy wysłać odpowiedni typ obiektu, którego oczekuje od klienta. – TugboatCaptain

1

lub można użyć JsonConvert.DeserializeObject<>();

Poniżej znajduje się kod do deserializowania wynikiem JSON.stringify()

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

zamiast

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

rzeczywiście najlepszym rozwiązaniem jest po prostu usunąć

var addressData = JSON.stringify(jsonData); 

linia i wyślij samą jsonData. ASP.NET MVC automatycznie je zwiąże, jeśli jest to rzeczywisty obiekt, a nie tylko ciąg.

Occam's Razor

2

Niestety odpowiedzieć za stary thread.here można pracować z JsonResult zamiast ActionResult

jest to Twoja sygnatura

[HttpPost] 
public ActionResult SaveAddress(AddressViewModel addressViewModel) 

powinno wyglądać

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

reklama Vantage będzie, jeśli używasz JsonResult zamiast ActionResult że u nie trzeba Deserialize

tu jest link http://codeforcoffee.org/asp-net-mvc-intro-to-mvc-using-binding-json-objects-to-models/ z tego linku można uzyskać pomysł.

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