9.1 C
New York
Thursday, March 20, 2025

How to implement idempotent APIs in ASP.NET Core



Now let’s get started with our implementation. For our example, we’ll use a simple shopping cart application.

Create the model classes

In the project we created earlier, create the following classes in the Models folder.


public class Product
{
   public int Product_Id { get; set; }
   public string Product_Code { get; set; }
   public string Product_Name { get; set; }
   public double Product_Price { get; set; }
}
public class Order
{
   public int Order_Id { get; set; }
   public List Products { get; set; }
}
public class KeyStore
{
   public string Key { get; set; }
   public DateTime Expiry { get; set; }
}

While the Product and Order classes are typically used in a ShoppingCart application, the KeyStore class is used here to store our idempotency keys. In this implementation, we’ll save these keys in the database (dbContext). Naturally, you could change the implementation to store the keys in the cache or any other data store.

Create the controller class

Right-click on the Controllers folder in the Solution Explorer Window and create an API controller called OrderController. Now, enter the following action method in the OrderController class. This method creates a new order.


[HttpPost]
public IActionResult CreateOrder([FromBody] Order order, [FromHeader(Name = "X-Idempotency_Key")] string key)
{
    if (string.IsNullOrEmpty(key))
    {
        return BadRequest("Idempotency key is required.");
    }
    if (_dbContext.KeyStore.FirstOrDefault(k => k.Key == key)!= null)
    {
        var existingItem = _dbContext.Orders.FirstOrDefault(o => o.Order_Id == order.Order_Id);
        return Conflict(new { message = "Request has already been processed.", item = existingItem });
    }
    _dbContext.KeyStore.Add(new KeyStore {Key = key, Expiry = DateTime.Now.AddDays(7)});
    _dbContext.Add(order);
    _dbContext.SaveChanges();
    return Ok(order.Order_Id);
}

Examine the code above. An idempotency key is generated at the client side and passed in the request header. This key will be used by the server to ensure that repeated calls to the same action method will not create duplicate records in the database. In other words, if the key is already present in the KeyStore, then the request for creation of the resource will be ignored. The presence of the key in the KeyStore means that the request was already processed earlier.

Takeaways

By embracing idempotency, you can build APIs that are robust, reliable, and fault-tolerant. Idempotent APIs are particularly important and beneficial in distributed systems, where network issues might lead to large numbers of retried requests from the client side. That said, you should always validate input data to ensure data consistency before storing data in the database.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles