ODATAv4 $expand 在选择显式对象时不起作用

ODATAv4 $expand doesn't work when selecting explicit object

第一个 GET 工作得很好:

http://localhost/webservice/odata/MyStuff?$filter=Id eq 2&$expand=History

它returns一个MyStuffHistory的数组被展开了。

但是,如果我尝试使用指定的密钥获取 MyStuff,历史导航 属性 不会展开。

http://localhost/webservice/odata/MyStuff(2)?$expand=History

我在启动时已经HttpConfiguration配置如下

             HttpConfiguration
            .Filter()
            .Expand()
            .Select()
            .OrderBy()
            .MaxTop(null)
            .Count();

像这样的问题有多个角度:

  1. 数据本身
  2. 用于获取数据的查询
  3. 提供数据的控制器方法的响应类型
  4. EnableQueryAttribute配置

您已经证明了数据的存在,因此我们可以对数据本身进行折扣,但其余因素可以通过各种组合实现。

You should update your question to show an example of your controller method that handles the GET by Key request

如果您使用的是像 Entity Framework 这样的 ORM,那么下面的简单控制器显示了一个应该工作的最小实现:

[OData.EnableQuery]
public virtual IHttpActionResult Get([FromODataUri] TKey key, ODataQueryOptions<MyStuff> queryOptions)
{
    return SingleResultAction(dbContext.MyStuff.Where(x => x.Id == 2));
}

当然还有很多其他方法,从最低限度的角度来看,使用 SingleResultAction 强制您传递一个查询并验证它只有 returns 一个结果。

只要您的方法返回 IQueryable<> 结果,EnableQueryAttribute 就会自动尝试将 queryOptions 应用于您的查询。

如果您的结果集是手动构造的,或者 NOT 返回为 IQueryable<> 或者不能自动链接,那么您将必须 Apply $expand 手动查询选项。

您可以这样做以仅允许扩展某些导航属性,下一个示例通过积极地将所有 History 记录加载到内存中来准备项目

Not recommended, especially if your navigation property may have many rows and the user will not be expanding very frequently, but it works:

[OData.EnableQuery]
public virtual MyStuff Get([FromODataUri] TKey key, ODataQueryOptions<MyStuff> queryOptions)
{
    var item = dbContext.MyStuff.Include(X => x.History).Single(x => x.Id == 2);
    return item;
}

这个例子仍然允许 EnableQueryAttribute$expand 甚至 $sort$filter 扩展中的记录,但是,因为整个可用数据已经加载到内存中,EnableQueryAttribute 无法加载其他端点。

in this last example, even though the History items were loaded into memory, the will only appear in the JSON response if the $expand=History query option is provided by the caller.

还有很多其他场景,OP 没有提供他们的实现代码,所以这里全是推测。我特意 NOT 演示了如何手动 将 QueryOptions 应用于您的数据查询,您可以这样做,但在您掌握它之前,我鼓励您更接近于最小的实现,我们通过 OData 获得了很多 OOTB,通常足以应付。