Échec de la sérialisation de la réponse dans L'API Web avec Json

je travaille avec ASP.NET MVC 5 Web Api. Je veux consulter tous mes utilisateurs.

j'ai écrit api/users et je reçois ceci:

"Le" ObjectContent`1' type échoué à sérialiser le corps de la réponse pour le type de contenu application/json; charset=utf-8'"

dans WebApiConfig, j'ai déjà ajouté ces lignes:

HttpConfiguration config = new HttpConfiguration();
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; 

mais ça ne marche toujours pas.

Ma fonction de retour de données est la suivante:

public IEnumerable<User> GetAll()
{
    using (Database db = new Database())
    {
        return db.Users.ToList();
    }
}
81
demandé sur chakeda 2014-04-16 06:56:38

18 réponses

quand il s'agit de retourner des données au consommateur à partir de L'Api Web (ou tout autre service web d'ailleurs), je recommande fortement de ne pas renvoyer des entités qui proviennent d'une base de données. Il est beaucoup plus fiable et maintenable d'utiliser des modèles dans lesquels vous avez le contrôle de ce que les données ressemblent et non la base de données. De cette façon, vous n'avez pas à jouer avec les formateurs tellement dans le WebApiConfig. Vous pouvez juste créer un UserModel qui a des modèles enfants comme propriétés et se débarrasser des boucles de référence dans le retour des objets. Qui rend le processus beaucoup plus heureux.

de plus, il n'est pas nécessaire de supprimer les formateurs ou les types de médias pris en charge typiquement si vous spécifiez simplement l'en-tête" Accepts " dans la requête. Jouer avec ça peut parfois rendre les choses plus confuses.

exemple:

public class UserModel {
    public string Name {get;set;}
    public string Age {get;set;}
    // Other properties here that do not reference another UserModel class.
}
65
répondu jensendp 2014-04-16 03:43:42

si vous travaillez avec EF, en plus d'ajouter le code ci-dessous sur Global.asax 151930920"

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

N'oubliez pas d'importer

using System.Data.Entity;

alors vous pouvez retourner vos propres modèles EF

C'est aussi Simple que ça!

109
répondu Lucas Roselli 2016-12-21 14:03:23

donner la bonne réponse est une façon d'y aller, cependant c'est une exagération quand vous pouvez le corriger par un paramètre de configuration.

mieux L'utiliser dans le constructeur dbcontext

public DbContext() // dbcontext constructor
            : base("name=ConnectionStringNameFromWebConfig")
{
     this.Configuration.LazyLoadingEnabled = false;
     this.Configuration.ProxyCreationEnabled = false;
}

Asp.Net erreur de L'API Web: le type`ObjectContent' 1 'n'a pas sérialisé le corps de réponse pour le type de contenu 'application / xml; charset=utf-8'

44
répondu Md. Alim Ul Karim 2017-05-23 12:17:55

ajouter ce code à global.asax ci-dessous sur Application_Start :

mise à Jour de .Ignore à .Serialize . Il doit travailler.

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize;
            GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
28
répondu Bimal Das 2016-01-14 18:48:52
public class UserController : ApiController
{

   Database db = new Database();

   // construction
   public UserController()
   {
      // Add the following code
      // problem will be solved
      db.Configuration.ProxyCreationEnabled = false;
   }

   public IEnumerable<User> GetAll()
    {
            return db.Users.ToList();
    }
}
10
répondu Aykut 2016-09-16 14:21:05

Je n'aime pas ce code:

foreach(var user in db.Users)

Comme alternative, on pourrait faire quelque chose comme ce qui a fonctionné pour moi:

var listOfUsers = db.Users.Select(r => new UserModel
                         {
                             userModel.FirstName = r.FirstName;
                             userModel.LastName = r.LastName;

                         });

return listOfUsers.ToList();

cependant, J'ai fini par utiliser la solution de Lucas Roselli.

mise à jour: simplifiée par la restitution d'un objet anonyme:

var listOfUsers = db.Users.Select(r => new 
                         {
                             FirstName = r.FirstName;
                             LastName = r.LastName;
                         });

return listOfUsers.ToList();
7
répondu Kasper Halvas Jensen 2017-04-04 18:06:35

il y a aussi ce scénario qui génère la même erreur:

dans le cas où le retour est une List<dynamic> à la méthode de l'api web

exemple:

public HttpResponseMessage Get()
{
    var item = new List<dynamic> { new TestClass { Name = "Ale", Age = 30 } };

    return Request.CreateResponse(HttpStatusCode.OK, item);
}

public class TestClass
{
    public string Name { get; set; }
    public int Age { get; set; }
}

donc, pour ce scénario, utilisez [KnownTypeAttribute] dans la classe return (tous) comme ceci:

[KnownTypeAttribute(typeof(TestClass))]
public class TestClass
{
    public string Name { get; set; }
    public int Age { get; set; }
}

ça marche pour moi!

6
répondu Alex 2014-10-24 17:20:05

Je l'ai résolu en utilisant ce code pour WebApiConfig.fichier cs

