Próbuję wykonać prosty zwrot JSON, ale mam problemy, które mam poniżej.
public JsonResult GetEventData()
{
var data = Event.Find(x => x.ID != 0);
return Json(data);
}
Otrzymuję HTTP 500 z wyjątkiem pokazanym w tytule tego pytania. Ja też próbowałem
var data = Event.All().ToList()
To spowodowało ten sam problem.
Czy to błąd czy moja implementacja?
ScriptIgnore
atrybut. stackoverflow.com/questions/1193857/subsonic-3-0-0-2-structs-ttScriptIgnore
atrybut we właściwości Tournament.Game i działało dobrze :)Odpowiedzi:
Wygląda na to, że w hierarchii obiektów istnieją odwołania cykliczne, które nie są obsługiwane przez serializator JSON. Czy potrzebujesz wszystkich kolumn? W widoku możesz wybrać tylko te właściwości, których potrzebujesz:
Dzięki temu Twój obiekt JSON będzie lżejszy i łatwiejszy do zrozumienia. Jeśli masz wiele właściwości, AutoMapper może służyć do automatycznego mapowania między obiektami DTO i obiektami widoku.
źródło
Miałem ten sam problem i rozwiązałem go
using Newtonsoft.Json;
źródło
Dzieje się tak, ponieważ złożone obiekty powodują niepowodzenie wynikowego obiektu JSON. I kończy się niepowodzeniem, ponieważ kiedy obiekt jest mapowany, mapuje dzieci, które mapują ich rodziców, tworząc cykliczne odniesienie. Json wymagałoby nieskończonego czasu, aby go serializować, więc zapobiega problemowi z wyjątkiem.
Mapowanie Entity Framework również powoduje to samo zachowanie, a rozwiązaniem jest odrzucenie wszystkich niechcianych właściwości.
Wyjaśniając tylko ostateczną odpowiedź, cały kod wyglądałby tak:
Może to być również następujące, jeśli nie chcesz obiektów wewnątrz
Result
właściwości:źródło
Podsumowując, istnieją 4 rozwiązania tego problemu:
Rozwiązanie 1: wyłącz ProxyCreation dla DBContext i przywróć go na końcu.
Rozwiązanie 2: użycie JsonConvert przez ustawienie ReferenceLoopHandling do ignorowania ustawień serializatora.
Poniższe dwa rozwiązania są takie same, ale użycie modelu jest lepsze, ponieważ jest silnie wpisane.
Rozwiązanie 3: zwróć Model, który zawiera tylko potrzebne właściwości.
Rozwiązanie 4: zwróć nowy obiekt dynamiczny, który zawiera tylko potrzebne właściwości.
źródło
JSON, podobnie jak XML i różne inne formaty, jest formatem serializacji opartym na drzewie. Nie będzie Cię kochać, jeśli w swoich obiektach masz odwołania cykliczne, tak jak wyglądałoby „drzewo”:
Często istnieją sposoby na wyłączenie nawigacji po określonej ścieżce; na przykład
XmlSerializer
możesz oznaczyć właściwość nadrzędną jakoXmlIgnore
. Nie wiem, czy jest to możliwe w przypadku danego serializatora json, ani czyDatabaseColumn
ma odpowiednie znaczniki ( bardzo mało prawdopodobne, ponieważ musiałoby odwoływać się do każdego interfejsu API serializacji)źródło
Jest to spowodowane nowym szablonem DbContext T4, który jest używany do generowania jednostek EntityFramework. Aby móc wykonać śledzenie zmian, te szablony używają wzorca proxy, owijając nimi Twoje ładne POCO. Powoduje to problemy podczas serializacji z JavaScriptSerializer.
Zatem dwa rozwiązania to:
Możesz wyłączyć automatyczne generowanie serwerów proxy, ustawiając je w konfiguracji kontekstu
context.Configuration.ProxyCreationEnabled = false;
Bardzo dobrze wyjaśniono w poniższym artykule.
http://juristr.com/blog/2011/08/javascriptserializer-circular-reference/
źródło
Korzystanie z Newtonsoft.Json: W metodzie Global.asax Application_Start dodaj następujący wiersz:
źródło
dodaj
[JsonIgnore]
do wirtualnych właściwości w swoim modelu.źródło
Unikaj bezpośredniego konwertowania obiektu tabeli. Jeśli relacje są ustawione między innymi tabelami, może to spowodować zgłoszenie tego błędu. Zamiast tego można utworzyć klasę modelu, przypisać wartości do obiektu klasy, a następnie serializować go.
źródło
Udzielone odpowiedzi są dobre, ale myślę, że można je poprawić, dodając perspektywę „architektoniczną”.
Dochodzenie
MVC's Controller.Json
funkcja wykonuje swoją pracę, ale w tym przypadku jest bardzo słaba w dostarczaniu odpowiedniego błędu. UżywającNewtonsoft.Json.JsonConvert.SerializeObject
, błąd określa dokładnie, jaka właściwość wyzwala odwołanie cykliczne. Jest to szczególnie przydatne podczas serializacji bardziej złożonych hierarchii obiektów.Właściwa architektura
Nigdy nie należy próbować serializować modeli danych (np. Modeli EF), ponieważ właściwości nawigacyjne ORM są drogą do zatracenia, jeśli chodzi o serializację. Przepływ danych powinien wyglądać następująco:
Modele usług można uzyskać z modeli danych przy użyciu automatycznych maperów (np. Automapper ). Chociaż nie gwarantuje to braku cyrkularnych odniesień, właściwy projekt powinien to zrobić: modele usług powinny zawierać dokładnie to, czego wymaga usługobiorca (tj. Właściwości).
W tych rzadkich przypadkach, gdy klient zażąda hierarchii obejmującej ten sam typ obiektu na różnych poziomach, usługa może utworzyć strukturę liniową z relacją rodzic -> dziecko (używając tylko identyfikatorów, a nie odwołań).
Nowoczesne aplikacje starają się unikać jednoczesnego ładowania złożonych struktur danych, a modele usług powinny być wąskie. Na przykład:
źródło
Używam poprawki, ponieważ używam Knockout w widokach MVC5.
W akcji
funkcjonować
źródło
Możesz zauważyć właściwości, które powodują odwołanie cykliczne. Następnie możesz zrobić coś takiego:
źródło
źródło
Łatwiejszą alternatywą rozwiązania tego problemu jest zwrócenie ciągu znaków i sformatowanie go na json za pomocą JavaScriptSerializer.
Ważna jest część „Wybierz”, która wybiera właściwości, które chcesz w widoku. Niektóre obiekty mają odniesienie do rodzica. Jeśli nie wybierzesz atrybutów, może pojawić się odwołanie cykliczne, jeśli po prostu weźmiesz tabele jako całość.
Nie rób tego:
Zrób to zamiast tego, jeśli nie chcesz całego stołu:
Pomaga to renderować widok z mniejszą ilością danych, tylko z potrzebnymi atrybutami i przyspiesza działanie sieci.
źródło