Вопрос:

Failed to serialize the response in Web API with Json

c# asp.net json asp.net-web-api

156253 просмотра

23 ответа

759 Репутация автора

I am working with ASP.NET MVC 5 Web Api. I want consult all my users.

I wrote api/users and I receive this:

"The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'"

In WebApiConfig, already I added these lines:

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

But it still doesn't work.

My function for return data is this:

public IEnumerable<User> GetAll()
{
    using (Database db = new Database())
    {
        return db.Users.ToList();
    }
}
Автор: CampDev Источник Размещён: 16.04.2014 02:56

Ответы (23)


69 плюса

1884 Репутация автора

Решение

When it comes to returning data back to the consumer from Web Api (or any other web service for that matter), I highly recommend not passing back entities that come from a database. It is much more reliable and maintainable to use Models in which you have control of what the data looks like and not the database. That way you don't have to mess around with the formatters so much in the WebApiConfig. You can just create a UserModel that has child Models as properties and get rid of the reference loops in the return objects. That makes the serializer much happier.

Also, it isn't necessary to remove formatters or supported media types typically if you are just specifying the "Accepts" header in the request. Playing around with that stuff can sometimes make things more confusing.

Example:

public class UserModel {
    public string Name {get;set;}
    public string Age {get;set;}
    // Other properties here that do not reference another UserModel class.
}
Автор: jensendp Размещён: 16.04.2014 03:12

6 плюса

147 Репутация автора

Есть также этот сценарий, который генерирует ту же ошибку:

В случае возврата List<dynamic>в метод веб-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; }
}

Это работает для меня!

Автор: Alex Размещён: 24.10.2014 05:20

130 плюса

2404 Репутация автора

Если вы работаете с 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

Просто как тот!

Автор: Lucas Roselli Размещён: 01.03.2015 01:08

10 плюса

262 Репутация автора

Мне не нравится этот код:

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();

Однако в итоге я воспользовался решением Лукаса Розелли.

Обновление: упрощено путем возврата анонимного объекта:

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

return listOfUsers.ToList();
Автор: Kasper Halvas Jensen Размещён: 09.04.2015 01:40

1 плюс

351 Репутация автора

Чтобы добавить к ответу 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>

Автор: Greg A Размещён: 05.05.2015 01:27

51 плюса

1649 Репутация автора

Правильный ответ - это один из способов, но это излишне, когда вы можете исправить это одним из параметров конфигурации.

Лучше использовать его в конструкторе 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'

Автор: Md. Alim Ul Karim Размещён: 04.07.2015 01:40

2 плюса

2111 Репутация автора

Использовать AutoMapper ...

public IEnumerable<User> GetAll()
    {
        using (Database db = new Database())
        {
            var users = AutoMapper.Mapper.DynamicMap<List<User>>(db.Users);
            return users;
        }
    }
Автор: Proximo Размещён: 04.09.2015 04:30

0 плюса

11 Репутация автора

Другой случай, когда я получил эту ошибку, был, когда мой запрос к базе данных возвратил нулевое значение, но мой тип модели пользователь / представление был установлен как не обнуляемый. Например, изменение моего UserModel поля от intдо int?решена.

Автор: marshall Размещён: 14.10.2015 02:49

32 плюса

1109 Репутация автора

Добавьте этот код global.asaxниже Application_Start:

Обновление с .Ignoreдо .Serialize. Это должно работать.

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize;
            GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
Автор: Bimal Das Размещён: 14.01.2016 06:48

4 плюса

17790 Репутация автора

Мой личный фаворит: просто добавьте код ниже App_Start/WebApiConfig.cs. Это вернет json вместо XML по умолчанию, а также предотвратит возникшую ошибку. Нет необходимости редактировать, Global.asaxчтобы удалить XmlFormatterи т. Д.