var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects; 
config.Formatters.Remove(config.Formatters.XmlFormatter);
4
répondu aemre 2018-03-23 13:28:57

mon préféré: il suffit d'ajouter le code ci-dessous à App_Start/WebApiConfig.cs . Ceci retournera json au lieu de XML par défaut et empêchera également l'erreur que vous aviez. Pas besoin d'éditer Global.asax pour supprimer XmlFormatter etc.

le type`ObjectContent' 1 ' n'a pas sérialisé le corps de réponse pour le type de contenu 'application / xml; charset=utf-8

config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
3
répondu Ogglas 2016-08-12 11:24:04

Utiliser AutoMapper...

public IEnumerable<User> GetAll()
    {
        using (Database db = new Database())
        {
            var users = AutoMapper.Mapper.DynamicMap<List<User>>(db.Users);
            return users;
        }
    }
2
répondu Proximo 2015-09-04 04:30:49

utilisez l'espace de nom suivant:

using System.Web.OData;

au lieu de:

using System.Web.Http.OData;

Il a travaillé pour moi

2
répondu Harish K 2016-11-03 12:04:04

Solution qui a fonctionné pour moi:

  1. utilisez [DataContract] pour les attributs de classe et [DataMember] pour chaque propriété à sérialiser.Ceci est suffisant pour obtenir le résultat Json (par ex. de fiddler).

  2. pour obtenir la sérialisation xml écrire dans Global.asax ce code:

    var xml = GlobalConfiguration.Configuration.Formateuses.XmlFormatter; XML.UseXmlSerializer = true;

  3. Lire cet article, il m'a aidé à comprendre la sérialisation: https://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization
2
répondu Lapenkov Vladimir 2016-11-16 07:07:16

à ajouter à la réponse de jensendp:

je passerais l'entité à un modèle créé par l'utilisateur et j'utiliserais les valeurs de cette entité pour définir les valeurs dans votre nouveau modèle créé. Par exemple:

public class UserInformation {
   public string Name { get; set; }
   public int Age { get; set; }

   public UserInformation(UserEntity user) {
      this.Name = user.name;
      this.Age = user.age;
   }
}

changez ensuite votre type de déclaration en: IEnumerable<UserInformation>

1
répondu Greg A 2015-05-05 13:27:29

si vous travaillez avec Entitefram Framework, vous devez désactiver proxy dans votre constructeur de classe DbContext as,

public class MyDbContext : DbContext
{
  public MyDbContext()
  {
    this.Configuration.ProxyCreationEnabled = false;
  }
}
1
répondu Er Suman G 2018-01-12 04:53:23

un autre cas où j'ai reçu cette erreur était quand ma requête de base de données retournait une valeur nulle mais mon type de modèle user/view était défini comme non-nullable. Par exemple, le changement de mon champ UserModel de int à int? résolu.

0
répondu marshall 2015-10-14 14:49:40

cela se produit aussi quand le type de réponse n'est pas public! J'ai retourné une classe interne car J'ai utilisé Visual Studio pour me générer le type.

internal class --> public class
0
répondu Vanice 2017-11-15 15:52:40

alors que toutes les réponses ci-dessus sont correctes, on peut vouloir vérifier le InnerException > Exceptitionmessage .

S'il dit quelque chose comme ceci "T il instance ObjectContext a été éliminé et ne peut plus être utilisé pour les opérations qui nécessitent une connexion. ". Cela pourrait poser problème en raison du comportement par défaut de L'EE.

en assignant LazyLoadingEnabled = false dans votre constructeur DbContext fera l'affaire.

public class MyDbContext : DbContext
{
  public MyDbContext()
  {
    this.Configuration.LazyLoadingEnabled = false;
  }
}

pour une lecture plus détaillée sur le comportement D'EagerLoading et de LazyLoading de EF, référez-vous à cet article MSDN .

0
répondu Bhramar 2017-12-29 12:39:48

dans mon cas, j'ai eu un message d'erreur similaire:

le type`ObjectContent' 1 ' n'a pas sérialisé l'organisme de réponse pour type de contenu "application / xml; charset=utf-8".

mais quand j'ai creusé plus profondément, la question était:

Type de nom.SomeSubRootType" avec le nom du contrat de données "SomeSubRootType: / / schemas.datacontract.org/2004/07/WhatEverService" n'est pas prévu. Envisagez D'utiliser un résolveur de données si vous êtes utiliser DataContractSerializer ou ajouter des types qui ne sont pas connus statiquement la liste des types connus - par exemple, en utilisant L'attribut KnownTypeAttribute attribut ou en les ajoutant à la liste des types connus passé à la sérialiseur.

la façon dont j'ai résolu en ajoutant KnownType .

[KnownType(typeof(SomeSubRootType))]
public partial class SomeRootStructureType

cela a été résolu inspiré de cette réponse .

référence: https://msdn.microsoft.com/en-us/library/ms730167 (v = 100).aspx

0
répondu maytham-ɯɐɥʇʎɐɯ 2018-02-19 13:04:09