nie udało się serializować odpowiedzi w internetowym interfejsie API


86

Pracowałem na internetowym API ASP.NET MVC, mam ten błąd:

Typowi „ObjectContent” 1 nie udało się serializować treści odpowiedzi dla typu zawartości „application / xml”; charset = utf-8 '.

Mój kontroler to:

public Employee GetEmployees()
{
    Employee employees = db.Employees.First();
    return employees;
}

dlaczego otrzymuję ten błąd?


6
Wyjątek, który widzisz, jest wyjątkiem ogólnym, który może być spowodowany wieloma czynnikami. Sprawdź InnerExceptionwłaściwość wyjątku serializacji, aby dowiedzieć się, co dokładnie spowodowało niepowodzenie serializacji.
— Nazwa wyświetlana

Czy możesz udostępnić kod swojego typu pracownika? Może to być spowodowane tym, że typ pracownika nie daje się serializować ...
— Maggie Ying


Odpowiedzi:


121

Dla mnie był to problem z odniesieniami cyklicznymi.

Zaakceptowana odpowiedź nie zadziałała, ponieważ zmieniała tylko zachowanie programu formatującego JSON, ale otrzymywałem XML, gdy dzwoniłem do usługi z przeglądarki.

Aby to naprawić, wyłączyłem XML i wymusiłem zwracanie tylko JSON.

W pliku Global.asax umieść następujące wiersze u góry metody Application_Start:

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);

Teraz zostaną zwrócone tylko wyniki JSON. Jeśli potrzebujesz wyników XML, musisz znaleźć inne rozwiązanie.


pracował dla mnie. ale rzecz w tym, że używam POSTMAN. to rozszerzenie do Chrome. kiedy wysyłam dane za pomocą POSTMAN, działa dobrze. ale kiedy używam restsharp, daje mi ten błąd. w każdym razie twoje rozwiązanie rozwiązało mój problem
— ArgeKumandan,

Ta odpowiedź nie dostarcza rozwiązania do używania xml i o to właśnie prosił.
— szczery

Działa dla mnie, gdy przełączyłem się na json z xml.
— Sike12

Właściwie ta odpowiedź dociera do źródła problemu. Pierwszym otrzymanym błędem był cykliczny błąd odwołania (próba zwrócenia JSON z kontrolera MVC). Kiedy przełączyłem się na kontroler dziedziczony po API, zacząłem otrzymywać ten błąd. Kiedy dodałem powyższy kod do Global.asax, błąd zniknął.
— Matthew Pitts

43

w pliku global.asax, w metodzie Application_start () dodaj następujący wiersz:

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;

Mam nadzieję, że ci to pomoże!


3
Co to jest application_start i gdzie można go znaleźć? A gdzie dokładnie należy umieścić tę linię?
— Ciaran Gallagher

4
Przepraszam, ale jakie jest znaczenie tego stwierdzenia?
— Blaise

5
Linia dodany do Global.asax„s Application_Start, ale bez zmian.
— ser

8
To nadal nie działa dla mnie. Jednak dodałem kolejną linię po jednej w tej odpowiedzi i zadziałało: GlobalConfiguration.Configuration.Formatters.Remove (GlobalConfiguration.Configuration.Formatters.XmlFormatter); Poniżej utworzyłem pełniejszą odpowiedź
— Zane

2
Ta odpowiedź nie powinna zostać zaakceptowana, ponieważ faktycznie usuwa XmlSerializer zamiast rozwiązywania problemu cyklicznego odwołania z XmlSerializer.
— Believe2014

29

Mam ten sam problem. I rozwiązałem to. Domyślnego konstruktora umieściłem w klasie DTO.

Dawny:

public class User
{
    public User()
    {
    }
}

Mam nadzieję, że to zadziała!


Dzięki za sugestię, pomogło mi to w odpowiedzi xml, ale czy ktoś wie, dlaczego potrzebuje domyślnego konstruktora? Mamy już dane ...
— Ilya Chernomordik

Myślę, że gdy obiekt jest serializowany z odpowiedzi, najpierw został wywołany konstruktor w celu utworzenia instancji obiektu, a następnie metoda set służy do ustawiania danych na instancję obiektu. To moje przypuszczenie.
— taynguyen

Właściwie to powinna być wybrana odpowiedź, ponieważ nie przyjmuje żadnych założeń dotyczących typów zwrotów, których potrzebujesz. To zadziała zarówno dla XML, jak i JSON. Dzięki za opublikowanie tego.
— Allen Underwood

22

Umieść to w konstruktorze. Mam nadzieję, że to rozwiąże problem:

    public MyController()
    {

        db.Configuration.ProxyCreationEnabled = false;
    }

Doskonałe rozwiązanie. Muszę włożyć to do konstruktora i zadziałało.
— InsParbo

To zadziałało dla mnie w połączeniu z ustawieniami GlobalConfiguration. Ale dlaczego to działa? Jakieś wyjaśnienie, jak to rozwiązuje problem? Na czym właściwie polegał problem?
— Ciaran Gallagher

Aby zrozumieć, czym są proxy encji: msdn.microsoft.com/en-us/library/jj592886(v=vs.113).aspx Aby zrozumieć, czym jest ProxyCreationEnabled: stackoverflow.com/questions/7111109/…
— Sadjad Khazaie

16

