The misunderstanding around PUT x PATCH

Author:

Over years working on development, I always had a doubt with the usage of the PATCH method.

On this article I’m going to show an example on the C# .NET Core perspective.

But first, a summary of it:

In ASP.NET Core, a PATCH endpoint is used to apply partial modifications to a resource. It is part of the HTTP/1.1 specification and is particularly useful in RESTful APIs when you want to update only specific fields of a resource rather than sending the entire resource representation.

Basically:

PUT updates an entire resource (replacing it), example:

{ “name”: “John Doe”, “age”: 22, “country”: “BR” }

If you make a PUT to update only the age setting 25 your object should look like this:

{ “name”: “”, “age”: 25, “country”: “” }

So update the entire resource

PATCH is used for partial updates

Key Characteristics of PATCH in NET Core:

  • Partial Updates: Unlike PUT, which typically requires a complete representation of the resource, PATCH allows you to send only the fields that need to be updated. This can reduce the amount of data sent over the network.
  • Request Format: The request body for a PATCH operation usually contains a JSON object that specifies the fields to be updated and their new values. The format can vary; for example, you might use JSON Merge Patch or JSON Patch.
  • Method Implementation: In ASP.NET Core, you can implement a PATCH endpoint using the [HttpPatch] attribute in your controller. This helps define a method that will handle incoming PATCH requests.
  • Routing: The PATCH endpoint typically maps to a specific resource, allowing clients to target a specific item for modification.

This method is really powerful as it can handle multiple operations (insert and remove too).

Code example

using Microsoft.AspNetCore.JsonPatch;  
using Microsoft.AspNetCore.Mvc;  
using System.Collections.Generic;  
using System.Linq;  
  
[ApiController]  
[Route("api/[controller]")]  
public class ProductsController : ControllerBase  
{  
    private static List<Product> Products = new List<Product>  
    {  
        new Product { Id = 1, Name = "Product 1", Price = 10.0M },  
        new Product { Id = 2, Name = "Product 2", Price = 20.0M }  
    };  
  
    [HttpPatch("{id}")]  
    public IActionResult PatchProduct(int id, [FromBody] JsonPatchDocument<Product> patchDoc)  
    {  
        if (patchDoc == null)  
        {  
            return BadRequest();  
        }  
  
        var product = Products.FirstOrDefault(p => p.Id == id);  
        if (product == null)  
        {  
            return NotFound();  
        }  
  
        patchDoc.ApplyTo(product, ModelState);  
  
        if (!ModelState.IsValid)  
        {  
            return BadRequest(ModelState);  
        }  
  
        return NoContent();  
    }  
}  
  
public class Product  
{  
    public int Id { get; set; }  
    public string Name { get; set; }  
    public decimal Price { get; set; }  
}  

Explanation of the Example:

PATCH endpoint expect to follow a certain structure. I’m going to cover operations to Add and Remove.

How’s the expected payload

  • If you want to UPDATE a field for a certain object
[ 
   { "op": "replace", "path": "/Name", "value": "Updated Product Name" }, 
   { "op": "replace", "path": "/Price", "value": 19.99 } 
]
  • If you want to ADD a new product

[ { “op”: “add”, “path”: “/Name”, “value”: “This is a new product” } ]

  • If you want to remove a property

[ { “op”: “remove”, “path”: “/Price” } ]

You can execute this code and see the results.

Conclusion

It’s not often I see developers using almost 100% of the time PUT instead of PATCH.

I hope this article finds helpful.