2015-11-06 98 views
5

我有一个工作(简化)ODataController以下方法。如何实例化ODataQueryOptions

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

我想能够从服务器调用此方法要做到这一点,我需要实例化一个ODataQueryOptions这需要一个ODataQueryContext

有一些如何做到这一点的例子(例如,herehere),但它们似乎都参考了先前版本的OData。构造函数ODataQueryContext当前需要第三个参数(ODataPath路径),这在我找不到的任何示例中都未涉及。

编辑: @snow_FFFFFF,这里的一些背景。我知道我可以简单地通过HttpClient的消费OData的终点,但我想与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

山姆。你真棒!如果你把答案放在答案中,我可以接受它。非常感谢。像魅力一样工作。 –

回答

3

肯定。 ODataPath是应跟进OData Uri spec的ODataPathSegment的列表。

在网页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

截止到2017年5月25日,Microsoft.AspNet.OData的最新稳定版本是v6.0.0。似乎不再有一个'EntitySetPathSegment'类。我需要在NuGet中降级到5.9.1。否则,非常有帮助的问题,我非常欣赏链接到源代码测试用例。 – asporter

+0

截至今天为止。 –

0

你的OData控制器提供HTTP接口,你的数据,你不应该通过HTTP访问它(即使从服务器)?有一个VS插件生成这里的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

更新#2:还有更详细的阅读之后,我觉得我错过了你的观点 - 我没有答案,但我会玩弄它。难道你不能改变URL本身(而不是实例化查询选项?

更新#3:我认为你将有一个很难欺骗它,以为它是得到一个OData的请求......这是不是一个真正的OData的请求。回到我原来的答复中提到的第二个方案 - 为什么不,您可以使用和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);