ASP.NET Core 2.2: Complete Updates of Resources with HTTP Put

To make a complete update of a resource, an HTTP Put is used on one of our endpoints. In the next blog post, we will learn how to do a partial update.

When we do an update with HTTP Put, it must be complete. So we expect the client to send us all the data of the resource. When we say that an update is complete, we mean that we must update all the fields of the resource.

In response, we can return either a 200 OK or a 204 No Content. Given the fact that the client already has the resource, sending a 204 No Content makes sense.

Let’s implement this. In a controller related to authors, called AuthorsController, we can place the following method:

[HttpPut("{id}", Name = "UpdateAuthor")]
public async Task<ActionResult> Put(int id, [FromBody] Author author)
{
    if (author.Id != id){
        return BadRequest();
    }

    _context.Entry(author).State = EntityState.Modified;
    await _context.SaveChangesAsync();
    return NoContent();
}

As we can see, the first thing we do is verify that the Id of the route value and the id of the sent author coincide, otherwise, we return a 400 Bad Request. After that, we mark the object as modified and then update it with Entity Framework asynchronously.

The reason why we have to do the verification of the IDs is that we are using as the input value of the Put function the class that we use as an entity, that is, the Author class. If we wanted to avoid this kind of thing, as we have already seen, we can use a DTO or ViewModel as the input value of the function.

(We talked about DTOs in a previous entry)

In order to use DTOs in this case, we could either reuse the author creation DTO or create a new one specifically for updating authors. Given the fact that the update and creation have the same business rules in our application, we can reuse the author creation DTO, however, in other applications it might make sense to create a new DTO for this. We can update our function as follows:

[HttpPut("{id}", Name = "UpdateAuthor")]
public async Task<ActionResult> Put(int id, [FromBody] AuthorCreationDTO authorUpdate)
{
  var author = _mapper.Map<Author>(authorUpdate);
  author.Id = id;
  _context.Entry(author).State = EntityState.Modified;
  await _context.SaveChangesAsync();
  return NoContent();
}

With this, we are not exposing our author entity to the outside world, which means that our entities can evolve freely without problems with the clients of our Web API.

Certainly, the HTTP PUT is for complete updates of a resource, however, this is not always what we want. A disadvantage of the complete updates is that we need the user to send all the fields of the resource so that we can do this update. Sometimes, our users will only want to update one or several fields, but not all. For this, we can use HTTP Patch. We’ll see that in the next post.

Summary

  • We use HTTP Put to perform complete updates
  • A complete update is one that updates all the fields
  • It is normal to return a 204 No Content when an HTTP Put is successful

Thanks!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s