Ошибка API-интерфейса Asp.Net: тип "ObjectContent`1" не смог сериализовать тело ответа для типа контента "application/xml"; кодировка = UTF-8'

Простейший пример этого, я получаю коллекцию и пытаюсь вывести ее через Web API:

// GET api/items
public IEnumerable<Item> Get()
{
    return MyContext.Items.ToList();
}

И я получаю сообщение об ошибке:

Объект типа
'System.Data.Objects.ObjectQuery`1 [Dcip.Ams.BO.EquipmentWarranty] не могут быть преобразованы в тип
'System.Data.Entity.DbSet`1 [Dcip.Ams.BO.EquipmentWarranty]

Это довольно распространенная ошибка, связанная с новыми прокси-серверами, и я знаю, что могу исправить ее, установив:

MyContext.Configuration.ProxyCreationEnabled = false;

Но это поражает цель многих моих попыток. Есть ли лучший способ?

Ответ 1

Я предлагаю отключить создание прокси только в том месте, где вам не нужно, или вызывает у вас проблемы. Вам не нужно отключать его во всем мире, вы можете просто отключить текущий контекст БД с помощью кода...

    [HttpGet]
    [WithDbContextApi]
    public HttpResponseMessage Get(int take = 10, int skip = 0)
    {
        CurrentDbContext.Configuration.ProxyCreationEnabled = false;

        var lista = CurrentDbContext.PaymentTypes
            .OrderByDescending(x => x.Id)
            .Skip(skip)
            .Take(take)
            .ToList();

        var count = CurrentDbContext.PaymentTypes.Count();

        return Request.CreateResponse(HttpStatusCode.OK, new { PaymentTypes = lista, TotalCount = count });
    }

Здесь я только отключил ProxyCreation в этом методе, потому что для каждого запроса создается новый DBC-контекст, и поэтому я отключил ProxyCreation для этого случая. Надеюсь, что это поможет.

Ответ 2

если у вас есть свойства навигации, и вы не хотите сделать их не виртуальными, вам следует использовать JSON.NET и изменить конфигурацию в App_Start на использование JSON not XML!
после установки JSON.NET From NuGet, вставьте этот код в WebApiConfig.cs в метод Register

var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);

Ответ 3

Если у вас есть свойства навигации, сделайте их не виртуальными. Картирование по-прежнему будет работать, но это предотвратит создание объектов динамического прокси, которые не могут быть сериализованы.]

Отсутствие ленивой загрузки в WebApi прекрасен, поскольку у вас нет постоянного соединения, и вы все равно запускали .ToList().

Ответ 4

Я просто отключил прокси-классы по необходимости:

    // GET: ALL Employee
    public IEnumerable<DimEmployee> Get()
    {
        using (AdventureWorks_MBDEV_DW2008Entities entities = new AdventureWorks_MBDEV_DW2008Entities())
        {
            entities.Configuration.ProxyCreationEnabled = false;
            return entities.DimEmployees.ToList();
        }
    }

Ответ 5

Это помогло мне:
Добавьте следующий код в Application_Start функцию Global.asax.cs

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

Ответ 6

В моем случае возвращаемый объект имеет свойство внутри него с типом, у которого не было конструктора без аргументов/по умолчанию. Добавив конструктор нулевого аргумента к этому типу, объект может быть успешно сериализован.