【问题标题】:WebApi Odata returning complex typeWebApi Odata 返回复杂类型
【发布时间】:2013-05-26 11:26:54
【问题描述】:

我有一个由两个实体组成的简单数据模型

public class product 
{
     public int ID {get;set;}
     public string Name {get;set;}
}

public class supplier
{
    public int ID {get;set;}
    public string Name {get;set;}
    public IEnumerable<product> products {get;set;}
}

现在,我想通过我的 WebApi odata 控制器返回供应商及其所有产品。但我似乎无法让这个工作,它只是返回供应商并有效地剥离产品信息。控制器方法是一个简单的 Get 和 GetEntityByKey。 我的配置如下。

 ODataModelBuilder modelBuilder = new ODataConventionModelBuilder();
            modelBuilder.EntitySet<supplier>("supplier");
            modelBuilder.EntitySet<product>("product");

是否有我缺少的配置选项来让它工作?

【问题讨论】:

    标签: asp.net-web-api odata complextype


    【解决方案1】:

    你没有提到你用来获取供应商实体的 URI,但我假设它看起来像:http://.../ServiceRoot.svc/supplier(1)。默认情况下,在 OData 中,导航属性不展开;也就是说,默认情况下,请求供应商不会包括链接产品的 ID 和名称,除非您通过 $expand 查询选项明确要求它们。例如:http://.../ServiceRoot.svc/supplier(1)?$expand=products。

    如果您不展开导航属性,则供应商的products 属性将仅显示为产品实体的链接集合。如果您在响应负载中没有看到指向产品的链接,可能是因为您使用的是 OData 的新 v3 JSON 格式,它可能会省略遵循一般 OData URI 约定的导航链接(因为客户端可以生成那些链接自身)。

    如果您包含请求 URI 和返回的有效负载,我可以更清楚地了解您的情况。

    关于术语的快速说明:OData 中的“复杂类型”通常是指没有标识的结构类型。一个典型的例子可能是地址类型,它是一种具有多个组件(城市、国家、街道等)但不需要有自己的键的值类型。您在这里谈论的是实体之间的导航。

    【讨论】:

    • 基于 Jen 的回答,NuGet 上 Web API OData 的第一个版本不支持 $expand,但它目前在我们的夜间版本中可用,并且应该在下一个版本中可用。有关如何访问我们的 nightlies 的更多信息,请参阅此博客文章:blogs.msdn.com/b/henrikn/archive/2012/06/01/…
    • 感谢您回复我。至少我知道它不是一个配置选项,它的 odata 本身剥离了额外的“产品”信息,而不是像在非 odata WebApi Get 中那样将其包含在返回的 Json 中。下一个版本有发布日期吗?
    • @YoussefMoussaoui 我已经获得了夜间版本,但无法获得一个简单的示例来工作,请注意我正在使用提琴手作曲家mywebsite:port/odata/suppler(1)?$expand=products。 webapi控制器中的代码如下protected override supplier GetEntityByKey(int key) { supplier s = new supplier() { Name = "Test", ID=1 }; s.products = new List&lt;product&gt;(){new product() { ID = 1, Name = "P1" }, new product() { Name = "P2", ID = 2 }}; return s; }
    • @YoussefMoussaoui - 返回的 JSON 不包含产品信息,仅包含供应商信息。调试控制器GetEntityKey可以看到返回值包含了产品,但是在Fiddler中查看Json时,产品仍然被剥离出来。它对 Get(返回供应商和产品)正常工作,但不适用于 GetEntityByKey,它只返回供应商。感谢 Youssef 抽出宝贵时间。
    • 好的,它适用于 Get 但不能通过键获取的原因是因为 Get 标记了 Queryable 属性,但您的 Get 没有。我实际上建议您从 ODataController 而不是 EntitySetController 派生,复制您需要的任何代码。并且您使用 Queryable 属性标记 Get by key。目前还没有太多的文档,因为我们还没有发布任何东西,但是如果你想为此创建一个单独的堆栈溢出问题,我可以尝试提供一些示例代码。
    【解决方案2】:

    也许尝试使用 QueryableAttribute。看这里:

    Expand support

    2) 支持 $select 和 $expand 在单个实体上通过 可查询属性。

    【讨论】:

      【解决方案3】:

      尝试使用 $expand 子句 在我的情况下,我必须先添加一个 complexType:

      builder.ComplexType();

      另外我发现应该使用不同的查询来获取 UI 上的复杂类型

      应该使用另一个 url 而不是调用 http://url/api/AccountDetails?$select=name,accountNumber,balance : http://url/api/AccountDetails?$select=name,accountNumber,balance&$expand=balance

      你只能通过 $expand 看到复杂的属性,比如 balance

      另外,打开 $expand 功能也很重要。为此,请在添加 edm 模型之前添加它: endpoints.Select().Expand().Filter().OrderBy().Count().MaxTop(10); endpoints.MapODataRoute("odata", "odata", this.GetEdmModel());

      在此处查看详细信息:https://stackoverflow.com/a/55476645/2050539

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-06-01
        • 2015-08-01
        • 1970-01-01
        • 2016-11-15
        • 1970-01-01
        • 1970-01-01
        • 2017-06-12
        相关资源
        最近更新 更多