【问题标题】:Why must HTTP PUT requests pass the entity key in the URL (as well as in the request body)?为什么 HTTP PUT 请求必须通过 URL(以及请求正文)中的实体键?
【发布时间】:2014-09-22 18:00:46
【问题描述】:

考虑一个 RESTful 服务,它公开类型为 Product 的实体,其类声明如下:

public class Product
{
    [Key]
    public int ID { get; set; }
    public string Name { get; set; }
    public double Price { get; set; }
}

现在假设我们要完全更新ID123Product。然后我们可以通过执行一个标准的 HTTP PUT 请求来轻松地做到这一点,如下所示:

PUT /odata/Products(123) HTTP/1.1
Host: localhost:1337
Content-Type: application/json

{
    "ID": 123,
    "Name": "Shirt",
    "Price": 19.99
}

重复密钥两次的理由是什么?即使我们从 URL 中省略了 ID 键,我们是否仍然能够完全更新 Product 实体,因为我们总是可以从请求正文中提取键?我知道 PUT 旨在是幂等的,并且可以通过使用 PATCH 而不是 PUT 完全避免这种冗余问题,但我只是想知道这个奇怪约定背后的动机。我尝试阅读official protocol documentation for PUT,但他们似乎没有谈论它。

【问题讨论】:

  • 不确定这里的正确性,但我通常会创建两个视图模型。一个用于整个实体,另一个用于编辑/创建我省略 Id 的实体。

标签: c# rest key httprequest put


【解决方案1】:

简短的回答是 HTTP PUT 并不关心,这就是为什么您在 HTTP 规范中找不到任何关于此的内容的原因。

(稍微)较长的答案是 REST 出于一致性的原因需要它。所有 REST 调用都使用唯一标识正在执行的资源的 URI。

在 REST 中,PUT 的意思是“用我发送给你的资源替换由 URI 表示的资源的内容。”如果您的 URI 引用了一个集合并且您发送了一个对象,那么相关的 REST API 可能应该将其视为错误。

因此,PUT 操作实际上是 DELETE 和 POST 的组合。根据您的数据的性质,为您的主键输入一个新值以替换旧值可能是完全有效的。在我使用的大多数结构中,我认为这是一种不好的形式,但就 REST 而言,这样做似乎完全可以。

有很多关于 REST 的问题。 Here 是一个很好的答案,我已经多次引用了它,它相当简单地解释了各种动词相对于集合与成员的含义。

【讨论】:

    【解决方案2】:

    PUT 是完全替换。无论您传递什么,都将完全替换 URL 中 ID 处的任何内容。

    如果您在 URL 和数据中传递 ID,则服务器不需要知道数据中的哪个字段是 ID。它只是对 URL 中 ID 处的任何内容进行批量替换。保持简单的服务器端。

    这也意味着您可以根据需要更改 ID。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-27
      相关资源
      最近更新 更多