Quantcast
Channel: briancaos – Brian Pedersen's Sitecore and .NET Blog
Viewing all articles
Browse latest Browse all 276

.NET Core Caching in your API using AddResponseCaching and ResponseCache attribute

$
0
0

Caching the response of an API speeds up the API endpoint because the code that generates the response is not called, but rather fetched from memory. This is especially helpful for API’s where the response is time-consuming to retrieve but the response does not change.

To add a response cache, you need to declare that caching is enabled, then specify the cache parameters for each of your API endpoints.

STEP 1: ENABLE CACHING IN Program.cs

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddResponseCaching();  
var app = builder.Build();
app.UseHttpsRedirection();
// UseCors must be called before UseResponseCaching
// app.UseCors();
app.UseResponseCaching();
app.UseAuthorization();
app.MapControllers();
app.Run();

It is important that you call UseResponseCaching AFTER you have called UseCors.

STEP 2: DEFINE THE CACHE PROPERTIES FOR YOUR API ENDPOINT

To declare the cache properties for an endpoint, use the [ResponseCache] attribute:

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace MyCode.Controllers
{
  [Route("api/[controller]")]
  [ApiController]
  public class MyController : ControllerBase
  {
    public MyController()
    {
    } 

    [HttpGet]
    [ResponseCache(Duration=10)]
    public string? GetCatFact()
    {
      // Pseudocode. Call something that will return a random cat fact
      // Insert your own code logic here:
      CatModel? catFact = _httpRepository.GetAsync<CatModel>("https://catfact.ninja/fact").Result;
      return catFact?.Fact;
    }
  }
}

In the example above, the ResponseCache attribute will cache the response for 10 seconds unconditionally.

The first request will call the underlying code, but the next requests are fetched from the memory cache, until the cache expires after 10 seconds. The response header will now have a max-age of 10, indicating the cache duration:

Response headers now has the cache-control max-age of 10, indicating that this response is cached in 10 seconds.
API Response as seen in Swagger

VARY THE CACHE BY HEADERS OR QUERYSTRING

The your API endpoint response is controlled using querystrings, you should add those as variation:

[HttpGet]
[ResponseCache(Duration=30, VaryByQueryKeys=new[] {"id", "search"})]
public string? GetCatFact([FromQuery] int id, [FromQuery] string search)
{
  // Still pseudo code, add your own logic
  CatModel? catFact = _httpRepository.GetAsync<CatModel>("https://catfact.ninja/fact").Result;
  return catFact?.Fact + id + search;
}

The response will very depending of the value of the querystrings. Use VaryByHeaders to vary by headers.

DEFINING CACHE PROFILES

Instead of defining the cache individually per endpoint, you can create cache profiles that can be reused. Go to the Program.cs and add the profiles to the AddControllers method:

builder.Services.AddControllers(options => 
  {
    options.CacheProfiles.Add("Default", 
      new CacheProfile() { Duration = 10 }
    );
    options.CacheProfiles.Add("Client",
      new CacheProfile() { Location = ResponseCacheLocation.Client, Duration = 10 }
    );
  }
);

Then use the profile name in the API endpoint. You can still decorate the endpoint with VaryByHeader/VaryByQueryKeys:

  [HttpGet]
  [ResponseCache(CacheProfileName="Default")]
  public string? GetCatFact()
  {
    CatModel? catFact = _httpRepository.GetAsync<CatModel>("https://catfact.ninja/fact").Result;
    return catFact?.Fact;
  }

  [HttpGet("2")]
  [ResponseCache(CacheProfileName="Client", VaryByQueryKeys=new[] {"id", "search"})]
  public string? GetCatFact2([FromQuery] int id, [FromQuery] string search)
  {
    CatModel? catFact = _httpRepository.GetAsync<CatModel>("https://catfact.ninja/fact").Result;
    return catFact?.Fact + id + search;
  }

That’s it. You are now a caching expert. Happy coding.

MORE TO READ:


Viewing all articles
Browse latest Browse all 276

Trending Articles