Типу ObjectContent`1 не удалось сериализовать тело ответа для типа содержимого application / xml; кодировка = UTF-8

config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
Автор: Ogglas Размещён: 12.08.2016 11:24

10 плюса

109 Репутация автора

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();
    }
}
Автор: Aykut Размещён: 16.09.2016 02:21

2 плюса

21 Репутация автора

Используйте следующее пространство имен:

using System.Web.OData;

Вместо :

using System.Web.Http.OData;

У меня сработало

Автор: Harish K Размещён: 03.11.2016 10:40

2 плюса

1199 Репутация автора

Решение, которое сработало для меня:

  1. Используйте [DataContract] для класса и атрибуты [DataMember] для каждого свойства для сериализации. Этого достаточно, чтобы получить результат Json (например, из fiddler).

  2. Чтобы получить сериализацию XML, напишите в Global.asax этот код:

    var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter; xml.UseXmlSerializer = true;

  3. Прочитайте эту статью, она помогла мне понять сериализацию: https://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization
Автор: Lapenkov Vladimir Размещён: 16.11.2016 07:07

0 плюса

433 Репутация автора

Это также происходит, когда тип ответа не является общедоступным! Я вернул внутренний класс, поскольку использовал Visual Studio для генерации типа.

internal class --> public class
Автор: Vanice Размещён: 15.11.2017 03:52

0 плюса

737 Репутация автора

Хотя все приведенные выше ответы верны, можно проверить InnerException> ExceptionMessage .

Если он говорит что-то вроде этого « Экземпляр ObjectContext был удален и больше не может использоваться для операций, требующих подключения ». Это может быть проблемой из-за поведения EF по умолчанию.

Назначая LazyLoadingEnabled = ложный в конструкторе DbContext будет делать трюк.

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

Более подробное чтение о EagerLoading и LazyLoading поведении EF смотрите в этой статье MSDN .

Автор: Bhramar Размещён: 29.12.2017 12:39

6 плюса

217 Репутация автора

Добавление этого в ваш 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;
  }
}
Автор: Er Suman G Размещён: 12.01.2018 04:31

0 плюса

11696 Репутация автора

В моем случае у меня было похожее сообщение об ошибке:

Типу 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

Автор: maytham-ɯɐɥʇʎɐɯ Размещён: 19.02.2018 12:21

6 плюса

1958 Репутация автора

Я решил с помощью этого кода в файл WebApiConfig.cs

var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects; 
config.Formatters.Remove(config.Formatters.XmlFormatter);
Автор: aemre Размещён: 23.03.2018 01:28

1 плюс

29 Репутация автора

Это моя ошибка

Я в основном добавляю одну строку, которые они

  • 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);
            }
        }
    }
}

Вот мой вывод:

Автор: GUL EDA AYDEMİR Размещён: 24.04.2019 09:36

0 плюса

53 Репутация автора

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.

Автор: William Hou Размещён: 30.04.2019 08:27

0 плюса

71 Репутация автора

В моем случае я решил воссоздать базу данных. Я внес некоторые изменения в модель и, запустив Update-Database в консоли диспетчера пакетов, получил следующую ошибку:

«Оператор ALTER TABLE конфликтует с ограничением FOREIGN KEY« FK_dbo.Activities_dbo.Projects_ProjectId ». Конфликт произошел в базе данных« TrackEmAllContext-20190530144302 », таблица« dbo.Projects », столбец« Id »."

Автор: Manuel Sansone Размещён: 30.05.2019 02:46

0 плюса

19 Репутация автора

В случае: если добавление кода в WebApiConfig.cs или Global.asax.cs не работает для вас:

.ToList();

Добавьте функцию .ToList ().

Я опробовал каждое решение, но у меня сработало следующее:

var allShops = context.shops.Where(s => s.city_id == id)**.ToList()**;
return allShops;

Я надеюсь, что это помогает.

Автор: Catalyst Размещён: 05.06.2019 10:24

0 плюса

1 Репутация автора

Добавьте строку ниже

this.Configuration.ProxyCreationEnabled = false;

Два способа использования в ProxyCreationEnabledкачестве false.

  1. Добавьте это внутри DBContextКонструктора

    public ProductEntities() : base("name=ProductEntities")
    {
        this.Configuration.ProxyCreationEnabled = false;
    }
    

ИЛИ ЖЕ

  1. Добавьте строку внутри Getметода

    public IEnumerable<Brand_Details> Get()
    {
        using (ProductEntities obj = new ProductEntities())
        {
            this.Configuration.ProxyCreationEnabled = false;
            return obj.Brand_Details.ToList();
        }
    }
    
Автор: Sudipta Saha Размещён: 13.06.2019 05:55
Вопросы из категории :
32x32