复合密钥资源REST服务 [英] composite key resource REST service

查看:104
本文介绍了复合密钥资源REST服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在工作中遇到了一个问题,我找不到关于在主资源是其他资源ID的组合的资源的RESTful Web服务中执行CRUD操作的常规标准或实践的信息.我们正在使用MVC WebApi创建控制器.例如,我们有三个表:

I've come across a problem at work where I can't find information on the usual standard or practice for performing CRUD operations in a RESTful web service against a resource whose primary key is a composite of other resource ids. We are using MVC WebApi to create the controllers. For example, we have three tables:

  • Product:PK = ProductId
  • Part:PK = PartId
  • ProductPartAssoc:PK =(ProductId,PartId)
  • Product: PK=ProductId
  • Part: PK=PartId
  • ProductPartAssoc: PK=(ProductId, PartId)

一个产品可以有很多零件,而零件可以是许多产品的组成部分.关联表还包含与关联本身相关的其他信息,这些信息比需要编辑的信息要多.

A product can have many parts and a part can be a component of many products. The association table also contains additional information relevant to the association itself than needs to be editable.

我们有ProductsControllerPartsController类,它们使用定义为{controller}/{id}/{action}的路由模板来处理常规的GET/PUT/POST/DELETE操作,从而使以下IRI起作用:

We have ProductsController and PartsController classes that handle the usual GET/PUT/POST/DELETE operations using route templates defined as: {controller}/{id}/{action} such that the following IRIs work:

  • GET,POST /api/Products-返回所有产品,创建新产品
  • 获取,删除,删除/api/Products/1-检索/更新/删除产品1
  • GET,POST /api/Parts-返回所有零件,创建新零件
  • 获取,删除,删除/api/Parts/2-检索/更新/删除第2部分
  • 获取/api/Products/1/Parts-获取产品1的所有零件
  • 获取/api/Parts/2/Products-获取第2部分为其组成部分的所有产品
  • GET,POST /api/Products - returns all products, creates a new product
  • GET,PUT,DELETE /api/Products/1 - retrieves/updates/deletes product 1
  • GET,POST /api/Parts - returns all parts, creates a new part
  • GET,PUT,DELETE /api/Parts/2 - retrieves/updates/deletes part 2
  • GET /api/Products/1/Parts - get all parts for product 1
  • GET /api/Parts/2/Products - get all products for which part 2 is a component

我遇到麻烦的地方是如何为ProductPartAssoc资源定义路由模板.路由模板和IRI应该如何获取关联数据? 坚持约定,我期望这样的事情:

Where I am having trouble is in how to define the route template for ProductPartAssoc resources. What should the route template and IRI look like for getting the association data? Adhering to convention, I would expect something like:

  • GET,POST /api/ProductPartAssoc-返回所有关联,创建关联
  • GET,PUT,DELETE /api/ProductPartAssoc/[1,2]-检索/更新/删除产品1和第2部分之间的关​​联
  • GET,POST /api/ProductPartAssoc - returns all associations, creates an association
  • GET,PUT,DELETE /api/ProductPartAssoc/[1,2] - retrieves/updates/deletes association between product 1 and part 2

我的同事们发现这在美学上是令人不愉快的,并且似乎认为最好完全不使用ProductPartAssocController类,而应该在ProductsController中添加其他方法来管理关联数据:

My coworkers find this aesthetically displeasing though and seem to think it would be better to not have a ProductPartAssocController class at all, but rather, add additional methods to the ProductsController to manage the association data:

  • GET,PUT,DELETE /api/Products/1/Parts/2-获取产品1和部件2之间关联的数据,而不是作为部件1成员的部件2的数据,这通常是基于诸如我在其他地方看到过的.
  • POST这里没有线索,他们希望IRI看起来像什么.不幸的是,他们是决策者.
  • GET,PUT,DELETE /api/Products/1/Parts/2 - get data for the association between product 1 and part 2 rather than data for part 2 as a member of part 1, which would conventionally be the case based on other examples such as /Book/5/Chapter/3 that I have seen elsewhere.
  • POST No clue here what they expect the IRI to look like. Unfortunately, they're the decision makers.

最终,我想我正在寻找的要么是验证,要么是我可以指出的方向,然后说:瞧,这就是其他人的工作."

At the end of the day, I guess what I am seeking is either validation, or direction that I can point to and say "See, this is what other people do."

处理组合键标识的资源的典型做法是什么?

What is the typical practice for dealing with resources identified by composite keys?

推荐答案

我也很喜欢/api/Products/1/Parts/2的美学.您可能还会有多条路线要执行相同的操作,因此您可以加倍并提供/api/Parts/2/Products/1作为同一资源的备用URL.

I too like the aesthetics of /api/Products/1/Parts/2. You could also have multiple routes go to the same action, so you could double up and also offer /api/Parts/2/Products/1 as an alternate URL for the same resource.

对于POST,您已经知道组合键.那么,为什么不消除对POST的需求,而仅将PUT用于创建和更新呢?如果您的系统生成主键,那么将POST传递到集合资源URL会非常有用,但是如果您拥有已知主键的组合,为什么需要POST?

As for POST, you already know the composite key. So why not eliminate the need for POST and just use PUT for both creation and updates? POST to a collection resource URL is great if your system generates the primary key, but in cases where you have a composite of already known primary keys, why do you need POST?

也就是说,我也喜欢这样的想法,即有一个单独的ProductPartAssocController来包含这些URL的动作.您必须做一个自定义的路由映射,但是如果使用类似 AttributeRouting.NET 之类的方法,则非常容易做.

That said, I also like the idea of having a separate ProductPartAssocController to contain the actions for these URL's. You would have to do a custom route mapping, but if you're using something like AttributeRouting.NET that is very easy to do.

例如,我们这样做是为了管理角色中的用户:

For example we do this for managing users in roles:

PUT, GET, DELETE /api/users/1/roles/2
PUT, GET, DELETE /api/roles/2/users/1

6个URL,但只有3个动作,全部在GrantsController中(我们将用户和角色之间的gerund称为授予").使用 AttributeRouting.NET :

6 URL's, but only 3 actions, all in the GrantsController (we call the gerund between users and roles a "Grant"). Class ends up looking something like this, using 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
}

对我来说,这似乎是一种非常直观的方法.将动作保存在单独的控制器中也可以使控制器更精简.

This seems a fairly intuitive approach to me. Keeping the actions in a separate controller also makes for leaner controllers.

这篇关于复合密钥资源REST服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