Die Antwort in der Web-API konnte nicht serialisiert werden


85

Ich habe an der ASP.NET MVC-Web-API gearbeitet und habe folgenden Fehler:

Der Typ 'ObjectContent`1' konnte den Antworttext für den Inhaltstyp 'application / xml nicht serialisieren. Zeichensatz = utf-8 '.

Mein Controller ist:

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

Warum bekomme ich diesen Fehler?


6
Die Ausnahme, die Sie sehen, ist eine allgemeine Ausnahme, die durch eine beliebige Anzahl von Faktoren verursacht werden kann. Überprüfen Sie die InnerExceptionEigenschaft der Serialisierungsausnahme, um herauszufinden, was genau dazu geführt hat, dass die Serialisierung fehlgeschlagen ist.
Anzeigename

Können Sie den Code für Ihren Mitarbeitertyp freigeben? Es könnte sein, dass der Typ Mitarbeiter nicht serialisierbar ist ...
Maggie Ying

Schauen Sie sich auch diese stackoverflow.com/questions/8173524/…
sttaq

Antworten:


119

Für mich war dies ein Problem mit der Zirkelreferenzierung.

Die akzeptierte Antwort hat bei mir nicht funktioniert, da sie nur das Verhalten des JSON-Formatierers ändert. Ich habe jedoch XML erhalten, als ich den Dienst über den Browser aufgerufen habe.

Um dies zu beheben, habe ich XML ausgeschaltet und nur die Rückgabe von JSON erzwungen.

Fügen Sie in der Datei Global.asax die folgenden Zeilen oben in Ihre Application_Start-Methode ein:

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

Jetzt werden nur JSON-Ergebnisse zurückgegeben. Wenn Sie XML-Ergebnisse benötigen, müssen Sie eine andere Lösung finden.


hat für mich gearbeitet. Aber die Sache ist, ich benutze POSTMAN. Es ist eine Chrom-Erweiterung. Wenn ich Daten mit POSTMAN poste, funktioniert es gut. aber wenn ich restsharp benutze, gibt es mir diesen Fehler.
Trotzdem

Diese Antwort bietet keine Lösung für die Verwendung von XML, und darum hat er gebeten.
ehrlichduane

Funktioniert für mich, da ich von XML auf json umgeschaltet habe.
Sike12

Tatsächlich geht diese Antwort dem Problem auf den Grund. Der erste Fehler, den ich erhielt, war ein Zirkelreferenzfehler (Versuch, JSON vom MVC-Controller zurückzugeben). Als ich zu einem von der API geerbten Controller wechselte, wurde stattdessen dieser Fehler angezeigt. Als ich den obigen Code zu Global.asax hinzufügte, verschwand der Fehler.
Matthew Pitts

43

Fügen Sie in Ihrer Datei global.asax in der Methode Application_start () diese Zeile hinzu:

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

Ich hoffe das hilft dir!


3
Was ist application_start und wo ist es zu finden? Und wo genau soll diese Linie platziert werden?
Ciaran Gallagher

4
Entschuldigung, aber was bedeutet diese Aussage?
Blaise

5
Zeile zu Global.asax's hinzugefügt Application_Start, aber keine Änderung.
Cheesus

8
Das hat bei mir immer noch nicht funktioniert. Ich habe jedoch eine weitere Zeile nach der in dieser Antwort eingefügt und es hat funktioniert: GlobalConfiguration.Configuration.Formatters.Remove (GlobalConfiguration.Configuration.Formatters.XmlFormatter); Ich habe eine ausführlichere Antwort unten erstellt
Zane

2
Diese Antwort sollte nicht akzeptiert werden, da sie tatsächlich XmlSerializer entfernt, anstatt das Problem des Zirkelverweises mit XmlSerializer zu lösen.
Believe2014

29

Ich habe das gleiche Problem. Und ich habe es gelöst. Ich habe den Standardkonstruktor in die DTO-Klasse eingefügt.

Ex:

public class User
{
    public User()
    {
    }
}

Hoffe es funktioniert mit dir!


Vielen Dank für den Vorschlag, dies hat mir bei der XML-Antwort geholfen, aber weiß jemand, warum ein Standardkonstruktor benötigt wird? Wir haben die Daten bereits ...
Ilya Chernomordik

Ich denke, wenn ein Objekt aus der Antwort serialisiert wird, wurde zuerst der Konstruktor aufgerufen, um eine Instanz des Objekts zu erstellen. Danach wird die set-Methode verwendet, um Daten auf die Objektinstanz zu setzen. Das ist meine Vermutung.
Taynguyen

Dies sollte eigentlich die gewählte Antwort sein, da keine Annahme über die von Ihnen benötigten Rückgabetypen getroffen wird. Dies funktioniert sowohl für XML als auch für JSON. Vielen Dank für die Veröffentlichung.
Allen Underwood

21

Setzen Sie dies in Konstruktor. Hoffe das löst das Problem:

    public MyController()
    {

        db.Configuration.ProxyCreationEnabled = false;
    }

Hervorragende Lösung. Ich muss es in den Konstruktor einfügen und es hat funktioniert.
InsParbo

