WebApi Odata, возвращающий сложный тип

У меня есть простая модель данных, состоящая из двух сущностей

public class product 
{
     public int ID {get;set;}
     public string Name {get;set;}
}

public class supplier
{
    public int ID {get;set;}
    public string Name {get;set;}
    public IEnumerable<product> products {get;set;}
}

Теперь с моего контроллера odata WebApi я хочу вернуть поставщику все его продукты. Но я не могу заставить это работать, просто возвращая поставщика и эффективно удаляя информацию о продукте. Метод контроллера — это простой метод Get и GetEntityByKey. Моя конфигурация выглядит следующим образом.

 ODataModelBuilder modelBuilder = new ODataConventionModelBuilder();
            modelBuilder.EntitySet<supplier>("supplier");
            modelBuilder.EntitySet<product>("product");

Есть ли параметры конфигурации, которых мне не хватает, чтобы заставить это работать?


person James Baldwinson    schedule 30.05.2013    source источник


Ответы (2)


Вы не упомянули URI, который вы используете для получения объекта поставщика, но я предполагаю, что он выглядит примерно так: http://.../ServiceRoot.svc/supplier(1). По умолчанию в OData свойства навигации не раскрываются; то есть по умолчанию запрос поставщика не будет включать идентификаторы и имена связанных продуктов, если только вы не запросите их явно с помощью параметра запроса $expand. Например: http://.../ServiceRoot.svc/supplier(1)?$expand=products.

Если вы не расширите свойство навигации, то свойство products поставщика будет отображаться как просто набор ссылок на сущности продукта. Если вы не видите ссылок на продукты в полезной нагрузке ответа, это может быть связано с тем, что вы используете новый формат OData v3 JSON, в котором могут отсутствовать навигационные ссылки, соответствующие общим соглашениям URI OData (поскольку клиент может генерировать такие сама ссылка).

Если вы включите URI запроса и полезную нагрузку, которую вы возвращаете, я смогу немного яснее понять, что происходит в вашей ситуации.

Небольшое примечание по терминологии: «сложный тип» в OData обычно относится к структурному типу, не имеющему идентификатора. Типичным примером этого может быть тип Address, который представляет собой тип значения, который имеет несколько компонентов (город, страна, улица и т. д.), но не требует собственного ключа. Здесь вы говорите о навигации между сущностями.

person Jen S    schedule 31.05.2013
comment
Чтобы основываться на ответе Джен, $expand не поддерживается в первом выпуске OData веб-API в NuGet, но в настоящее время он доступен в наших ночных сборках и должен быть доступен в следующем выпуске. Дополнительную информацию о том, как получить доступ к нашим ночным журналам, см. в этом сообщении в блоге: blogs.msdn.com/b/henrikn/archive/2012/06/01/ - person Youssef Moussaoui; 31.05.2013
comment
Спасибо, что вернулись ко мне. По крайней мере, я знаю, что это не параметр конфигурации, а его odata сама по себе удаляет дополнительную информацию о «продукте», а не включает ее в возвращаемый Json, как это было бы в не-odata WebApi Get. Есть ли дата выхода следующей версии? - person James Baldwinson; 31.05.2013
comment
@YoussefMoussaoui Я получил ночную сборку, но не могу заставить простой пример работать, обратите внимание, что я использую fiddler composer мой веб-сайт:port/odata/suppler(1)?$expand=products. Код в контроллере webapi выглядит следующим образом protected override supplier GetEntityByKey(int key) { supplier s = new supplier() { Name = "Test", ID=1 }; s.products = new List<product>(){new product() { ID = 1, Name = "P1" }, new product() { Name = "P2", ID = 2 }}; return s; } - person James Baldwinson; 31.05.2013
comment
@YoussefMoussaoui - возвращенный JSON не содержит информации о продукте, а только информацию о поставщике. Отладка контроллера GetEntityKey Я вижу, что возвращаемое значение содержит продукты, но при просмотре Json в Fiddler продукты по-прежнему удалены. Он работает правильно для Get (возврат поставщика и продуктов), но не для GetEntityByKey, где он возвращает только поставщика. Спасибо Юссеф за ваше время на это. - person James Baldwinson; 01.06.2013
comment
Хорошо, причина, по которой он работает для Get, но не для Get по ключу, заключается в том, что Get помечен атрибутом Queryable, а ваш Get — нет. На самом деле я бы рекомендовал вам получить от ODataController вместо EntitySetController, скопировав любой код, который вам нужен. И что вы помечаете ключ Get by атрибутом Queryable. Документации пока не так много, потому что мы еще ничего не выпустили, но если вы хотите создать для этого отдельный вопрос о переполнении стека, я могу попытаться предоставить пример кода. - person Youssef Moussaoui; 01.06.2013
comment
Еще раз спасибо @YoussefMoussaoui, мне не нужен пример кода, который указал мне правильное направление с помощью OdataContoller и устранил проблему с GetEntityKey. - person James Baldwinson; 01.06.2013

Возможно, попробуйте использовать QueryableAttribute. Смотри сюда:

Расширить поддержку

2) Поддержка $select и $expand для отдельных объектов через QueryableAttribute.

person Roman Bats    schedule 02.06.2013