no se pudo serializar la respuesta en la API web


86

Estaba trabajando en la API web ASP.NET MVC, tengo este error:

El tipo 'ObjectContent`1' no pudo serializar el cuerpo de la respuesta para el tipo de contenido 'application / xml; charset = utf-8 '.

Mi controlador es:

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

¿Por qué recibo este error?


6
La excepción que está viendo es una excepción general, que puede deberse a varios factores. Verifique la InnerExceptionpropiedad de la excepción de serialización para averiguar qué causó exactamente que fallara la serialización.
Nombre

¿Puede compartir el código para su tipo de empleado? Podría ser porque el tipo Empleado no es serializable ...
Maggie Ying

También eche un vistazo a este stackoverflow.com/questions/8173524/…
sttaq

Respuestas:


121

Para mí, esto fue un problema con las referencias circulares.

La respuesta aceptada no me funcionó porque solo cambia el comportamiento del formateador JSON, pero estaba obteniendo XML cuando llamé al servicio desde el navegador.

Para solucionar esto, apagué XML y obligué a que solo se devolviera JSON.

En el archivo Global.asax, coloque las siguientes líneas en la parte superior de su método Application_Start:

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

Ahora solo se devolverán los resultados JSON. Si necesita resultados XML, deberá encontrar una solución diferente.


funcionó para mí. pero la cosa es que estoy usando POSTMAN. es una extensión de Chrome. cuando publico datos con POSTMAN funciona bien. pero cuando uso restsharp me da este error. de todos modos, su solución solucionó mi problema
ArgeKumandan

Esta respuesta no proporciona una solución para usar xml, y eso es lo que pidió.
honestduane

Funciona para mí cuando encendí json desde xml.
Sike12

En realidad, esta respuesta llega a la raíz del problema. El primer error que recibí fue un error de referencia circular (tratando de devolver JSON desde el controlador MVC). Cuando cambié a un controlador heredado de API, comencé a recibir este error. Cuando agregué el código anterior a Global.asax, el error desapareció.
Matthew Pitts

43

en su archivo global.asax, en el método Application_start () agregue esta línea:

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

¡Espero que eso te ayude!


3
¿Qué es application_start y dónde se puede encontrar? ¿Y dónde exactamente debería colocarse esta línea?
Ciaran Gallagher

4
Lo siento, pero ¿cuál es el significado de esta declaración?
Blaise

5
Línea agregada a Global.asax's Application_Start, pero sin cambios.
Cheesus

8
Esto todavía no funcionó para mí. Sin embargo, agregué otra línea después de la de esta respuesta y funcionó: GlobalConfiguration.Configuration.Formatters.Remove (GlobalConfiguration.Configuration.Formatters.XmlFormatter); He creado una respuesta más completa a continuación
Zane

2
Esta respuesta no debe aceptarse porque de hecho elimina XmlSerializer en lugar de abordar el problema de la referencia circular con XmlSerializer.
Believe2014

29

Tengo el mismo problema. Y lo resolví. Pongo el constructor predeterminado en la clase DTO.

Ex:

public class User
{
    public User()
    {
    }
}

¡Espero que funcione contigo!


Gracias por la sugerencia, esto me ayudó con la respuesta xml, pero ¿alguien sabe por qué necesita un constructor predeterminado? Ya tenemos los datos ...
Ilya Chernomordik

Creo que cuando un objeto se serializa a partir de la respuesta, primero se llamó al constructor para crear una instancia del objeto, después de eso, el método set se usa para configurar los datos en la instancia del objeto. Esa es mi suposición.
taynguyen

En realidad, esta debería ser la respuesta elegida, ya que no hace ninguna suposición sobre los tipos de devolución que necesita. Esto funcionará tanto para XML como para JSON. Gracias por publicar esto.
Allen Underwood

22

Pon esto en constructor. Espero que esto resuelva el problema:

    public MyController()
    {

        db.Configuration.ProxyCreationEnabled = false;
    }

