【问题标题】:How to Instantiate ODataQueryOptions如何实例化 ODataQueryOptions
【发布时间】:2016-02-07 22:42:49
【问题描述】:

我有一个使用以下方法的工作(简化)ODataController

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

我希望能够从服务器调用此方法,为此我需要实例化一个需要 ODataQueryContextODataQueryOptions

有一些示例说明如何执行此操作(例如 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);
}

【问题讨论】:

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


【解决方案1】:

您的 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

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

【讨论】:

    【解决方案2】:

    当然。 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

    【讨论】:

    • 截至 2017 年 1 月 25 日,Microsoft.AspNet.OData 的最新稳定版本为 v6.0.0。似乎不再有 EntitySetPathSegment 类。我需要将 NuGet 降级到 5.9.1。否则,非常有用的问题,我非常感谢源代码测试用例的链接。
    • 截至今天的链接失效。
    • setName 是什么?
    • @anisanwesley setName 可以是模型中定义的任何实体集。
    • @SamXu,是否可以在 Odata 7.4.0 版本的上下文中添加更新以反映您的解决方案?
    猜你喜欢
    • 2019-10-29
    • 1970-01-01
    • 2017-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多