如何实例化ODataQueryOptions

时间:2015-11-06 17:47:25

标签: c# .net odata asp.net-web-api2

我使用以下方法工作(简化)ODataController

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);
}

2 个答案:

答案 0 :(得分:4)

不确定。 ODataPath是ODataPathSegment的列表,应该跟随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 :(得分:0)

您的odata控制器为您的数据提供HTTP接口,您是否应该通过HTTP访问它(即使是从服务器)?这里有一个VS加载项来生成odata客户端代码:

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

或者,如果您是在同一个项目中执行此操作,为什么不返回可以从您的代码或控制器调用的IQueryable的常用方法?

更新:根据原始问题中的更多信息:

如果在控制器方法中定义了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本身(而不是实例化查询选项吗?

更新#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);