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 type 'ObjectContent`1' n'a pas pu 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 pour les données de retour est la suivante:
public IEnumerable<User> GetAll()
{
using (Database db = new Database())
{
return db.Users.ToList();
}
}
Lorsque vient le temps de renvoyer des données au consommateur à partir de Web Api (ou de tout autre service Web), je recommande vivement de ne pas restituer les entités provenant 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 sur l'apparence des données et non sur la base de données. Ainsi, vous n'avez pas à vous soucier des formateurs dans WebApiConfig. Vous pouvez simplement créer un UserModel qui a des modèles enfants en tant que propriétés et supprimer les boucles de référence dans les objets de retour. Cela rend le sérialiseur beaucoup plus heureux.
En outre, il n'est généralement pas nécessaire de supprimer les formateurs ou les types de supports pris en charge si vous ne spécifiez que l'en-tête "Accepter" dans la demande. Jouer avec ce genre de choses 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.
}
Si vous travaillez avec EF, en plus d'ajouter le code ci-dessous sur Global.asax
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;
Ensuite, vous pouvez retourner vos propres modèles EF
Aussi simple que cela!
La bonne réponse est un bon moyen d’aller, mais c’est exagéré de pouvoir le corriger à l’aide d’un paramètre de configuration.
Mieux vaut l'utiliser dans le constructeur de dbcontext
public DbContext() // dbcontext constructor
: base("name=ConnectionStringNameFromWebConfig")
{
this.Configuration.LazyLoadingEnabled = false;
this.Configuration.ProxyCreationEnabled = false;
}
Ajoutez ce code à global.asax
ci-dessous sur Application_Start
:
Mettre à jour de .Ignore
à .Serialize
. Ça doit marcher.
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize;
GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
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();
}
}
Je n'aime pas ce code:
foreach(var user in db.Users)
Comme alternative, on pourrait faire quelque chose comme ça, 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 en renvoyant un objet anonyme:
var listOfUsers = db.Users.Select(r => new
{
FirstName = r.FirstName;
LastName = r.LastName;
});
return listOfUsers.ToList();
Je l'ai résolu en utilisant ce code dans le fichier WebApiConfig.cs
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
Ajouter ceci dans votre méthode Application_Start()
de Global.asax
devrait résoudre le problème
protected void Application_Start()
{
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings
.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
GlobalConfiguration.Configuration.Formatters
.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
// ...
}
METHODE 2: [Non recommandé]
Si vous travaillez avec EntityFramework, vous pouvez désactiver le proxy dans votre constructeur de classe DbContext. NOTE: ce code sera supprimé si vous mettez à jour le modèle
public class MyDbContext : DbContext
{
public MyDbContext()
{
this.Configuration.ProxyCreationEnabled = false;
}
}
Il y a aussi ce scénario qui génère la même erreur:
Si le retour est une méthode List<dynamic>
to web api
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 le [KnownTypeAttribute] dans la classe de retour (tous) comme ceci:
[KnownTypeAttribute(typeof(TestClass))]
public class TestClass
{
public string Name { get; set; }
public int Age { get; set; }
}
Cela fonctionne pour moi!
Mon préféré: ajoutez simplement le code ci-dessous à App_Start/WebApiConfig.cs
. Cela retournera json au lieu de XML par défaut et empêchera également l'erreur que vous avez eue. Pas besoin de modifier Global.asax
pour supprimer XmlFormatter
etc.
Le type 'ObjectContent`1' n'a pas pu sérialiser le corps de la réponse pour le type de contenu 'application/xml; jeu de caractères = utf-8
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
Utilisez l'espace de noms suivant:
using System.Web.OData;
Au lieu de :
using System.Web.Http.OData;
Ça a fonctionné pour moi
Solution qui a fonctionné pour moi:
Utilisez [DataContract] pour la classe et les attributs [DataMember] pour chaque propriété à sérialiser. Cela suffit pour obtenir le résultat Json (par exemple de fiddler).
Pour obtenir la sérialisation XML, écrivez dans Global.asax le code suivant:
var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter; xml.UseXmlSerializer = true;
Utiliser AutoMapper ...
public IEnumerable<User> GetAll()
{
using (Database db = new Database())
{
var users = AutoMapper.Mapper.DynamicMap<List<User>>(db.Users);
return users;
}
}
Vous devrez définir le formateur de sérialiseur dans WebApiConfig.cs disponible dans le dossier App_Start, comme
Ajout de config.Formatters.Remove (config.Formatters.XmlFormatter); // qui vous fournira des données au format JSON
Ajout de config.Formatters.Remove (config.Formatters.JsonFormatter); // qui vous fournira des données au format XML
Pour ajouter à la réponse de jensendp:
Je voudrais transmettre l'entité à un modèle créé par l'utilisateur et utiliser les valeurs de cette entité pour définir les valeurs de votre modèle nouvellement 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;
}
}
Puis changez votre type de retour en: IEnumerable<UserInformation>
J'ajoute essentiellement une ligne qu'ils sont
à UsersController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using UserDataAccess;
namespace SBPMS.Controllers
{
public class UsersController : ApiController
{
public IEnumerable<User> Get() {
using (SBPMSystemEntities entities = new SBPMSystemEntities()) {
entities.Configuration.ProxyCreationEnabled = false;
return entities.Users.ToList();
}
}
public User Get(int id) {
using (SBPMSystemEntities entities = new SBPMSystemEntities()) {
entities.Configuration.ProxyCreationEnabled = false;
return entities.Users.FirstOrDefault(e => e.user_ID == id);
}
}
}
}
Dans mon cas, j'ai eu un message d'erreur similaire:
Le type 'ObjectContent`1' n'a pas pu sérialiser le corps de la réponse pour le type de contenu 'application/xml; jeu de caractères = utf-8 '.
Mais quand j'y ai plongé plus profondément, le problème était:
Tapez 'name.SomeSubRootType' avec le nom du contrat de données 'SomeSubRootType: //schemas.datacontract.org/2004/07/WhatEverService' n'est pas attendu. Pensez à utiliser DataContractResolver si vous utilisez DataContractSerializer ou ajoutez des types non connus statiquement à la liste des types connus, par exemple, en utilisant l'attribut KnownTypeAttribute ou en les ajoutant à la liste des types connus transmis au sérialiseur.
La façon dont j'ai résolu en ajoutant KnownType
.
[KnownType(typeof(SomeSubRootType))]
public partial class SomeRootStructureType
Ceci a été résolu inspiré de ceci réponse .
Référence: https://msdn.Microsoft.com/en-us/library/ms730167 (v = vs.100) .aspx
Dans mon cas, j'ai résolu de recréer la base de données. J'ai apporté des modifications à un modèle et en lançant Update-Database dans la console du gestionnaire de packages, l'erreur suivante s'est produite:
"L'instruction ALTER TABLE a été en conflit avec la contrainte FOREIGN KEY" FK_dbo.Activities_dbo.Projects_ProjectId ". Le conflit s'est produit dans la base de données" TrackEmAllContext-20190530144302 ", table" dbo.Projects ", colonne" Id "."
Dans le cas où: Si vous ajoutez du code à WebApiConfig.cs ou Global.asax.cs ne fonctionne pas pour vous:
.ToList();
Ajoutez la fonction .ToList ().
J'ai essayé toutes les solutions mais les solutions suivantes ont fonctionné pour moi:
var allShops = context.shops.Where(s => s.city_id == id)**.ToList()**;
return allShops;
J'espère que ça aide.
Visual Studio 2017 ou 2019 est totalement irréfléchi, car Visual Studio exige lui-même que la sortie soit au format json , alors que le format par défaut de Visual Studio est " XmlFormat "(config.Formatters.XmlFormatter) .
Visual Studio doit le faire automatiquement au lieu de causer tant de problèmes aux développeurs.
Pour corriger ce problème, accédez au fichier WebApiConfig.cs et ajoutez
var json = config.Formatters.JsonFormatter; json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects; config.Formatters.Remove (config.Formatters.XmlFormatter);
après " config.MapHttpAttributeRoutes (); " dans le registre (HttpConfiguration config) méthode. Cela permettrait à votre projet de générer une sortie JSON.
Un autre cas où j'ai reçu cette erreur était lorsque ma requête de base de données a renvoyé une valeur null alors que mon type de modèle utilisateur/vue était défini sur non nullable. Par exemple, changer mon champ UserModel de int
à int?
résolu.
Cela se produit également lorsque le type de réponse n'est pas public! J'ai renvoyé une classe interne car j'ai utilisé Visual Studio pour générer le type.
internal class --> public class
Ajouter la ligne ci-dessous
this.Configuration.ProxyCreationEnabled = false;
Deux façons d'utiliser ProxyCreationEnabled
comme false
.
Ajoutez-le à l'intérieur de DBContext
Constructeur
public ProductEntities() : base("name=ProductEntities")
{
this.Configuration.ProxyCreationEnabled = false;
}
OU
Ajouter la ligne à l'intérieur de la méthode Get
public IEnumerable<Brand_Details> Get()
{
using (ProductEntities obj = new ProductEntities())
{
this.Configuration.ProxyCreationEnabled = false;
return obj.Brand_Details.ToList();
}
}
Bien que toutes les réponses ci-dessus soient correctes, il peut être utile de vérifier le InnerException> ExceptionMessage .
Si elle indique quelque chose comme ceci "T , l'instance ObjectContext a été supprimée et ne peut plus être utilisée pour des opérations nécessitant une connexion. ". Cela pourrait être un problème en raison du comportement par défaut de l'EF.
En assignant LazyLoadingEnabled = false dans votre constructeur DbContext fera l'affaire.
public class MyDbContext : DbContext
{
public MyDbContext()
{
this.Configuration.LazyLoadingEnabled = false;
}
}
Pour plus d'informations sur le comportement de EF dans EagerLoading et LazyLoading, reportez-vous à ceci Article MSDN .
Utilisez [Serializable] pour la classe:
Exemple:
[Serializable]
public class UserModel {
public string Name {get;set;}
public string Age {get;set;}
}
Cela a fonctionné pour moi!