Section 3 of 6

Response Caching

🎯 What You'll Learn

  • What is response caching
  • Response caching middleware
  • [ResponseCache] attribute
  • Cache-Control headers
  • VaryByQueryKeys

What is Response Caching?

Response caching stores entire HTTP responses and returns them for subsequent identical requests without executing the action method.

Setup

Program.cs C#
builder.Services.AddResponseCaching();

var app = builder.Build();

app.UseResponseCaching(); // Must be before UseEndpoints

[ResponseCache] Attribute

Basic Usage C#
[ResponseCache(Duration = 60)] // Cache for 60 seconds
public IActionResult Index()
{
    return View();
}

Cache Profiles

Define Cache Profiles C#
builder.Services.AddControllersWithViews(options =>
{
    options.CacheProfiles.Add("Default", new CacheProfile
    {
        Duration = 60
    });
    options.CacheProfiles.Add("Long", new CacheProfile
    {
        Duration = 3600 // 1 hour
    });
});
Use Cache Profile C#
[ResponseCache(CacheProfileName = "Long")]
public IActionResult About()
{
    return View();
}

Cache-Control Headers

Location Options C#
// Client-side only (browser cache)
[ResponseCache(Duration = 60, Location = ResponseCacheLocation.Client)]

// No caching
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]

// Any (client or proxy)
[ResponseCache(Duration = 60, Location = ResponseCacheLocation.Any)]

VaryByQueryKeys

Cache different responses based on query string parameters.

Vary by Query C#
[ResponseCache(Duration = 60, VaryByQueryKeys = new[] { "category" })]
public IActionResult Products(string category)
{
    // Different cache for each category
    return View();
}

InvenTrack Example

ProductsController.cs C#
public class ProductsController : Controller
{
    // Cache product list for 5 minutes
    [ResponseCache(Duration = 300)]
    public async Task<IActionResult> Index()
    {
        var products = await _context.Products.ToListAsync();
        return View(products);
    }

    // Cache varies by category
    [ResponseCache(Duration = 300, VaryByQueryKeys = new[] { "category" })]
    public async Task<IActionResult> ByCategory(string category)
    {
        var products = await _context.Products
            .Where(p => p.Category == category)
            .ToListAsync();
        return View(products);
    }

    // No caching for create/update
    [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
    public IActionResult Create()
    {
        return View();
    }
}

Best Practices

  • GET only: Only cache GET requests
  • No authentication: Don't cache authenticated responses
  • Static content: Best for static or rarely changing data
  • VaryByQueryKeys: Cache different responses per query
  • Cache profiles: Reuse common configurations

Key Takeaways

  • Response caching: Cache entire HTTP responses
  • AddResponseCaching(): Register service
  • UseResponseCaching(): Add middleware
  • [ResponseCache]: Attribute for actions
  • Duration: Cache duration in seconds
  • VaryByQueryKeys: Different cache per query
  • Cache profiles: Reusable configurations