Caching data with distributed caches like Azure Redis Cache is easy – but how to easily cache whole response from your Web API (response code+body) describes this post.
Following method implements REST Get method in Web API controller Order. This method provides information about order from database:
// GET: order/{orderId}
///
/// Get manifest file
///
/// Order ID
[HttpGet("order/{orderId}"]
public IActionResult Get(int orderId)
{
var entry = _repository.GetById(orderId);
if (entry == null)
return NotFound("Order not found.");
return Ok(entry);
}
I needed to add response cache, but I didn’t wanted to care about status codes – if i would only cache the output text, I would miss in cached responses alternative codes like 404 – or i would have to save also some another metadata – which is not so developer-friendly solution.
I got idea – what about cache whole response? Response is object implementing IActionResult, so what about serializate whole response, save to cache – and when is accessed already cached, only load from cache and deserializate and send to client. And how to do it really developer-friendly? I have idea to wrap it into lambda, so original content of method is invoked in lambda and result of the lambda is saved to cache:
// GET: order/{orderId}
/// <summary>
/// Get manifest file
/// </summary>
/// <param name="orderId">Order ID</param>
[HttpGet("order/{orderId}"]
public IActionResult Get(int orderId)
{
var cacheKey = "Get-Order-" + orderId;
var cachedResponse = _distributedCache.GetString(cacheKey);
if (!string.IsNullOrEmpty(cachedResponse))
{
return JsonConvert.DeserializeObject(cachedResponse);
}
}
Func createResponse = () =>
{
var entry = _repository.GetById(orderId);
if (entry == null)
return NotFound("Order not found.");
return Ok(entry);
};
var actionResponse = createResponse();
var serializatedResponse = JsonConvert.SerializeObject(actionResponse);
_distributedCache.SetString(cacheKey, serializatedResponse);
return actionResponse;
}