PUT
The HTTP PUT verb is idempotent. This means that the first HTTP PUT request with a certain payload will impact the server and the resource. It will update the resource specified by ID. However, subsequent HTTP PUT requests with the same payload would result in the same response as the first one.
Consider the following example where we will update one product:
// PUT: api/Products/1
[HttpPut("{id}")]
public async Task<IActionResult> Put(int id, [FromBody]Product product)
=> (await _productService.UpdateProductAsync(id, product))
? Ok()
: StatusCode(500);
The [HttpPut] attribute is supplied with a template of {id} similar to what we had in [HttpGet]. In the case of PUT, it would get the ID from the URL and the Product object from the body of the request, which is specified by the [FromBody] attribute as we did in the case of POST in the previous section.
When the ID and the product object is tied with the arguments, the method body starts execution, which in turn calls the service method UpdateProductAsync with the same parameters. That method would return a Boolean based on whether the update was successful. If everything was successful, we would return 200 OK by calling the OK() method, otherwise a 500 Internal Server Error would be given if an error occurred.
Let me show you the screenshot from Postman:
Another status code, 301 Moved Permanently, can be returned if the PUT request comes with an ID that has expired, meaning the product passed in the request body is not associated with the ID. To identify this condition, we need to add business logic accordingly, and if we can verify whether the ID is related to the product or not. If not, we can simply return 301 Moved Permanently with the new URL where the product actually exists currently.