简体   繁体   English

如何使用 ASP.Net Web Api 2 进行部分响应

[英]How to do partial responses using ASP.Net Web Api 2

I'm really new to API design and MVC concepts, but as far as I can tell, something like GET /api/products should return a list of products and GET /api/products/1 should return a single product.我对 API 设计和 MVC 概念真的很陌生,但据我所知,像 GET /api/products 这样的东西应该返回一个产品列表,而 GET /api/products/1 应该返回一个单一的产品。 In terms of speed my feeling is that /api/products should return less information ie just id and name, whereas /api/products/1 should return more ie id, name, and description.在速度方面,我的感觉是 /api/products 应该返回较少的信息,即只有 id 和 name,而 /api/products/1 应该返回更多,即 id、name 和 description。

As far as I can see, the best way to handle this is to make certain fields of the product class not be returned in the /api/products endpoint.据我所知,处理此问题的最佳方法是使产品类的某些字段不在 /api/products 端点中返回。 This is especially necessary in the case of /api/products?fields=name .这在 /api/products?fields=name 的情况下尤其必要。 I'm using ASP.Net Web Api 2 and have tried the following:我正在使用 ASP.Net Web Api 2 并尝试了以下操作:

Is there any simple way to do what I'm trying to do?有什么简单的方法可以做我想做的事情吗?

Otherwise could you suggest a better API design than what I'm doing?否则你能提出比我正在做的更好的 API 设计吗?

You could also use WebApi.PartialResponse ( http://www.nuget.org/packages/WebApi.PartialResponse/ ). 您也可以使用WebApi.PartialResponse( http://www.nuget.org/packages/WebApi.PartialResponse/ )。 It's a package I wrote which uses LINQ to JSON (Json.NET) to manipulate the returned objects. 这是我写的一个包,它使用LINQ to JSON(Json.NET)来操作返回的对象。 It uses the fields syntax used by Google in their API's, eg.: 它使用Google在其API中使用的字段语法,例如:

  • fields=items/id,playlistItems/snippet/title,playlistItems/snippet/position 字段=项/ ID,playlistItems /片断/标题,playlistItems /片断/位置
  • fields=items(id,snippet/title,snippet/position) 字段=项(ID,段/标题,片段/位置)
  • fields=items(id,snippet(title,position)) 字段=项(ID,片段(标题,位置))

You can find more information on the GitHub project page: https://github.com/dotarj/PartialResponse . 您可以在GitHub项目页面上找到更多信息: https//github.com/dotarj/PartialResponse

I'd recommend using separate classes to map to when returning a list of entities. 我建议在返回实体列表时使用单独的类进行映射。

Particularly as the problem is not just what you return to the user, but also what you select from the database. 特别是因为问题不仅仅是您返回给用户的内容,还包括您从数据库中选择的内容。

So, make getting and entity return a Product object, and getting a list of entities return a ProductLink object or something similar. 因此,让get和entity返回一个Product对象,获取实体列表会返回一个ProductLink对象或类似的东西。

Edit 编辑

As per jtlowe's comment, if you have many different methods returning slight variations of product properties, use anonymous classes (though I'd question whether this is necessarily a good design). 根据jtlowe的评论,如果你有许多不同的方法返回产品属性的微小变化,使用匿名类(虽然我怀疑这是否一定是一个好的设计)。

Consider something like this in your action 在你的行动中考虑这样的事情

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

This: 这个:

  • Only selects the columns you need from the database. 仅从数据库中选择所需的列。
  • Needs no additional classes defined for new variations of the product 不需要为产品的新变体定义其他类

This doesn't make it easy to pass the result of this statement around to other methods because you can only return it as IEnumerable, object or dynamic. 这并不容易将此语句的结果传递给其他方法,因为您只能将其作为IEnumerable,object或dynamic返回。 If you are putting this in the controller then it may be good enough. 如果你把它放在控制器中那么它可能就足够了。 If you are implementing a repository pattern, you'll be unable to return strongly typed lists if you use anonymous types. 如果要实现存储库模式,则在使用匿名类型时,将无法返回强类型列表。

Stumpled over this topic and just want to share my feelings - maybe it helps others :) I recommend to use something like OData.被这个话题绊倒了,只是想分享我的感受 - 也许它可以帮助其他人:) 我建议使用像 OData 这样的东西。 You can implement it so that you can write /api/products?$select=Id,Name,Price你可以实现它,这样你就可以写/api/products?$select=Id,Name,Price

some advantages:一些优点:

  • with OData you can use further functions, like $filter, $orderby to work with filters and sort it使用 OData,您可以使用更多函数,例如 $filter、$orderby 来处理过滤器并对其进行排序
  • $skip, $top, $count to get a nice paging $skip, $top, $count 以获得漂亮的分页
  • more $-functions :)更多 $-functions :)
  • you can directly apply it to a IQueryable<T> .您可以直接将其应用于IQueryable<T> Why is this great?为什么这很棒? You reduce the result not just in the response of your API, but you even reduce the result your database generates, which makes your application much faster.您不仅减少了 API 响应的结果,而且还减少了数据库生成的结果,这使您的应用程序更快。 - and you don't even have to change your query - 您甚至不必更改查询

some disadvantages:一些缺点:

  • you can't filter directly on columns that are calculated您不能直接对计算的列进行过滤
  • setting it up will take a little time设置它需要一点时间

hint: sometimes it's better to just use ODataQueryOptions<T> in the parameter instead of complete implementation.提示:有时最好只在参数中使用ODataQueryOptions<T>而不是完整的实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM