How to Implement Caching in ASP.NET Core 8 Web API – In-Memory, Response and Distributed Caching Examples

How to Implement Caching in ASP.NET Core 8 Web API – Types & Examples

Introduction to Caching

Caching Strategies in ASP.NET Core 8

Why Caching is Important

Types of Caching in ASP.NET Core

1. IMemoryCache

When to Use IMemoryCache

A Few Things to Keep in Mind In IMemoryCache

Code Example (Step-by-Step):

dotnet new webapi -n MemoryCacheDemo
cd MemoryCacheDemo
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

// Register Memory Cache
builder.Services.AddMemoryCache();

var app = builder.Build();

app.MapControllers();

app.Run();
namespace MemoryCacheDemo.Services;

public class ProductService
{
    public async Task<List<string>> GetProductsAsync()
    {
        // Simulate slow database call
        await Task.Delay(3000);

        return new List<string>
        {
            "Laptop",
            "Keyboard",
            "Mouse",
            "Monitor"
        };
    }
}
builder.Services.AddScoped<ProductService>();
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using MemoryCacheDemo.Services;

namespace MemoryCacheDemo.Controllers;

[ApiController]
[Route("api/[controller]")]
public class ProductController : ControllerBase
{
    private readonly IMemoryCache _cache;
    private readonly ProductService _productService;

    public ProductController(IMemoryCache cache, ProductService productService)
    {
        _cache = cache;
        _productService = productService;
    }

    [HttpGet]
    public async Task<IActionResult> GetProducts()
    {
        string cacheKey = "productList";

        if (!_cache.TryGetValue(cacheKey, out List<string> products))
        {
            // Data not in cache → fetch from service
            products = await _productService.GetProductsAsync();

            var cacheOptions = new MemoryCacheEntryOptions()
                .SetAbsoluteExpiration(TimeSpan.FromMinutes(5))
                .SetSlidingExpiration(TimeSpan.FromMinutes(2));

            _cache.Set(cacheKey, products, cacheOptions);
        }

        return Ok(products);
    }
}

Cleaner Alternative – Using GetOrCreateAsync (Recommended)

[HttpGet]
public async Task<IActionResult> GetProducts()
{
    string cacheKey = "productList";

    var products = await _cache.GetOrCreateAsync(cacheKey, async entry =>
    {
        entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5);
        entry.SlidingExpiration = TimeSpan.FromMinutes(2);

        return await _productService.GetProductsAsync();
    });

    return Ok(products);
}
dotnet run
GET https://localhost:5001/api/product
.SetAbsoluteExpiration(TimeSpan.FromMinutes(5))
.SetSlidingExpiration(TimeSpan.FromMinutes(2))
dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis
builder.Services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = "localhost:6379";
    options.InstanceName = "DemoInstance_";
});
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using System.Text.Json;
using MemoryCacheDemo.Services;

namespace MemoryCacheDemo.Controllers;

[ApiController]
[Route("api/[controller]")]
public class ProductController : ControllerBase
{
    private readonly IDistributedCache _cache;
    private readonly ProductService _productService;

    public ProductController(IDistributedCache cache, ProductService productService)
    {
        _cache = cache;
        _productService = productService;
    }
}
[HttpGet("distributed")]
public async Task<IActionResult> GetProductsDistributed()
{
    string cacheKey = "productList";

    // Try to get cached data
    var cachedData = await _cache.GetStringAsync(cacheKey);

    if (string.IsNullOrEmpty(cachedData))
    {
        // Cache miss → fetch data from service
        var products = await _productService.GetProductsAsync();

        var options = new DistributedCacheEntryOptions
        {
            AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5),
            SlidingExpiration = TimeSpan.FromMinutes(2)
        };

        // Serialize and store in Redis
        await _cache.SetStringAsync(cacheKey, JsonSerializer.Serialize(products), options);

        return Ok(products);
    }

    // Cache hit → deserialize JSON
    var cachedProducts = JsonSerializer.Deserialize<List<string>>(cachedData);

    return Ok(cachedProducts);
}
dotnet run
GET https://localhost:5001/api/product/distributed

What is Response Caching?

When to Use

Code Example (Step-by-Step)

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

// Enable Response Caching
builder.Services.AddResponseCaching();

var app = builder.Build();

app.UseResponseCaching(); // Add middleware

app.MapControllers();
app.Run();
using Microsoft.AspNetCore.Mvc;
using MemoryCacheDemo.Services;

namespace MemoryCacheDemo.Controllers;

[ApiController]
[Route("api/[controller]")]
public class ProductController : ControllerBase
{
    private readonly ProductService _productService;

    public ProductController(ProductService productService)
    {
        _productService = productService;
    }

    [HttpGet("response")]
    [ResponseCache(Duration = 60, Location = ResponseCacheLocation.Client)]
    public async Task<IActionResult> GetProductsResponseCache()
    {
        // Simulate slow database call
        var products = await _productService.GetProductsAsync();
        return Ok(products);
    }
}
GET https://localhost:5001/api/product/response

Comparison of Caching Types in ASP.NET Core 8 Web API

Conclusion

Related Blogs You Might Like

🚀 Subscribe for Tech Updates

📧

👤

We respect your privacy. Unsubscribe anytime.