Excelente solucion. Necesito ponerlo en el constructor y funcionó.
InsParbo

Esto funcionó para mí en combinación con la configuración de GlobalConfiguration. Pero, ¿por qué funciona esto? ¿Alguna explicación de cómo esto soluciona el problema? ¿Y cuál era realmente el problema?
Ciaran Gallagher

Para comprender qué son los proxies de entidad: msdn.microsoft.com/en-us/library/jj592886(v=vs.113).aspx Para comprender qué es ProxyCreationEnabled: stackoverflow.com/questions/7111109/…
Sadjad Khazaie

16

Encontré dos soluciones para esto. La primera y más fácil de implementar es cambiar cualquier IEnumerables, ICollections a un tipo de Lista. WebAPI puede serializar estos objetos, sin embargo, no puede serializar tipos de interfaz.

public class Store
{

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

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

La otra opción es no usar el serializador JSON nativo y ejecutar esta anulación en el método Register de WebApi Config:

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

1
Aunque cambiar a List funcionó para mí, agregar un constructor sin parámetros también funcionó para mí y pude continuar devolviendo IEnumerable <Widget>
Mike Cheel

8

La solución es simple.

Después de la consulta LINQ, agregue .ToList () (o ToDictionary si es necesario).

Hará una carga ansiosa que una carga diferida de los datos


1
Cambiar el tipo de retorno de acción ay IENumerableagregar .TiList()al retorno funcionó para mí.
Ricardo Souza

5

** este error ocurre cuando se llama desde la solicitud web api / wcf / ... desde el lado del cliente, pero como efecto secundario, deberá incluir las relaciones dependientes mediante la palabra clave include. **

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

4

Si está trabajando con EF, además de agregar el siguiente código en Global.asax

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

No olvides importar

using System.Data.Entity;

Entonces puede devolver sus propios modelos EF



3

Si usa la API web con Entity Framework, es posible que una solución no pueda serializar la respuesta en la API web con Json

Básicamente, necesita crear un modelo correspondiente a cada modelo EF, esto elimina las dependencias entre clases y permite una fácil serialización.

Código: (tomado del enlace de referencia)

Crear un modelo de usuario

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

Cambiar mi método 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

La Entidad 6 predeterminada usa XML para apis, en su proyecto, busque el archivo "Global.asax" File y agregue esta línea:

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

Esta línea elimina el formateador XML.


Hola, Web API serializa la respuesta en XML y JSON, si agregas encabezado Content-Type: application / json, la respuesta está en JSON, necesitas definir este encabezado, en el navegador siempre puedes verlo como formato XML
Roberth Solís

1

pero si encontraste este problema con otras entidades / clases, tienes que crear un nuevo DTO para cada clase, y si tienes muchos de ellos, puedes encontrar un problema, también creo que crear un DTO solo para resolver este problema no es la mejor manera ...

¿Intentaste esto?

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

Saludos


1

hmmm, lo siguiente puede ayudar.

Recibía la misma excepción y, en mi caso, pasaba primero la entidad poco real creada para el código de entidad. Dado que contiene relación con otras entidades, acabo de crear la entidad viewmapper / dto encima para regresar.

Funciona bien ahora.

Entidad 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

Tu pregunta es bastante similar a la mía. No debe devolver datos de la base de datos directamente. Para ello, debe crear el modelo y asociar los datos que desea mostrar.

En mi ejemplo, hay datos sobre User que Json no pudo serializar, tuve que crear un userModel y, en mi API, devuelvo userModel en lugar de User from database.

La lógica de convertir o asociar datos entre User y UserModel debe estar en API.

No se pudo serializar la respuesta en la API web con Json


0

Este era el error específico que recibía de mi llamada a la API web de odata:

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

Finalmente descubrí que mi clase dbContext tenía un nombre de tabla mal formateado que se estaba asignando en onModelCreating ... ¡¡así que SqlClient se estaba muriendo buscando una tabla que no existía en mi base de datos !!

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.