non è riuscito a serializzare la risposta nell'API Web


86

Stavo lavorando sull'API web ASP.NET MVC, sto riscontrando questo errore:

Il tipo "ObjectContent" 1 "non è riuscito a serializzare il corpo della risposta per il tipo di contenuto" application / xml; charset = utf-8 '.

Il mio controller è:

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

perché ricevo questo errore?


6
L'eccezione che stai vedendo è un'eccezione generale, che può essere causata da un numero qualsiasi di fattori. Controllare la InnerExceptionproprietà dell'eccezione di serializzazione per scoprire cosa ha causato esattamente il fallimento della serializzazione.
Nome visualizzato

Puoi condividere il codice per il tuo tipo di dipendente? Potrebbe essere perché il tipo Employee non è serializzabile ...
Maggie Ying

Anche dare un'occhiata a questo stackoverflow.com/questions/8173524/...
sttaq

Risposte:


121

Per me questo era un problema con i riferimenti circolari.

La risposta accettata non ha funzionato per me perché cambia solo il comportamento del formattatore JSON, ma stavo ottenendo XML quando ho chiamato il servizio dal browser.

Per risolvere questo problema, ho disattivato XML e ho costretto a restituire solo JSON.

Nel file Global.asax, inserisci le seguenti righe all'inizio del tuo metodo Application_Start:

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

Ora verranno restituiti solo i risultati JSON. Se hai bisogno di risultati XML, dovrai trovare una soluzione diversa.


ha funzionato per me. ma il fatto è che sto usando POSTMAN. è un'estensione di Chrome. quando inserisco dati con POSTMAN funziona bene. ma quando uso restsharp mi dà questo errore. comunque la tua soluzione ha risolto il mio problema
ArgeKumandan

Questa risposta non fornisce una soluzione per utilizzare xml, ed è quello che ha chiesto.
honestduane

Funziona per me quando sono passato a json da xml.
Sike

In realtà, questa risposta va alla radice del problema. Il primo errore che ho ricevuto è stato un errore di riferimento circolare (cercando di restituire JSON dal controller MVC). Quando sono passato a un controller ereditato dall'API, ho iniziato a ricevere questo errore. Quando ho aggiunto il codice sopra a Global.asax l'errore è scomparso.
Matthew Pitts

43

nel tuo file global.asax, nel metodo Application_start () aggiungi questa riga:

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

Spero che ti aiuti!


3
Cos'è application_start e dove si trova? E dove dovrebbe essere posizionata esattamente questa linea?
Ciaran Gallagher

4
Scusa ma qual è il significato di questa affermazione?
Blaise

5
Riga aggiunta a quella Global.asaxdi Application_Start, ma nessuna modifica.
cheesus

8
Questo ancora non ha funzionato per me. Tuttavia ho aggiunto un'altra riga dopo quella in questa risposta e ha funzionato: GlobalConfiguration.Configuration.Formatters.Remove (GlobalConfiguration.Configuration.Formatters.XmlFormatter); Ho creato una risposta più completa di seguito
Zane

2
Questa risposta non dovrebbe essere accettata perché rimuove effettivamente XmlSerializer anziché affrontare il problema del riferimento circolare con XmlSerializer.
Believe2014

29

Ho lo stesso problema. E l'ho risolto. Ho inserito il costruttore predefinito nella classe DTO.

Ex:

public class User
{
    public User()
    {
    }
}

Spero che funzioni con te!


Grazie per il suggerimento, questo mi ha aiutato con la risposta xml, ma qualcuno sa perché ha bisogno di un costruttore predefinito? Abbiamo già i dati ...
Ilya Chernomordik

Penso che quando un oggetto viene serializzato dalla risposta, prima il costruttore è stato chiamato per creare l'istanza dell'oggetto, dopodiché, il metodo set viene utilizzato per impostare i dati sull'istanza dell'oggetto. Questa è la mia ipotesi.
taynguyen

Questa dovrebbe effettivamente essere la risposta scelta in quanto non presuppone alcun tipo di reso di cui hai bisogno. Funzionerà sia per XML che per JSON. Grazie per aver postato questo.
Allen Underwood

22

Mettilo nel costruttore. Spero che questo risolva il problema:

    public MyController()
    {

        db.Configuration.ProxyCreationEnabled = false;
    }

