Не удалось выполнить сериализацию ответа в Web API с помощью Json
Я работаю с ASP.NET MVC 5 Web Api. Я хочу проконсультироваться со всеми моими пользователями.
Я написал api/users
и получаю это:
"Типу ObjectContent'1 не удалось сериализовать тело ответа для типа контента application/json; charset = utf-8 '"
В WebApiConfig я уже добавил эти строки:
HttpConfiguration config = new HttpConfiguration();
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
Но это все еще не работает.
Моя функция для возврата данных такова:
public IEnumerable<User> GetAll()
{
using (Database db = new Database())
{
return db.Users.ToList();
}
}
Ответы
Ответ 1
Когда дело доходит до возврата данных пользователю из Web Api (или любого другого веб-сервиса), я настоятельно рекомендую не передавать объекты, которые поступают из базы данных. Он намного надежнее и удобен в использовании моделей, в которых вы контролируете, как выглядят данные, а не база данных. Таким образом, вам не нужно возиться с форматировщиками так много в WebApiConfig. Вы можете просто создать UserModel с дочерними моделями как свойствами и избавиться от опорных циклов в возвращаемых объектах. Это делает сериализатор намного более счастливым.
Кроме того, нет необходимости удалять форматы или поддерживаемые типы носителей, как правило, если вы просто указываете заголовок "Принимает" в запросе. Игра с этим материалом иногда может сбить с толку.
Пример:
public class UserModel {
public string Name {get;set;}
public string Age {get;set;}
// Other properties here that do not reference another UserModel class.
}
Ответ 2
Если вы работаете с EF, помимо добавления кода ниже на Global.asax
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings
.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
GlobalConfiguration.Configuration.Formatters
.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
Не забывайте импортировать
using System.Data.Entity;
Затем вы можете вернуть свои собственные модели EF
Просто как это!
Ответ 3
Правильный ответ - один из способов пойти, однако это может быть чрезмерным, если вы можете исправить его с помощью одной настройки конфигурации.
Лучше использовать его в конструкторе dbcontext
public DbContext() // dbcontext constructor
: base("name=ConnectionStringNameFromWebConfig")
{
this.Configuration.LazyLoadingEnabled = false;
this.Configuration.ProxyCreationEnabled = false;
}
Ошибка API-интерфейса Asp.Net: тип ObjectContent`1 не смог сериализовать тело ответа для типа содержимого 'application/xml; кодировка = UTF-8'
Ответ 4
Добавьте этот код в global.asax
ниже на Application_Start
:
Обновление от .Ignore
до .Serialize
. Он должен работать.
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize;
GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
Ответ 5
Мне не нравится этот код:
foreach(var user in db.Users)
В качестве альтернативы можно было бы сделать что-то вроде этого, которое сработало для меня:
var listOfUsers = db.Users.Select(r => new UserModel
{
userModel.FirstName = r.FirstName;
userModel.LastName = r.LastName;
});
return listOfUsers.ToList();
Однако я решил использовать решение Lucas Roselli.
Обновление: упрощено путем возврата анонимного объекта:
var listOfUsers = db.Users.Select(r => new
{
FirstName = r.FirstName;
LastName = r.LastName;
});
return listOfUsers.ToList();
Ответ 6
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();
}
}
Ответ 7
Я решил с помощью этого кода в файл WebApiConfig.cs
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
Ответ 8
Также этот сценарий генерирует ту же ошибку:
В случае, когда return является List<dynamic>
для метода web api
Пример:
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; }
}
Итак, для этого сценария используйте [KnownTypeAttribute] в возвращаемом классе (все из них) следующим образом:
[KnownTypeAttribute(typeof(TestClass))]
public class TestClass
{
public string Name { get; set; }
public int Age { get; set; }
}
Это работает для меня!
Ответ 9
Добавление этого в ваш метод Application_Start()
файла Global.asax
должен решить проблему
protected void Application_Start()
{
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings
.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
GlobalConfiguration.Configuration.Formatters
.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
// ...
}
МЕТОД 2: [Не рекомендуется]
Если вы работаете с EntityFramework, вы можете отключить прокси в своем конструкторе класса DbContext. ПРИМЕЧАНИЕ: этот код будет удален, если вы обновите модель
public class MyDbContext : DbContext
{
public MyDbContext()
{
this.Configuration.ProxyCreationEnabled = false;
}
}
Ответ 10
Мой личный фаворит: просто добавьте код ниже App_Start/WebApiConfig.cs
. Это вернет json вместо XML по умолчанию, а также предотвратит возникшую у вас ошибку. Нет необходимости редактировать Global.asax
для удаления XmlFormatter
и т.д.
Тип "ObjectContent`1" не смог сериализовать тело ответа для типа контента "application/xml"; кодировка = UTF-8
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
Ответ 11
Использовать AutoMapper...
public IEnumerable<User> GetAll()
{
using (Database db = new Database())
{
var users = AutoMapper.Mapper.DynamicMap<List<User>>(db.Users);
return users;
}
}
Ответ 12
Используйте следующее пространство имен:
using System.Web.OData;
Вместо:
using System.Web.Http.OData;
Это сработало для меня
Ответ 13
Решение, которое сработало для меня:
-
Используйте [DataContract] для атрибутов класса и [DataMember] для каждого свойства для сериализации. Этого достаточно, чтобы получить результат Json (например, от fiddler).
-
Чтобы получить сериализацию xml, напишите в Global.asax этот код:
var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
xml.UseXmlSerializer = true;
- Прочитайте эту статью, это помогло мне понять сериализацию:
https://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization
Ответ 14
Чтобы добавить к jensendp ответ:
Я передал бы объект модели, созданной пользователем, и использовал значения из этого объекта для установки значений в вашей вновь созданной модели. Например:
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;
}
}
Затем измените свой тип возврата на: IEnumerable<UserInformation>
Ответ 15
![This is my error]()
Я в основном добавляю одну строку, которые они
- entity.Configuration.ProxyCreationEnabled = false;
в 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);
}
}
}
}
![Here is my output:]()
Ответ 16
Вам нужно определить Serializer Formatter в файле WebApiConfig.cs, доступном в папке App_Start, например
Добавление config.Formatters.Remove(config.Formatters.XmlFormatter); // который предоставит вам данные в формате JSON
Добавление config.Formatters.Remove(config.Formatters.JsonFormatter); // который предоставит вам данные в формате XML
Ответ 17
Другим случаем, когда я получил эту ошибку, был то, что запрос базы данных возвращал значение null, но мой тип модели пользователя/вида был установлен как недействительный. Например, изменилось поле UserModel с int
на int?
.
Ответ 18
Это также происходит, когда тип ответа не является общедоступным!
Я вернул внутренний класс, поскольку использовал Visual Studio для генерации типа.
internal class --> public class
Ответ 19
Хотя все приведенные выше ответы верны, можно проверить InnerException> ExceptionMessage.
Если он говорит что-то вроде этого " Экземпляр ObjectContext был удален и больше не может использоваться для операций, требующих подключения ". Это может быть проблемой из-за поведения EF по умолчанию.
Назначив LazyLoadingEnabled = false в конструкторе DbContext, добьемся цели.
public class MyDbContext : DbContext
{
public MyDbContext()
{
this.Configuration.LazyLoadingEnabled = false;
}
}
Более подробное чтение о EagerLoading и LazyLoading поведении EF смотрите в этой статье MSDN.
Ответ 20
В моем случае у меня было похожее сообщение об ошибке:
Типу ObjectContent'1 не удалось сериализовать тело ответа для типа контента application/xml; кодировка = UTF-8'.
Но когда я углубился в это, проблема была:
Тип 'name.SomeSubRootType' с именем контракта данных 'SomeSubRootType://schemas.datacontract.org/2004/07/WhatEverService' не ожидается. Рассмотрите возможность использования DataContractResolver, если вы используете DataContractSerializer или добавляете любые типы, которые не известны статически, в список известных типов - например, с помощью атрибута KnownTypeAttribute или добавляя их в список известных типов, передаваемых в сериализатор.
Способ, который я решил, добавив KnownType
.
[KnownType(typeof(SomeSubRootType))]
public partial class SomeRootStructureType
Это было решено на основе этого ответа.
Ссылка: https://msdn.microsoft.com/en-us/library/ms730167(v=vs.100).aspx
Ответ 21
Visual Studio 2017 или 2019 совершенно не задумывается над этим, поскольку сама Visual Studio требует, чтобы вывод был в формате json, а формат Visual Studio по умолчанию - " XmlFormat" (config.Formatters.XmlFormatter).
Visual Studio должна делать это автоматически, а не доставлять разработчикам столько хлопот.
Чтобы исправить эту проблему, перейдите в файл WebApiConfig.cs и добавьте
var json = config.Formatters.JsonFormatter; json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects; config.Formatters.Remove(config.Formatters.XmlFormatter);
после " config.MapHttpAttributeRoutes(); " в методе Register (конфигурация HttpConfiguration). Это позволит вашему проекту производить вывод в формате json.
Ответ 22
В моем случае я решил воссоздать базу данных. Я внес некоторые изменения в модель и, запустив Update-Database в консоли диспетчера пакетов, получил следующую ошибку:
"Оператор ALTER TABLE конфликтует с ограничением FOREIGN KEY" FK_dbo.Activities_dbo.Projects_ProjectId ". Конфликт произошел в базе данных" TrackEmAllContext-20190530144302 ", таблица" dbo.Projects ", столбец" Id "."
Ответ 23
В случае: если добавление кода в WebApiConfig.cs или Global.asax.cs не работает для вас:
.ToList();
Добавьте функцию .ToList().
Я опробовал каждое решение, но у меня сработало следующее:
var allShops = context.shops.Where(s => s.city_id == id)**.ToList()**;
return allShops;
Я надеюсь, что это помогает.
Ответ 24
Добавьте строку ниже
this.Configuration.ProxyCreationEnabled = false;
Два способа использовать ProxyCreationEnabled
как false
.
-
Добавьте его в конструктор DBContext
public ProductEntities() : base("name=ProductEntities")
{
this.Configuration.ProxyCreationEnabled = false;
}
ИЛИ ЖЕ
-
Добавьте строку внутри метода Get
public IEnumerable<Brand_Details> Get()
{
using (ProductEntities obj = new ProductEntities())
{
this.Configuration.ProxyCreationEnabled = false;
return obj.Brand_Details.ToList();
}
}
Ответ 25
Используйте [Serializable] для класса:
Пример:
[Serializable]
public class UserModel {
public string Name {get;set;}
public string Age {get;set;}
}
Это сработало для меня!