Search code examples
c#restkeyhttprequestput

Why must HTTP PUT requests pass the entity key in the URL (as well as in the request body)?


Consider a RESTful service that exposes entities of type Product whose class is declared as follows:

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

Now suppose that we want to completely update the Product whose ID is 123. Then we can easily do this by performing a standard HTTP PUT request like the following:

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

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

What is the justification behind repeating the key twice? Shouldn't we still be able to completely update the Product entity even if we omit the ID key from the URL, since we could always just extract the key from the request body? I get that PUT is intended to be idempotent and that this redundancy issue could be avoided entirely by using PATCH instead of PUT, but I was just wondering about the motivation behind this weird convention. I tried reading the official protocol documentation for PUT, but they don't seem to talk about it.


Solution

  • The short answer is that HTTP PUT doesn't care, which is why you won't find anything about this in the HTTP specifications.

    The (slightly) longer answer is that REST requires it for reasons of consistency. All REST calls use a URI that uniquely identifies the resource being acted on.

    In REST a PUT means "replace the contents of the resource represented by the URI with the resource I am sending you." If your URI references a collection and you send a single object the REST API in question should probably treat that as an error.

    So a PUT operation is effectively a combination of DELETE and POST. Depending on the nature of your data it could be completely valid to PUT a new value for your primary key to replace the old one. In most structures I use I'd consider that to be bad form, but it seems to be perfectly OK to do so as far as REST is concerned.

    There are lots of questions about REST. Here is a good answer that I've referenced several times that gives a fairly simple explanation of what the various verbs mean with respect to collections vs members.