Reputation: 13885
I have a ProductsController and I want to create an action method that copies a product. It only needs one parameter which is an Id which temps me to want to use a simple GET Request. Something is telling me GET doesn't make sense here though. Do I really use POST and pass a single Id to this method?
Here is what I came up with:
// COPY: api/products/{id}/copy
[HttpPost("{id}/copy")]
public void Copy(int id)
{
_productManager.Copy(sourceProductId: id);
}
Upvotes: 7
Views: 5710
Reputation: 18295
I'd basically handle the situation using one of the following approaches:
COPY
Do as per the WebDav specification and just use COPY
http method. This, I believe, is the most semantically correct way of cloning/copying a resource in a RESTful manner. Note that REST do not restricts you in using just the default verbs:
[AcceptVerbs("COPY")]
[Route("{id}")]
public void Copy(int id)
{
_productManager.Copy(sourceProductId: id);
}
POST
Keep using the same method you are using for creating a new resource (because, after all, you are creating a new resource), but with an optional query string parameter that will determine if you are copying an existing resource.
You will then trigger the copy operation by sending a POST
request with an empty body to a URI similar to the following one: http://myhost/api/products?sourceId=1
. Here it is a code sample:
[HttpPost]
[Route("")]
public void CreateOrCopy([FromBody] ProductDTO dto, [FromUri] int? sourceId = null)
{
if(dto == null && sourceId.HasValue)
_productManager.Copy(sourceProductId: id); // copy behavior
else
// normal behavior
}
I think that both approaches are very usable from a client point of view, without breaking REST constraints or semantic meanings (absolutely avoid the use of GET
for such a purpose).
Upvotes: 12