2013-08-22 28 views
12

Tôi gặp vấn đề với json liên kết với mô hình khung nhìn. Đây là mã của tôi:ASP.NET MVC 4 JSON Binding vào Model View - Lỗi đối tượng lồng nhau

phần của ViewModels của tôi (AddressViewModel có nhiều thuộc tính):

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

      }); 
     }); 

Tiêu đề của bộ điều khiển:

[HttpPost] 
public ActionResult SaveAddress(AddressViewModel addressViewModel) 

Đây là những gì Tôi thấy bằng firebug:

enter image description here

Và đây là những gì tôi nhìn thấy trong VS:

enter image description here

Như bạn có thể thấy một trang thuộc đồng bằng được binded đúng nhưng đối tượng lồng nhau của tôi (Quốc gia) là null. Tôi đọc rất nhiều bài báo khác nhau và tôi vẫn không biết mình đang làm gì sai. Làm ơn giúp tôi với!

Trả lời

16

Vấn đề là từ tham số phương pháp hành động của bạn:

[HttpPost] 
public ActionResult SaveAddress(AddressViewModel addressViewModel) 

Khi bạn sử dụng JSON.stringify(), bạn gửi một chuỗi để điều khiển của bạn, không phải là một đối tượng! Vì vậy, bạn cần phải làm một số công trình để đạt được mục tiêu của bạn:

1) Thay đổi hành động của bạn phương pháp parametter:

[HttpPost] 
public ActionResult SaveAddress(string addressViewModel) 

2) Deserialize rằng chuỗi đến một đối tượng - đó là AddressViewModel:

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

Vì vậy, phương pháp hành động cuối cùng của bạn sẽ giống như sau:

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

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

Sau khi thay đổi tiêu đề hành động và ít thay đổi trong javascript, nó hoạt động! –

+7

Đây không thực sự là một giải pháp thành ngữ vì nó sẽ bỏ qua khả năng xác nhận và ràng buộc của MVC. Một giải pháp tốt hơn là thêm một JsonModelBinder và đặt logic deserialization này vào đó. Nếu có thể được thực hiện bằng cách ghi đè một vài phương thức trong DefaultModelBinder –

+0

Nếu các giá trị của bạn nằm trong một 'biểu mẫu', chỉ cần tuần tự hóa chúng và gửi chúng với ajax có' contentType' của 'application/x-www-form-urlencoded; charset = UTF-8'. Nếu không, chỉ cần bọc các trường nhập của bạn với một 'form action =" javascript: void (0); ">' để bạn có thể tuần tự hóa biểu mẫu với câu lệnh [jQuery $ .serialize()] (https: //api.jquery .com/serialize /) và sử dụng làm trọng tải của yêu cầu. –

17

bạn có thể giữ cựu của bạn isting ActionMethod hoang sơ mà không cần json serializing: Ở phía client tạo một đối tượng từ json của bạn:

JSON.parse(jsonData) 

và gửi trong các tài sản dữ liệu $ .ajax.

Hoặc, thay vì tạo json, tạo ra một đối tượng:

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

Và một lần nữa, gửi đối tượng đó trong các tài sản dữ liệu $ .ajax.

+4

đây là câu trả lời đúng cho câu hỏi này. không cần phải sửa đổi mã phía máy chủ của bạn, chỉ cần gửi đúng loại đối tượng mà nó mong đợi từ máy khách. – TugboatCaptain

1

HOẶC bạn có thể sử dụng JsonConvert.DeserializeObject<>();

Sau đây là đoạn code để deserialize JSON.stringify() kết quả

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

thay vì

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

Thực ra lựa chọn tốt nhất chỉ là để loại bỏ các

var addressData = JSON.stringify(jsonData); 

dòng và gửi jsonData chính nó. ASP.NET MVC sẽ tự động liên kết nó nếu nó là một đối tượng thực tế và không chỉ là một chuỗi.

Occam's Razor

2

Xin lỗi vì đã trả lời cho cũ thread.here bạn có thể làm việc với JsonResult thay vì ActionResult

đây là chữ ký của bạn

[HttpPost] 
public ActionResult SaveAddress(AddressViewModel addressViewModel) 

nó sẽ giống như

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

quảng cáo thuận lợi sẽ là nếu bạn sử dụng JsonResult thay vì ActionResult rằng u không cần phải Deserialize

đây là liên kết http://codeforcoffee.org/asp-net-mvc-intro-to-mvc-using-binding-json-objects-to-models/ từ liên kết này bạn có thể lấy ý tưởng.

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