我遇到了一个工作问题,我无法找到有关在RESTful Web服务中针对主键是其他资源ID的组合的资源执行CRUD操作的通常标准或惯例的信息。我们使用MVC WebApi来创建控制器。例如,我们有三个表:
Product
:PK = ProductId Part
:PK = PartId ProductPartAssoc
:PK =(ProductId,PartId)产品可以包含许多部件,而部件可以是许多产品的组件。关联表还包含与关联本身相关的其他信息,而不是可编辑的信息。
我们有ProductsController
和PartsController
个类,它们使用定义为:{controller}/{id}/{action}
的路由模板处理通常的GET / PUT / POST / DELETE操作,以便以下IRI工作:
/api/Products
- 返回所有产品,创建新产品/api/Products/1
- 检索/更新/删除产品1 /api/Parts
- 返回所有部分,创建新部分/api/Parts/2
- 检索/更新/删除第2部分/api/Products/1/Parts
- 获取产品1的所有部件/api/Parts/2/Products
- 获取第2部分为组件的所有产品我遇到问题的方法是如何为ProductPartAssoc资源定义路径模板。获取关联数据的路由模板和IRI应该是什么样的? 坚持惯例,我希望有类似的东西:
/api/ProductPartAssoc
- 返回所有关联,创建关联/api/ProductPartAssoc/[1,2]
- 检索/更新/删除产品1和第2部分之间的关联我的同事发现这在美学上令人不悦,并且似乎认为最好不要有ProductPartAssocController
类,而是向ProductsController
添加其他方法来管理关联数据:
/api/Products/1/Parts/2
- 获取产品1和第2部分之间关联的数据,而不是第2部分作为第1部分成员的数据,这通常是基于其他示例的情况,例如我在其他地方看到的/Book/5/Chapter/3
。在一天结束时,我想我要求的是验证,或指示我可以指出并说“看,这是其他人做的。”
处理由复合键识别的资源的典型做法是什么?
答案 0 :(得分:18)
我也喜欢/api/Products/1/Parts/2
的美学。您也可以将多条路线转到同一操作,这样您就可以加倍并提供/api/Parts/2/Products/1
作为同一资源的备用网址。
对于POST,您已经知道复合键。那么为什么不消除POST的需要,只是使用PUT进行创建和更新?如果您的系统生成主键,则POST到集合资源URL很好,但是如果您有已知主键的复合,那么为什么需要POST?
也就是说,我也喜欢单独ProductPartAssocController
来包含这些URL的操作。您必须进行自定义路由映射,但如果您使用AttributeRouting.NET这样的东西很容易。
例如,我们这样做是为了管理角色中的用户:
PUT, GET, DELETE /api/users/1/roles/2
PUT, GET, DELETE /api/roles/2/users/1
6个URL,但只有3个动作,全部在GrantsController
中(我们将用户和角色之间的动名称为“Grant”)。使用AttributeRouting.NET:
[RoutePrefix("api")]
[Authorize(Roles = RoleName.RoleGrantors)]
public class GrantsController : ApiController
{
[PUT("users/{userId}/roles/{roleId}", ActionPrecedence = 1)]
[PUT("roles/{roleId}/users/{userId}", ActionPrecedence = 2)]
public HttpResponseMessage PutInRole(int userId, int roleId)
{
...
}
[DELETE("users/{userId}/roles/{roleId}", ActionPrecedence = 1)]
[DELETE("roles/{roleId}/users/{userId}", ActionPrecedence = 2)]
public HttpResponseMessage DeleteFromRole(int userId, int roleId)
{
...
}
...etc
}
这对我来说似乎是一种相当直观的方法。将操作保存在单独的控制器中也可以实现更精简的控制器。
答案 1 :(得分:0)
我建议:
/api/PartsProductsAssoc
:在零件和产品之间创建链接。在POST数据中包含零件和产品ID。/api/PartsProductsAssoc/<assoc_id>
:使用<assoc_id>
读取/更新/删除链接(不是部分或产品ID,是的,这意味着在您的PartsProductsAssoc表中创建新列)。/api/PartsProductsAssoc/Parts/<part_id>/Products
:获取与给定部分关联的产品列表。/api/PartsProductsAssoc/Products/<product_id>/Parts
:获取与给定产品相关的零件清单。采取这种方法的原因:
有关详细信息,请参阅56:30的https://www.youtube.com/watch?v=hdSrT4yjS1g。