Blake Rivell
Blake Rivell

Reputation: 13885

RESTFull HTTP method to use when performing a copy of an object with Web API

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

Answers (1)

Federico Dipuma
Federico Dipuma

Reputation: 18295

I'd basically handle the situation using one of the following approaches:


1. 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);
}

2. 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

Related Questions