【问题标题】:REST API including and excluding of subresources包含和排除子资源的 REST API
【发布时间】:2015-08-20 10:28:29
【问题描述】:

我正在尝试确定一种 RESTful 方式来随意包含和排除特定请求的子资源。

例如,这可能是原始请求:

获取部门/321

200 (Ok)
{
    "id": "321",
    "name": "Sales",
    "building": "The Foundary"
    "subdepartments": [
       {
          "id": "123",
          "name": "Training"
       },
       {
          "id": "224",
          "name": "Book Sales"
       }
       ...
    ]
}

可能有很多子部门。 GET departments 资源也将包括每个部门和每个部门的子部门。大量数据。

这可以通过创建两个单独的资源来解决:

获取部门/321

200 (Ok)
{
    "id": "3",
    "name": "Sales",
    "building": "The Foundary"
}

获取部门/321/子部门

200 (Ok)
[
   {
      "id": "123",
      "name": "Training"
   },
   {
      "id": "224",
      "name": "Book Sales"
   }
   ...
]

但在某些情况下,客户端软件可能不希望发出多个请求(很可能出于性能考虑)。也许通过提供include 过滤器:

获取部门/321?include=subdepartments

200 (Ok)
{
    "id": "321",
    "name": "Sales",
    "building": "The Foundary"
    "subdepartments": [
       {
          "id": "123",
          "name": "Training"
       },
       {
          "id": "224",
          "name": "Book Sales"
       }
       ...
    ]
}

或排除过滤器:

获取部门/321?exclude=subdepartments

200 (Ok)
{
    "id": "321",
    "name": "Sales",
    "building": "The Foundary"
}

虽然我们可能需要包含指向子资源的链接(如果它被排除在外)?

获取部门/321?exclude=subdepartments

200 (Ok)
{
    "id": "321",
    "name": "Sales",
    "building": "The Foundary"
    "subdepartments": {
        "href" : "api.com/departments/321/subresources"
    }
}

是否有可接受的 RESTful 方式来执行上述(包括或排除子资源)?

【问题讨论】:

  • 你的提议在我看来不错。我认为 RESTful 不应该用得太严格。如果你的世界不适合 REST,那么 REST 应该被弯曲——而不是世界。

标签: rest asp.net-web-api2 asp.net-web-api restful-architecture


【解决方案1】:

适当的 REST 服务必须使用超媒体(链接)连接到相关资源。如果我们使用自定义媒体类型而不是 JSON Collection 或 AtomPub 之类的东西,那么第一次调用的响应将类似于

{
    "id": "321",
    "name": "Sales",
    "building": "The Foundary"
    "links": [
          { "rel": "subdepartments", "href": "departments/321/subdepartments", "method": "get" }
     ]
}

您可以调用该链接来获取包含所有子部门链接的资源。

{
    ...
    "links": [
      { "rel": "subdepartment", "href": "departments/321/subdepartments/1", "method": "get" },
      { "rel": "subdepartment", "href": "departments/321/subdepartments/2", "method": "get" }
    ]
}

它的工作方式几乎就像浏览网站并单击链接。

阅读 Roy Fielding 本人的这篇博文: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven

这种方法可能会出现明显的复杂性和性能问题。当服务器应用程序可以与客户端分开发展时,真正的 RESTful 服务才有意义。否则,只需使用带有查询字符串参数的方法。

【讨论】:

  • 谢谢。像我上一个示例中那样提供 href 是否有任何价值?
  • 这真的取决于使用服务的客户端。默认情况下提供链接并使用一些 OData 样式的 $expand=true 查询参数来用实际资源替换链接可能是个好主意。
  • 我不确定 REST 中的任何内容是否是必须
  • @Opal Roy Fielding,这个人在他的论文中首先描述了 REST 架构,他在他的博客中说。使用 URL 作为端点的基于 HTTP 的基本服务没有任何问题,但它们并不是真正的 RESTful。
  • @DmitryS。那将是我的问题:我应该何时返回资源链接与集合 URI 的资源表示?什么是“RESTful”的做法,有时违反规则是否有效?例如,您说 GET "departments/321/subdepartments" 应该返回指向所有子部门的链接列表。如果我需要在一个表中显示所有子部门的详细信息,并且有 5000 个,那么我需要对每个 URI 进行 5000 个 GET 请求……这样有效吗?我认为在这种情况下,包含所有资源的单个 GET 会更有效。你能详细说明一下吗?
【解决方案2】:

添加这些参数我没有任何问题,所以继续使用它,最重要的部分是您管理http状态代码,响应具有读取数据的良好结构(您拥有它! )

另外,如果您想了解其他方式,请使用 OData:Web API and OData

【讨论】:

    【解决方案3】:

    这听起来非常适合http://jsonapi.org/ - 在构建 JSON 响应时,它是“你的反自行车脱落武器”。与实现您自己的 ad-hoc 模式相比,通读规范一开始可能需要一些时间,但它确实得到了回报。 该规范还包含section about "compound documents" 的一部分,它还利用include=… 参数通过一个请求获取多个文档/资源。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-24
      • 2011-12-10
      • 2019-12-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多