简体   繁体   English

Web API - REST帮助和澄清

[英]Web API - REST help and clarification

I'm writing an API using WebAPI, and whilst I'm designing this from scratch, I'm trying to make it RESTful. 我正在使用WebAPI编写API,虽然我从头开始设计它,但我正在努力使其成为RESTful。 In the past when doing web service work, I've always used RPC patterns (ASMX, SOAP, etc) - eg. 在过去做Web服务工作时,我总是使用RPC模式(ASMX,SOAP等) - 例如。 using an arbitrary method name that matches what I want it to do. 使用与我想要的匹配的任意方法名称。 To me this seems much more intuitive and explicit than REST, but given WebApi seems to be more RESTful by nature (I know you can change the route so it's not), I've decided to try and make it RESTful. 对我而言,这似乎比REST更直观和明确,但鉴于WebApi似乎更加RESTful(我知道你可以改变路线,所以它不是),我决定尝试使它成为RESTful。

I understand (I think!) the basics - eg. 我理解(我认为!)基础知识 - 例如。 POST for create, PUT for update when specifying an ID, GET to get, DELETE to delete, etc, etc. 用于创建的POST,用于指定ID的PUT,要获取的GET,要删除的删除等等。

My confusion is how to deal with returning collections vs a single object. 我的困惑是如何处理返回集合与单个对象。 For example, say that I've got an API controller called UsersController . 例如,假设我有一个名为UsersController的API控制器。 As far as I gather, I'd have the following URLs: 据我所知,我有以下网址:

GET: /api/users (lists all users)
GET: /api/users/1 (lists details about user with ID 1)
POST: /api/users (creates a new user with details sent in the POST data)
PUT: /api/users/1 (updates the existing user with ID 1 with details sent in the POST data)
DELETE: /api/users/1 (deletes the existing user with ID 1)

For the first URL above, I need to also send various filter/search criteria. 对于上面的第一个URL,我还需要发送各种过滤器/搜索条件。 Does this criteria just get passed through as query string parameters? 此条件是否仅作为查询字符串参数传递? Or should I be using a completely different controller for this "search" functionality? 或者我应该使用完全不同的控制器来实现这种“搜索”功能? Eg. 例如。 UserSearchController? UserSearchController? If so, should that be a POST in this case or still a GET? 如果是这样,在这种情况下应该是POST还是GET? Actually as I write this, I'm wondering whether a separate controller makes sense anyway, as I'll probably want more detail returned in the GET for a single user than in the search results. 实际上,当我写这篇文章时,我想知道一个单独的控制器是否有意义,因为我可能想要在单个用户的GET中返回比在搜索结果中更多的细节。 Does it make it not RESTful if the same controller does return different data for a single object GET vs a GET returning a collection? 如果同一个控制器确实为单个对象GET和GET返回一个集合返回不同的数据,它是否会使它不是RESTful?

For the first URL above, I need to also send various filter/search criteria. 对于上面的第一个URL,我还需要发送各种过滤器/搜索条件。 Does this criteria just get passed through as query string parameters? 此条件是否仅作为查询字符串参数传递?

It definitely makes sense to use query string for specifying filter/search parameters. 使用查询字符串指定过滤器/搜索参数绝对有意义。

should I be using a completely different controller for this "search" functionality? 我应该使用完全不同的控制器来实现这种“搜索”功能吗? Eg. 例如。 UserSearchController? UserSearchController?

You should not do that. 你不应该这样做。 There are couple of reasons that i see here: 我在这里看到几个原因:

  1. There will be almost identical functionality in GET: /api/users GET: /api/users功能几乎完全相同GET: /api/users
  2. You can easily implement GET: /api/users , GET: /api/users?filter=...&sort=... and GET: /api/users/1 in one method: 您可以在一种方法中轻松实现GET: /api/usersGET: /api/users?filter=...&sort=...GET: /api/users/1

     //If you are using EF it could look like //filter and sort arguments could be added here as well public HttpResponseMessage Get(int? id) { if(id.HasValue) { return Request.CreateResponse( HttpStatusCode.OK, Context.Users.SingleOrDefault<Users>(u => u.Id == id)); } var users = Context.Users.Select(apply filter).OrderBy(apply sort).ToList(); return Request.CreateResponse(HttpStatusCode.OK, users); } 

You can take a look at OData - it may help you with the implementation. 你可以看看OData - 它可以帮助你实现。

  1. Spreading this logic between different controllers compromises single responsibility principle - your users controller should handle all the logic related to users and only this logic 在不同的控制器之间传播这种逻辑会破坏单一责任原则 - 您的用户控制器应该处理与用户相关的所有逻辑,并且只处理这种逻辑

If so, should that be a POST in this case or still a GET? 如果是这样,在这种情况下应该是POST还是GET?

If you want to make your API RESTful you should be using GET. 如果你想让你的API RESTful,你应该使用GET。 BUT you should be aware, that returning an array of JSON objects through GET could be potentially vulnerable to JSON hijacking . 但是你应该知道,通过GET返回一组JSON对象可能容易受到JSON劫持 One of the simplest solutions to this exploit is allowing to get JSON arrays through POST only (there are other solutions as well). 这种漏洞利用的最简单的解决方案之一是允许通过POST获取JSON数组(还有其他解决方案)。

I'll probably want more detail returned in the GET for a single user than in the search results. 我可能想要在单个用户的GET中返回比在搜索结果中更多的详细信息。 Does it make it not RESTful if the same controller does return different data for a single object GET vs a GET returning a collection? 如果同一个控制器确实为单个对象GET和GET返回一个集合返回不同的数据,它是否会使它不是RESTful?

This is totally fine to return more details for a single object than for a collection. 这对于单个对象而不是集合返回更多细节是完全正确的。 It doesn't affect RESTfulness of your API in any way. 它不会以任何方式影响API的RESTfulness。

COMMENT 评论

You wrote: 你写了:

PUT for update when specifying an ID 指定ID时进行PUT更新

Actually it is not entirely correct: 实际上它并不完全正确:

  • PUT should be used for complete replacement of the entire entity PUT应该用于完全替换整个实体
  • PATCH should be used to perform a partial update. 应使用PATCH执行部分更新。

If you want to get passed through criteria as query string parameters to URI, you can do that using Attribute Routing into WebApi. 如果您希望将标准作为查询字符串参数传递给URI,则可以使用属性路由到WebApi来实现。 I think attribute-routing-in-web-api helps to you. 我认为attribute-routing-in-web-api对你有帮助。

Yes, I would pass filter parameters as query string options. 是的,我会将过滤器参数作为查询字符串选项传递。 The 'restfulness' of your application is not dependent on controller structure, so you can follow a structure that best suits your application 应用程序的“restfulness”不依赖于控制器结构,因此您可以遵循最适合您的应用程序的结构

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

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