Ottima soluzione. Devo metterlo nel costruttore e ha funzionato.
InsParbo

Questo ha funzionato per me in combinazione con le impostazioni GlobalConfiguration. Ma perché funziona? Qualche spiegazione su come questo risolve il problema? E qual era effettivamente il problema?
Ciaran Gallagher

Per capire che cosa i proxy di entità sono: msdn.microsoft.com/en-us/library/jj592886(v=vs.113).aspx Per capire che cosa è ProxyCreationEnabled: stackoverflow.com/questions/7111109/...
Sadjad Khazaie

16

Ho trovato due soluzioni a questo. Il primo e più semplice da implementare consiste nel modificare qualsiasi IEnumerables, ICollections in un tipo di List. L'API Web può serializzare questi oggetti, tuttavia non può serializzare i tipi di interfaccia.

public class Store
{

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

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

L'altra opzione è quella di non utilizzare il serializzatore JSON nativo ed eseguire questo override nel metodo Register di WebApi Config:

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

1
Mentre il passaggio a List ha funzionato per me, l'aggiunta di un costruttore senza parametri ha funzionato anche per me e potrei continuare a restituire IEnumerable <Widget>
Mike Cheel

8

La soluzione è semplice.

Dopo la query LINQ aggiungere .ToList () (o ToDictionary se necessario).

Farà il caricamento desideroso del caricamento pigro dei dati


1
La modifica del tipo di restituzione dell'azione su IENumerablee l'aggiunta .TiList()al ritorno ha funzionato per me.
Ricardo Souza

5

** questo bug si verifica quando si chiama da request web api / wcf / ... dal lato client, ma come effetto collaterale, sarà necessario includere le relazioni dipendenti dalla parola chiave include. **

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

4

Se stai lavorando con EF, oltre ad aggiungere il codice qui sotto su Global.asax

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

Non dimenticare di importare

using System.Data.Entity;

Quindi puoi restituire i tuoi modelli EF



3

Se si utilizza l'API Web con Entity Framework, è possibile che una soluzione non riesca a serializzare la risposta nell'API Web con Json

Fondamentalmente, è necessario creare un modello corrispondente a ciascun modello EF, questo rimuove le dipendenze tra le classi e consente una facile serializzazione.

Codice: (tratto dal link di riferimento)

Crea un UserModel

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

Cambia il mio metodo 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

L'entità predefinita 6 usa XML per le API, nel tuo progetto, trova il file "Global.asax" File e aggiungi questa riga:

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

Questa riga rimuove il formattatore XML.


Ciao, l'API Web serializza la risposta in XML e JSON, se aggiungi l'intestazione Content-Type: application / json, la risposta è in JSON, devi definire questa intestazione, nel browser puoi sempre vederla come formato XML
Roberth Solís

1

ma se hai riscontrato questo problema con altre entità / classi, devi creare un nuovo DTO per ogni classe, e se ne hai molti, puoi trovare un problema, inoltre penso che crei un DTO solo per risolvere questo problema non è il modo migliore ...

Hai provato questo?

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

Saluti


1

hmmm, seguire può aiutare.

Stavo ottenendo la stessa eccezione e nel mio caso stavo passando prima l'entità poco effettiva creata per il codice entità. Poiché contiene una relazione con altre entità, ho appena creato l'entità viewmapper / dto sopra di essa per tornare.

Ora funziona bene.

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

La tua domanda è abbastanza simile alla mia. Non è necessario restituire i dati direttamente dal database. Per questo, è necessario creare il modello e associare i dati che si desidera visualizzare.

Nel mio esempio, ci sono dati sull'utente che Json non ha potuto serializzare, avevo creato un userModel e, nella mia API, restituisco userModel invece User dal database.

La logica di conversione o associazione dei dati tra User e UserModel deve essere nell'API.

Impossibile serializzare la risposta nell'API Web con Json


0

Questo era l'errore specifico che stavo ricevendo dalla mia chiamata all'API Web odata:

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

Alla fine ho capito che la mia classe dbContext aveva un nome di tabella formattato male assegnato in onModelCreating .. quindi SqlClient stava morendo alla ricerca di una tabella che non esisteva nel mio db !!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.