Не удалось выполнить сериализацию ответа в 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.

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

Ответ 25

Используйте [Serializable] для класса:

Пример:

[Serializable]
public class UserModel {
    public string Name {get;set;}
    public string Age {get;set;}
}

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