将现有项目添加到REST API中的集合的最佳模式是什么?


23

我正在设计一个实用的REST API,并且对如何最好地将现有实体添加到集合中有些困惑。我的域模型包括一个具有站点集合的项目。这是一个严格的多对多关系,我无需创建一个显式建模该关系的实体(即ProjectSite)。

我的API将允许使用者将现有站点添加到项目中。我挂断电话的地方是,我真正需要的唯一数据是ProjectId和SiteId。我最初的想法是:

1. POST myapi/projects/{projectId}/sites/{siteId}

但是我也想过

2. POST myapi/projects/{projectId}/sites

与作为JSON内容发送的Site实体。

选项1简单易用,但感觉不太正确,而且我还有其他关系无法遵循此模式,因此它增加了我的API的不一致性。

选项2感觉更好,但引起两个问题:

  • 如果发布了新网站(SiteId = 0),我应该创建一个网站还是引发异常?
  • 因为我只需要ProjectId和SiteId来创建关系,所以该站点可能发布的其他属性数据有误或缺失。

第三种选择是提供一个仅用于创建和删除关系的简单端点。该端点将期望仅包含ProjectId和SiteId的JSON有效负载。

你怎么看?



@RoryHunter在该链接中有一些有趣的讨论,但是没有什么可以消除我的不确定性。我特别喜欢被接受的答案说“您理解正确”。第二名(尽管有很大差距)回答“简而言之,您正在完全落后。”
Jamie Ide 2014年

您的第一个选择很好,尽管我将使用PUT而不是POST,因为客户端可以控制要添加到集合中的身份。您对选项2的首要担心完全取决于您,如果您不希望有新站点,请不要引发异常,而是返回4xx代码之一。您的第二个顾虑既不在这里也不在那里。除非您允许添加内容,否则您不应该发布整个网站。添加现有站点时,仅在修改站点时才应具有ID,但仅应具有“ ProjectSite”集合(即使您没有为其创建单独的资源)也应具有ID。
Marjan Venema 2014年

Answers:


14

POST是“追加”动词,也是“处理”动词。PUT是“创建/更新”动词(用于已知标识符),在这里看起来几乎是正确的选择,因为已知完整的目标URI。projectId并且siteId已经存在,因此您无需“ POST to a collection”即可生成新的ID。

PUT的问题在于它要求主体是您要放入的资源的表示形式。但是这里的目的是要添加到“项目/站点”集合资源,而不是更新站点资源。

如果有人对现有站点进行完整的JSON表示怎么办?您应该更新集合更新对象吗?您可以支持这一点,但这听起来并不是目的。如你所说,

我真正需要的唯一数据是ProjectId和SiteId

而是,我尝试siteId将POST到集合中,并依赖于POST的“追加”和“处理”性质:

POST myapi / projects / {projectId} / sites

{'ID': '...' }

由于您要修改的是网站集资源而不是Site 资源,因此您需要的URI。POST可以知道“附加/处理”并将具有该ID的元素添加到项目的网站集中。

通过充实JSON并省略id,仍然为创建项目的全新站点打开了大门。“ No id” ==“从头开始创建”。但是,如果集合URI得到一个id,而没有其他任何东西,那么很清楚需要发生什么。

有趣的问题。:)


我坚信POST用于创建,PUT用于更新,但是您的结论就是我昨天的结论。令人高兴的是,由于Web API中的属性路由,我将代码保存在ProjectSites控制器中,因此代码井井有条。
Jamie Ide 2014年

我认为你需要使用的决定性原因POST,而不是PUTPATCH这里要说的是你没有整个Site实体投入的sites资源。您只有ID,需要对其进行处理才能将其添加到集合中。
美眉

4

我们将这种Patch方法用于这样的事情。您要做的是修改现有项目以向其添加站点。

所以这样的事情会起作用

PATCH myapi/projects/{id} 

在请求正文中将Site实体作为JSON / JSONArray使用。

这样,您可以根据需要使用相同的URL来修改Project的不同部分-实现中的代码必须足够智能,以处理资源的部分修改。


有趣的方法。我有一个“丰富”(即高度依赖)的较旧域模型,而Project尤其悬挂了许多收藏。检测请求中的实体类型将是一个挑战,并且不符合我的务实目标。
Jamie Ide 2014年

为什么要挑战?如果有这些限制,则始终可以使用JSON来明确说明其发送的内容... {"sites": [], "other-stuff": {}},然后可以分支代码以非常轻松地处理所有这些“ subjson”。这确实取决于您的特定问题,但我仍然建议您使用PATCH,因为它是专门为此类事情设计的。
2014年

我看到的缺点是:1)API没有明确传达哪些集合允许更改;2)无法利用Web API参数绑定;3)大开关或if语句。
Jamie Ide 2014年

我从来没有见过使用的补丁方法在其他地方
宁姆

难道还不PATCH希望完整的实体作为此处的值传递,而不是指向某个实体的ID传递吗?
美眉
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.