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