Dies funktionierte bei mir in Kombination mit den GlobalConfiguration-Einstellungen. Aber warum funktioniert das? Gibt es eine Erklärung, wie dies das Problem behebt? Und was war das Problem eigentlich?
Ciaran Gallagher

Um zu verstehen, was Entity-Proxys sind: msdn.microsoft.com/en-us/library/jj592886(v=vs.113).aspx Um zu verstehen, was ProxyCreationEnabled ist: stackoverflow.com/questions/7111109/…
Sadjad Khazaie

16

Ich habe zwei Lösungen dafür gefunden. Die erste und am einfachsten zu implementierende Methode besteht darin, IEnumerables und ICollections in einen Listentyp zu ändern. Die WebAPI kann diese Objekte serialisieren, jedoch keine Schnittstellentypen serialisieren.

public class Store
{

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

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

Die andere Option besteht darin, den nativen JSON-Serializer nicht zu verwenden und diese Überschreibung in der Register-Methode der WebApi-Konfiguration auszuführen:

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

1
Während der Wechsel zu List für mich funktioniert hat, hat das Hinzufügen eines parameterlosen Konstruktors auch für mich funktioniert und ich konnte weiterhin IEnumerable <Widget>
Mike Cheel

8

Die Lösung ist einfach.

Fügen Sie nach der LINQ-Abfrage .ToList () (oder bei Bedarf ToDictionary) hinzu.

Das Laden wird eifriger als das langsame Laden der Daten


1
Das Ändern des Aktionsrückgabetyps in IENumerableund das Hinzufügen .TiList()zur Rückgabe hat bei mir funktioniert.
Ricardo Souza

4

** Dieser Fehler tritt auf, wenn von der Client-Seite aus die Anforderungs-Web-API / wcf / ... aufgerufen wird. Als Nebeneffekt müssen Sie jedoch abhängige Beziehungen durch das Schlüsselwort include einschließen. ** **.

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

4

Wenn Sie mit EF arbeiten, fügen Sie neben dem folgenden Code auch Global.asax hinzu

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

Vergessen Sie nicht zu importieren

using System.Data.Entity;

Dann können Sie Ihre eigenen EF-Modelle zurückgeben



3

Wenn Sie die Web-API mit Entity Framework verwenden, kann eine Lösung fehlschlagen, um die Antwort in der Web-API mit Json zu serialisieren

Grundsätzlich müssen Sie ein Modell erstellen, das jedem EF-Modell entspricht. Dadurch werden Abhängigkeiten zwischen Klassen beseitigt und eine einfache Serialisierung ermöglicht.

Code: (entnommen aus dem Link, auf den verwiesen wird)

Erstellen Sie ein UserModel

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

Ändere meine Methode 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

Standardentität 6 verwendet XML , um in Ihrem Projekt die Datei "Global.asax" zu finden und die folgende Zeile hinzuzufügen:

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

Diese Zeile entfernt den XML-Formatierer.


Hallo, Web-API serialisiert die Antwort in XML und JSON. Wenn Sie den Header Content-Type: application / json hinzufügen, ist die Antwort in JSON. Sie müssen diesen Header definieren. Im Browser können Sie ihn immer als XML-Format
anzeigen

1

Wenn Sie dieses Problem jedoch bei anderen Entitäten / Klassen festgestellt haben, müssen Sie für jede Klasse ein neues DTO erstellen. Wenn Sie viele davon haben, können Sie ein Problem finden. Ich denke auch, dass Sie ein DTO nur zur Lösung dieses Problems erstellen ist nicht der beste Weg ...

Hast du das versucht?

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

Grüße


1

hmmm, Folgendes kann helfen.

Ich habe die gleiche Ausnahme erhalten und in meinem Fall zuerst die eigentliche Poco-Entität übergeben, die für den Entitätscode erstellt wurde. Da es eine Beziehung zu anderen Entitäten enthält, habe ich gerade die viewmapper / dto-Entität darüber erstellt, um zurückzukehren.

Es funktioniert jetzt gut.

Poco Entity:

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

Ihre Frage ist meiner ziemlich ähnlich. Sie dürfen keine Daten direkt aus der Datenbank zurückgeben. Dazu müssen Sie ein Modell erstellen und Daten zuordnen, die angezeigt werden sollen.

In meinem Beispiel gibt es Daten zu Benutzern, die Json nicht serialisieren konnte. Ich hatte ein Benutzermodell erstellt und in meiner API gebe ich stattdessen Benutzermodell Benutzer aus Datenbank zurück.

Die Logik zum Konvertieren oder Zuordnen von Daten zwischen User und UserModel muss in der API enthalten sein.

Fehler beim Serialisieren der Antwort in der Web-API mit Json


0

Dies war der spezifische Fehler, den ich von meinem Odata-Web-API-Aufruf erhalten habe:

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

Ich fand schließlich heraus, dass meine dbContext-Klasse einen schlecht formatierten Tabellennamen hatte , der in onModelCreating zugewiesen wurde. Also starb der SqlClient auf der Suche nach einer Tabelle, die in meiner Datenbank nicht vorhanden war !!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.