2012-03-19 17 views
8

Problemy z pobieraniem ASP.NET MVC3 w celu powiązania mojego złożonego obiektu JSON zawierającego listę.MVC3 Complex JSON List Binding

Oto struktura, którą mam dla moich obiektów.

public class PageModel 
{ 
    public PageModel() { } 
    public CustomObject1 CustomObject { get; set; } 
    public IEnumerable<CustomObject2> Objects { get; set; } 

} 

public class CustomObject1 
{ 
    public CustomObject1() { } 
    [Required] 
    public int CustomId1 { get; set; } 
    public string CustomName { get; set; } 
} 

public class CustomObject2 
{ 
    public CustomObject2() { } 
    [Required] 
    public int Custom2Id { get; set; } 
    public CustomObject3 SubItem { get; set; } 
    public int SubItemId { get; set; } 
} 

Można zakładać CustomObject3 ma podobną strukturę - nie ma potrzeby powielać kolejną utworzoną klasę, więc postać można użyć wyobraźni :)

Oto kod JavaScript/jQuery sprawia, że ​​wywołanie POST (zakładamy cały JS prowadzące do tego zapewnia prawidłowe dane):

//$obj1 has all data for the first object 
var firstObj = { }; 
firstObj.CustomId1 = $obj1.Id; 
firstObj.CustomName = $obj1.Name; 

var i = 0; 

//$objects is an array with all the data 
$.each($objects, function() { 
    objsArray[i] = { 
    Custom2Id: $(this).Id, 
    SubItemId: $(this).itemId 
    }; 

    ++i; 
}); 

$.ajax({ 
    type: 'POST', 
    url: '/Action/Method', 
    data: { CustomObject: firstObj, Objects: objsArray }, 
    //Success/error handlers here 
}); 

i wreszcie (wiem, sporo code) oto przegląd sposobu mam:

public class ActionController : Controller { 
    public JsonResult Method(PageModel model) { 
     //Gets here - model.CustomObject is filled correctly, and model.Objects has a correct count of whatever data I passed to the method - but all of the properties are empty! 
    } 
} 

Tak jak powiedziałem, pierwszy obiekt jest wypełniony i wszystkie dane są tam, kiedy debuguję i przechodzę. Jeśli przekażę dwa obiekty w tablicy Objects w obiekcie JSON, widzę w sterowniku Count, ale Custom2Id i SubItemId są puste. Co daje?

Kiedy określam contentType z w moim zgłoszeniu $.ajax, MVC skarży się na przekazane dane. Spróbowałem również podzielić parametr model w metodzie MVC na dwa oddzielne parametry, ale to nie pomaga.

Każda pomoc jest bardzo doceniana - ta osoba mnie zaskoczyła!

Odpowiedz

5

więc rozwiązanie tego konkretnego problemu jest połączenie dwóch lub więcej rozwiązań gdzie indziej na SO (jeden z nich może być odpowiedź Jakuba obracające się wokół wykorzystania rodzajowego typu Collection - IEnumerable - w przeciwieństwie do bardziej konkretny jeden - List).

Po pierwsze, kod po stronie serwera nie musi być zmieniany - wszystko jest dobrze z przodu. Wszystkie zmiany, które należy wprowadzić, to strona klienta, a konkretnie w jaki sposób jQuery i JavaScript przesyłają dane do wspomnianego serwera.

Oto stary Javascript:

$.ajax({ 
    type: 'POST', 
    url: '/Action/Method', 
    data: { CustomObject: firstObj, Objects: objsArray }, 
    //Success/error handlers here 
}); 

Pierwszy problem jest to, że JavaScript nie jest informowanie serwera na '/Action/Method' co dokładnie jesteś wysyłanie (jest to binarny, jest to mieszanka parametrów, czy to JSON?), więc dodawanie linii contentType: 'application/json' będzie służyć temu celowi. Gdy to zrobisz, serwer wie, że musi zdekodować JSON ...

Ale tak, jak by to było teraz, dekodowanie zakończyłoby się niepowodzeniem z wyrzuceniem wyjątku ("Invalid JSON primitive") zanim kod wejdzie w twoją metodę (MVC obsługuje wtedy dekodowanie i wiązanie). W powyższym wywołaniu AJAX budowałem nowy obiekt JSON w opcjach $.ajax, ale wysyłany JSON nie przekazał walidatora JSON (James Kyburz wspomina o wielkim walidatorze JSON: JSONLint Validator). Zamiast tego utwórz obiekt JSON przed wywołaniem $.ajax i poddaj go ciągowi, aby był w odpowiednim formacie JSON. Podsumowując, oto co wywołanie AJAX powinna wyglądać następująco:

var dataObj = { CustomObject: firstObj, Objects: objsArray }; 

$.ajax({ 
    type: 'POST', 
    url: '/Action/Method', 
    contentType: 'application/json', 
    data: JSON.stringify(dataObj), 
    //Success/error handlers here 
}); 
+0

to bardzo pomogło :)! – Rookian

+0

Po godzinach szukania w pełni funkcjonalnego kodu rozwiązało to mój problem! Dzięki!! –

3

Zmień public IEnumerable<CustomObject2> Objects { get; set; } do List<CustomObject2>

model spoiwo nie wie, jak utworzyć instancję IEnumerable interfejs, potrzebuje czegoś bardziej konkretnego.

Należy również zmienić:

data: { CustomObject: firstObj, Objects: objsArray }

do

data: { model: { CustomObject: firstObj, Objects: objsArray } }

model część pasuje do nazwy parametru w swoim działaniu.

+0

Grałem około z tym - 'IEnumerable',' IList', 'List' wszystko produkować takie same wyniki - listę z prawidłową liczbą obiektów, które nie ma żadnych wartości. – Mattygabe

+0

Nie zgadzam się z twoją drugą częścią - chociaż może to pomóc w niektórych przypadkach, MVC3 jest wystarczająco inteligentny, aby zauważyć, że dane, które do niego przesyłam, należą do mojego parametru "model". Rozwiązanie robocze, które opisałem powyżej, nie określa dodatkowej warstwy obiektu, aby uspokoić MVC - jest w stanie rozpoznać, co robię. – Mattygabe