2015-11-06 10 views
5

У меня есть рабочий (упрощенный) ODataController следующим образом.Как создавать объекты ODataQueryOptions

public class MyTypeController : ODataController 
{ 
    [HttpGet] 
    [EnableQuery] 
    [ODataRoute("myTypes")] 
    public IQueryable<MyType> GetMyTypes(ODataQueryOptions<MyType> options) 
    { 
    return _repo.myResultsAsQueryable(); 
    } 
} 

Я хотел бы иметь возможность вызывать этот метод с сервера и сделать это мне нужно создать экземпляр ODataQueryOptions который требует ODataQueryContext.

Есть примеры того, как это сделать (например, here и here), но все они ссылаются на предыдущую версию OData. Конструктор ODataQueryContext в настоящее время требует третьего аргумента(), который не рассматривается ни в одном из примеров, которые я могу найти.

Edit: @snow_FFFFFF, Вот еще контекст ... Я понимаю, что я могу просто потреблять конечную OData через HttpClient, но я хотел бы взаимодействовать с IQueryable непосредственно, как вы говорите.

Проблема в том, что приложение, над которым я работаю, позволяет пользователям создавать фильтры (например, сложные поисковые системы), которые могут быть сохранены и позже вызваны другими пользователями. От JS-клиента они просто ищут фильтр по id и выдают запрос к конечной точке OData с фильтром, применяемым к строке запроса. Это очень хорошо работает с клиентской стороны, но я хотел бы иметь возможность делать что-то подобное с серверной стороны.

Это то, что я хотел бы сделать, но как я могу создать экземпляр аргумента ODataPath?

public IQueryable<MyType> FilterMyTypes(int filterID) 
{ 
    // lookup filter by filterID from db... 
    filter = "$filter=Status eq 1"; // for example... 

    ODataPath path = // but how can I get the path!!! 
    new ODataQueryContext(edmModel, typeof(MyType), path); 

    var uri = new HttpRequestMessage(HttpMethod.Get, "http://localhost:56339/mytypes?" + filter); 
    var opts = new ODataQueryOptions<MyType>(ctx, uri); 

    var results = new MyTypeController().GetMyTypes(opts); 
} 

Другое применение этого будет поддерживать динамическую группировку, как показано ниже:

[HttpGet] 
[Route("myTypes/{filterID:int}/groupby/{groupByFieldName}")] 
public IHttpActionResult GroupMyTypes(int filterID, string groupByFieldName) 
{ 
    // For example: get all Active MyTypes and group by AssignedToUserID... 

    // Get the results of the filter as IQueryable... 
    var results = FilterMyTypes(filterID); 

    // group on groupByFieldName 
    var grouped = results.GroupBy(x => GetPropertyValue(x,groupByFieldName)); 

    // select the groupByFieldName and the count 
    var transformedResults = grouped.Select(g => new { g.Key, Count = g.Count() }); 

    return Ok(transformedResults); 
} 
+1

В http://github.com/OData/WebApi есть много тестовых примеров, к которым вы можете обратиться. Например, ODataQueryContext, вы можете обратиться к: https://github.com/OData/WebApi/blob/master/OData/test/UnitTest/System.Web.OData.Test/OData/Query/ODataQueryContextTests.cs#L181- L200 –

+0

Спасибо Сэму, я попробую это. Не используется для MS с открытым исходным кодом ... –

+0

Sam. Ты восхитителен! Если вы положите это в ответ, я могу принять его. Спасибо. Работал как шарм. –

ответ

3

Конечно. ODataPath - это список ODataPathSegment (s), который должен отслеживать OData Uri spec.

В Web API OData, это легко создать экземпляр ODataPath, например:

IEdmModel model = GetEdmModel(); 
IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet(setName); 
ODataPath path = new ODataPath(new EntitySetPathSegment(entitySet)); 

выше path следит за спецификации OData, что он имеет OData шаблон как:

~/entityset 

Подробнее (коды) можно найти here

+1

По состоянию на 1/25/2017 последняя стабильная версия 'Microsoft.AspNet.OData' - v6.0.0. Похоже, что уже нет класса EntitySetPathSegment. Мне нужно было понизить рейтинг в NuGet до 5.9.1. В противном случае, ОЧЕНЬ полезный вопрос, и я действительно оценил ссылку на тестовые примеры исходного кода. – asporter

+0

borked ссылка на сегодня. –

0

Ваш OData контроллер обеспечивает интерфейс HTTP к вашим данным, не вы должны получить к нему доступ через HTTP (даже если с сервера)? Существует В.С. надстройку для создания OData код клиента здесь:

https://visualstudiogallery.msdn.microsoft.com/9b786c0e-79d1-4a50-89a5-125e57475937

Или, если вы делаете это из того же проекта, почему бы не общий метод, который возвращает IQueryable, который может быть вызван из ваш код или контроллер?

UPDATE: На основе дополнительной информации в исходном вопросе:

Если у вас есть ODataQueryOptions, определенный в методе контроллера, это позволит вам разобрать хорошо сформированную OData запроса, призывающий этот метод. Я использовал это, когда мне нужно было перевести части запроса odata, потому что мне нужно было запросить несколько источников данных, чтобы вернуть окончательный результат.

Похоже, вы хотите что-то, что принимает параметры и параметры, отличные от odata. Для этого, вероятно, нужно посмотреть на пользовательские действия и или функции (если вы просто возвращает данные, вероятно, функция):

http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/odata-actions-and-functions

UPDATE # 2: И после более детального чтения, я думаю, Я пропустил ваш вопрос - у меня нет ответа, но я буду играть с ним. Не можете ли вы просто изменить сам URL (в отличие от создания экземпляров параметров запроса?

UPDATE # 3: Я думаю, вам будет сложно с этим поработать, думая, что он получает запрос одата ... это не действительно запрос одата. Назад ко второму варианту упомянутого в моем оригинальный ответ - почему не распространенный метод, который можно использовать и OData контроллер может использовать - что-то вроде этого:

// some sort of helper class 
public class HelperObject 
{ 
    public static IQueryable<MyType> GetGroupedValues(int filterID, string groupByFieldName) 
    { 
     // all your code/logic here 
    } 
} 

// your odata controller uses the helper 
[HttpGet] 
[Route("myTypes/{filterID:int}/groupby/{groupByFieldName}")] 
public IHttpActionResult GroupMyTypes(int filterID, string groupByFieldName) 
{ 
    return Ok(HelperObject.GetGroupedValues(filterID, groupByFieldName)); 
} 

// ... and so does your other code that wants to do the same thing 
var x = HelperObject.GetGroupedValues(filterID, groupByFieldName);