WebAPI v2 — сериализация JSON для расширения OData приводит к неправильному отображению $type

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

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

Вопрос:

Я только что обновил приложение MVC4 / WebAPI v1 до MVC5 WebApi2..

Похоже, что после этого обновления Json.Сетевой сериализатор больше не будет включать правильный тип $для запросов, использующих метод расширения OData $. смотрите Ниже пример того, что я имею в виду…

ПРАВИЛЬНО:

запрос: http://url.com/api/Studies/277/Sites

ответ:

 {
$id: "1"
$type: "LGCYDAPI.Domain.Model.StudySiteWithContacts, LGCYDAPI.Domain.Model"
Contacts: [
{
$id: "2"
$type: "LGCYDAPI.Domain.Model.ContactRelatedToSite, LGCYDAPI.Domain.Model"
ContactID: -38445
}],
SiteID: 38445
}
  

НЕВЕРНО:

запрос: http://url.com/api/Studies/277/Sites ?$развернуть=Контакты

ответ:

 {
$id: "1"
$type: "System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Object, mscorlib]], mscorlib"
Contacts: [
{
$id: "2"
$type: "System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Object, mscorlib]], mscorlib"
ContactID: -38445
}],
SiteID: 38445}
  

Наряду со сборками MVC и WebAPI я обновил JSON.NET с 5.0.6 по 6.0.3, что, как я думал, и было проблемой.. однако я вернулся к версии 5, и это не решило проблему, поэтому я вернулся к версии 6. Также обновлены nugets OData — мои текущие версии — Microsoft.Data.OData= 5.6.0 и Microsoft.AspNet.WebAPI.OData=5.1.2.

Настройки сериализатора JSON:

 pConfiguration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
        pConfiguration.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
        pConfiguration.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Objects;

        pConfiguration.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
  

Ответ №1:

Полезная нагрузка $type в ответе предназначена для фактического объекта, подлежащего сериализации.

При применении $expand к результату структура возвращаемого объекта изменяется с LGCYDAPI.Domain.Model.StudySiteWithContacts на SelectExpandWrapper .

Таким образом, вы не можете получить ожидаемый тип сайтов с применением $expand.

Для SelectExpandWrapper структуры проверьте это:

https://aspnetwebstack.codeplex.com/wikipage?title=$select and $expand support

Комментарии:

1. Спасибо за информацию! Есть ли у вас какие-либо идеи о том, какие альтернативы или хаки я мог бы сделать, чтобы заставить $type читать фактический тип объекта? Breeze в значительной степени зависит от этого…

2. 1. попробуйте написать обработчик сообщений для анализа типа содержимого ответа, а затем сохранить его в ответе. 2. попробуйте отправить еще один почти такой же запрос, но без параметров запроса select и expand, чтобы получить фактический тип. 3. не используйте параметры выбора и запроса в uri вашего запроса.