C# 如何使用ASP.NETWebAPI2进行部分响应

C# 如何使用ASP.NETWebAPI2进行部分响应,c#,asp.net-mvc,json,asp.net-web-api,C#,Asp.net Mvc,Json,Asp.net Web Api,我对API设计和MVC概念非常陌生,但据我所知,像GET/API/products这样的东西应该返回产品列表,而GET/API/products/1应该返回单个产品。就速度而言,我的感觉是/api/products应该返回更少的信息,即id和name,而/api/products/1应该返回更多的信息,即id、name和description 据我所见,处理此问题的最佳方法是使product类的某些字段不在/api/products端点中返回。这在/api/products?fields=nam

我对API设计和MVC概念非常陌生,但据我所知,像GET/API/products这样的东西应该返回产品列表,而GET/API/products/1应该返回单个产品。就速度而言,我的感觉是/api/products应该返回更少的信息,即id和name,而/api/products/1应该返回更多的信息,即id、name和description

据我所见,处理此问题的最佳方法是使product类的某些字段不在/api/products端点中返回。这在/api/products?fields=name的情况下尤为必要。我正在使用ASP.Net Web Api 2,并尝试了以下操作:

  • -安装此程序包导致程序集版本错误
  • 在产品字段上添加ShouldSerialize方法。由于一些原因,我将不在这里讨论,这种方法有点麻烦
  • 看了,但似乎没有一个结论性的答案
  • 建议使用具有所有可空字段的product类。我不确定我到底明白在那里该做什么
有没有简单的方法来做我想做的事


否则,您能推荐一个比我现在做的更好的API设计吗?

我建议在返回实体列表时使用单独的类进行映射

特别是,问题不仅在于您返回给用户的内容,还在于您从数据库中选择的内容

所以,让获取和实体返回一个产品对象,获取实体列表返回一个ProductLink对象或类似的东西

编辑

根据jtlowe的评论,如果您有许多不同的方法返回产品属性的细微变化,请使用匿名类(尽管我怀疑这是否一定是一个好的设计)

在你的行动中考虑类似的事情

return from p in this.context.Products
       select new
       {
           p.Id,
           p.Name,
           p.SKU
       };
这:

  • 仅从数据库中选择所需的列
  • 不需要为产品的新变体定义额外的类

这不便于将此语句的结果传递给其他方法,因为您只能将其作为IEnumerable、object或dynamic返回。如果你把它放在控制器里,那么它可能就足够好了。如果要实现存储库模式,则如果使用匿名类型,将无法返回强类型列表。

也可以使用WebApi.PartialResponse()。这是我编写的一个包,它使用linqtojson(JSON.NET)来操作返回的对象。它使用谷歌在API中使用的字段语法,例如:

  • 字段=项目/id、播放项目/片段/标题、播放项目/片段/位置
  • 字段=项(id、代码段/标题、代码段/位置)
  • 字段=项目(id、代码段(标题、位置))

您可以在GitHub项目页面上找到更多信息:。

也许您可以在/api/products处返回一个匿名类型,然后返回详细的产品类型/api/products/10。谢谢@jtlowe-两个/api/products和/api/products/10都是通过实体框架检索产品对象的,因此我们在这两种情况下都有完整的产品对象。当然,由于/api/products上已经有了完整的产品对象,因此必须有某种方法返回该列表,但省略了一些属性?这取决于数据库的大小/设置,可能还有序列化程序。听起来您只想加载/api/产品所需的信息,而不是完整的产品。如果从Products表中检索所有完整记录,可能会影响性能,这听起来像是在试图避免。马丁的回答是一个很好的方法。还可以查看支持OData查询。这使得过滤变得更容易,主要的性能问题是在响应中向客户端传递大量数据,而不是数据库。在这方面,Martin的方法听起来不错,尽管我看不出它是可伸缩的。例如,如果我们要引入/api/stores/1/products,它返回产品对象,但这次只公开ID、名称和SKU号,该怎么办?我们现在需要创建另一种类型的产品类吗?在您刚才概述的情况下,您可以对/api/products和/api/store/1/products使用相同的初始产品对象。对于ProductDetail视图,您可以对/api/products/10进行api调用,而不是继续向下查看/api/store/1/products/10。感谢Martin的建议,我认为我们将使用这种方法。您建议如何处理?fields=id,name问题?请仔细考虑一下,请参阅我上面对jtlowe的评论。当然,这种方法是不可伸缩的?如果您的产品对象不是包含所有产品详细信息的实际产品对象,那么这种方法将可伸缩。例如:产品{ID,SKU,Name},产品详细信息{ID,SKU,姓名,制造商,联系人,价格,产地,高度,宽度,…}。感谢你的帮助jtlowe和Martin Booth-这真的帮助我理清思路!但是,关于部分回复,我找不到关于如何处理/api/products?fields=颜色、大小、名称之类的内容的任何具体信息。在.NET生态系统中是否有针对这一点的最佳实践?如果可能的话,我宁愿不使用OData。有没有一种方法可以将其用于收藏?假设我从web api返回分页集合,而不是获取分页集合的全部内容,我只需要集合中每个项目的id和名称。我可以让一切正常工作,除了上面的场景,这正是我真正想使用它的原因:)我阅读了谷歌开发文档中关于部分响应的内容,认为可能有一些见解。看起来这应该适用于集合。我的JSON有类型信息,这会把事情搞砸吗{$id:“4”,$type:“System.Collections.Generic.List`1[[Acme.Models.FluidModel,KNE.Athena.Models]],mscorlib“,$values:[{$id:“5”,$type:“Acme.FluidModel,Acme.Models”,链接:{},id:1,名称:“Fluid”,},