Znalazłem dwa rozwiązania tego problemu. Pierwszym i najłatwiejszym do zaimplementowania jest zmiana dowolnego IEnumerables, ICollections na typ List. Interfejs WebAPI może serializować te obiekty, ale nie może serializować typów interfejsów.

public class Store
{

  [StringLength(5)]
    public string Zip5 { get; set; }

    public virtual List<StoreReport> StoreReports { get; set; }  //use a list here
 }

Inną opcją jest nieużywanie natywnego serializatora JSON i uruchomienie tego zastąpienia w metodzie Register w WebApi Config:

        var json = config.Formatters.JsonFormatter;
        json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
        config.Formatters.Remove(config.Formatters.XmlFormatter);

1
Podczas zmiany na List zadziałało dla mnie dodanie konstruktora bez parametrów i mogłem nadal zwracać IEnumerable <Widget>
— Mike Cheel

8

Rozwiązanie jest proste.

Po zapytaniu LINQ dodaj .ToList () (lub ToDictionary w razie potrzeby).

Będzie ładować chętniej niż leniwie ładowanie danych


1
Zmiana typu powrotu akcji na IENumerablei dodanie .TiList()do zwrotu zadziałało.
— Ricardo Souza

5

** ten błąd występuje podczas wywoływania z żądania internetowego interfejsu API / wcf / ... ze strony klienta, ale jako efekt uboczny, będziesz musiał dołączyć zależne relacje przez słowo kluczowe include. **

public CustomerPortalContext()
            : base("Name=CustomerPortalContext")
        {
            base.Configuration.ProxyCreationEnabled = false;
        }

4

Jeśli pracujesz z EF, oprócz dodania poniższego kodu na Global.asax

            GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);          

Nie zapomnij zaimportować

using System.Data.Entity;

Następnie możesz zwrócić własne modele EF



3

Jeśli używasz interfejsu API sieci Web z Entity Framework, rozwiązanie może zakończyć się niepowodzeniem serializacji odpowiedzi w interfejsie API sieci Web z Json

Zasadniczo musisz utworzyć model odpowiadający każdemu modelowi EF, usuwa to zależności między klasami i umożliwia łatwą serializację.

Kod: (pobrany z odnośnika)

Utwórz model użytkownika

public class UserModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Zmień moją metodę GetAll ()

public IEnumerable<UserModel> GetAll()
{
    using (Database db = new Database ())
    {
        List<UserModel> listOfUsers = new List<UserModel>();
        UserModel userModel = new UserModel();
        foreach(var user in db.Users)
        {
           userModel.FirstName = user.FirstName;
           userModel.LastName = user.LastName;
           listOfUsers.Add(userModel);
        }
        IEnumerable<UserModel> users = listOfUsers;

        return users;
    }
}

2

Domyślna jednostka 6 używa XML do apis, w swoim projekcie znajdź plik „Global.asax” File i dodaj ten wiersz:

GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);

Ta linia usuwa XML Formatter.


Witaj, Web API serializuje odpowiedź w XML i JSON, jeśli dodasz nagłówek Content-Type: application / json, odpowiedź jest w formacie JSON, musisz zdefiniować ten nagłówek, w przeglądarce zawsze możesz zobaczyć go jako format XML
— Roberth Solís

1

ale jeśli znalazłeś ten problem z innymi bytami / klasami, musisz stworzyć nowe DTO dla każdej klasy, a jeśli masz ich dużo, możesz znaleźć problem, również myślę, że tworzymy DTO tylko do rozwiązania tego problemu nie jest najlepszym sposobem ...

Próbowałeś tego?

var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = 
Newtonsoft.Json.PreserveReferencesHandling.All;

pozdrowienia


1

hmmm, Poniższe mogą pomóc.

Otrzymałem ten sam wyjątek, aw moim przypadku najpierw przekazywałem rzeczywistą jednostkę poco utworzoną dla kodu jednostki. Ponieważ zawiera on relacje z innymi bytami, właśnie utworzyłem na nim byty viewmapper / dto, aby powracały.

Teraz działa dobrze.

Podmiot Poco:

public class Tag
{
public int Id{get;set;}
public string Title{get;set;}
public IList<Location> Locations{get;set;}
}

ViewMapper / Dto

public class TagResultsViewMapper
{
public int Id{get;set;}
public string Title{get;set;}
//just remove the following relationship 
//public IList<Location> Locations{get;set;}
}

0

Twoje pytanie jest dość podobne do mojego. Nie możesz zwracać danych bezpośrednio z bazy danych. W tym celu musisz utworzyć Model i skojarzyć dane, które chcesz pokazać.

W moim przykładzie są dane o użytkowniku, których Json nie mógł serializować, utworzyłem userModel iw moim API zwracam userModel zamiast User z bazy danych.

Logika konwertowania lub kojarzenia danych między użytkownikiem a modelem użytkownika musi znajdować się w interfejsie API.

Nie udało się serializować odpowiedzi w internetowym interfejsie API za pomocą Json


0

To był konkretny błąd, który otrzymałem z mojego wywołania internetowego interfejsu API odata:

The 'ObjectContent`1' type failed to serialize the response 
body for content type 'application/json; odata.metadata=minimal'.

W końcu zorientowałem się, że moja klasa dbContext miała źle sformatowaną nazwę tabeli, która została przypisana w onModelCreating .. więc SqlClient umierał, szukając tabeli, której nie było w mojej bazie danych !!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.