Customize Consent Preferences

We use cookies to help you navigate efficiently and perform certain functions. You will find detailed information about all cookies under each consent category below.

The cookies that are categorized as "Necessary" are stored on your browser as they are essential for enabling the basic functionalities of the site. ... 

Always Active

Necessary cookies are required to enable the basic features of this site, such as providing secure log-in or adjusting your consent preferences. These cookies do not store any personally identifiable data.

No cookies to display.

Functional cookies help perform certain functionalities like sharing the content of the website on social media platforms, collecting feedback, and other third-party features.

No cookies to display.

Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics such as the number of visitors, bounce rate, traffic source, etc.

No cookies to display.

Performance cookies are used to understand and analyze the key performance indexes of the website which helps in delivering a better user experience for the visitors.

No cookies to display.

Advertisement cookies are used to provide visitors with customized advertisements based on the pages you visited previously and to analyze the effectiveness of the ad campaigns.

No cookies to display.

blog
Ottorino Bruni  

How to Use Response Caching for Faster Results in ASP.NET Core Minimal API

Introduction

In modern web applications, performance is a key factor for both user satisfaction and system efficiency. One highly effective technique to enhance performance is response caching. With response caching, browsers or other clients store a copy of a server’s response locally. When the same resource is requested again, the cached version is served instantly. This saves time by eliminating unnecessary communication with the server and avoids duplicate work on the server side.

ASP.NET Core provides several powerful caching mechanisms tailored to different scenarios, including in-memory caching, distributed caching, and response caching. In this article, we’ll focus specifically on Response Caching in the context of Minimal APIs. We’ll explore how it works, why it improves performance, and see a step-by-step example of implementing it effectively.

In ASP.NET Core, we have several caching mechanisms available, but today we’ll focus on Response Caching, particularly in the context of Minimal APIs.

What is Response Caching?

Response caching is a way to store the server’s response to a request so that the same data can be reused without requiring the server to execute the same logic repeatedly. This technique benefits both the client and the server by:

  • Reducing server load: The server doesn’t need to process the same request multiple times.
  • Improving client performance: The client retrieves the data faster since it’s served from the cache.
  • Saving bandwidth: Cached responses minimize data transfer, especially for large payloads.

ASP.NET Core’s Response Caching Middleware provides the functionality to cache HTTP responses. However, it works best for idempotent GET requests, where the response doesn’t change unless the resource itself changes.

 If you’re interested in further optimizing your caching strategies, check out my previous articles on How to Implement In-Memory Caching in .NET Console App Using C# and How to Implement Redis Cache in .NET using Minimal APIs and C#. Both provide valuable techniques that complement the output caching insights shared here.

How to Use Response Caching for Faster Results in ASP.NET Core Minimal API

Understanding Client-Side vs Server-Side Caching

Before diving into the implementation, let’s clarify the key differences between client-side and server-side caching:

Client-Side Response Caching

  • Stores responses in the client’s browser or proxy servers
  • Controlled through HTTP headers (Cache-Control, Age, Vary, etc.)
  • Reduces network traffic by avoiding unnecessary server requests
  • Ideal for static or semi-static data that doesn’t change frequently
  • No server memory consumption

Server-Side Caching

  • Stores data in server memory or distributed cache (Redis, SQL Server)
  • Requires server resources to maintain the cache
  • Provides more control over cached data
  • Suitable for dynamic data that needs server-side processing
  • For more details about server-side caching, check my previous articles on In-Memory and Distributed caching

Brief Explanation of HTTP-Based Response Caching

HTTP-based response caching, defined in RFC 9111, describes how internet caches (such as client-side caches, proxy servers, or reverse proxies) should behave to improve the efficiency of web communication. The Cache-Control HTTP header plays a crucial role in controlling caching behavior, enabling caches to store responses and reuse them to reduce latency, bandwidth usage, and load on servers.

Key Concepts in HTTP Caching

  1. Cache-Control Directives:
    These are instructions included in HTTP headers that guide how requests and responses should be cached. Here are some common directives:
    • public: The response can be stored and reused by any cache (e.g., browsers, shared proxies).
    • private: Limits caching to a single client. Shared caches (like proxies) must not store the response.
    • max-age: Defines how many seconds a response can remain fresh in the cache. Example:
      • max-age=60: Cache the response for 60 seconds.
      • max-age=2592000: Cache the response for 30 days (1 month).
    • no-cache:
      • On requests: The cache must revalidate the response with the origin server before serving it.
      • On responses: Clients must validate the response with the origin server before reuse.
    • no-store: Prohibits the cache from storing any part of the request or response.
  2. Other Cache Headers:
    Beyond Cache-Control, additional headers influence caching:
    • Age: Indicates the time (in seconds) since the response was generated or validated at the origin server.
    • Expires: Specifies an expiration date/time after which the response is considered stale.
    • Pragma: Used for backward compatibility with HTTP/1.0 caches (e.g., setting no-cache). Ignored if Cache-Control is present.
    • Vary: Ensures cached responses are served correctly by requiring certain request headers to match. For example, if Vary: Accept-Language is set, separate cached responses are stored for each language.

How Does Response Caching Work in ASP.NET Core?

When you enable response caching in ASP.NET Core, the server adds specific HTTP headers to the response. These caching headers inform clients and any intermediate caches (e.g., CDN providers) how to cache the response.

Key headers involved include:

  • Cache-Control: Specifies how caching should work (e.g., whether caching is allowed, duration, etc.).
  • Expires: Indicates when the cached response should expire.
  • Vary: Modifies how caching is handled for requests with different headers (e.g., caching separate versions of the response based on Accept-Language).

For example, when a client makes a GET request, a cached response can be served without involving the server if the headers show it is still valid.

Example: Implement Response Caching in ASP.NET Core Minimal API

Disclaimer: This example is intended for educational purposes only. While it demonstrates key concepts, there are more efficient ways to write and optimize this code in real-world applications. Consider this a starting point for learning, and always aim to follow best practices and refine your implementation.

In this example, we’ll demonstrate how to implement Response Caching in an ASP.NET Core Minimal API. You’ll see how to:

  • Introduce variations in caching behavior using the VaryByHeader.
  • Configure the ResponseCache attribute to cache GET responses for 10 seconds.
  • Use middleware to inspect cache behavior and provide custom headers.

Prerequisites

Before starting, make sure you have the following installed:

  • .NET SDK: Download and install the .NET SDK if you haven’t already.
  • Visual Studio Code (VSCode): Install Visual Studio Code for a lightweight code editor.
  • C# Extension for VSCode: Install the C# extension for VSCode to enable C# support.

Step 1: Create a Minimal API

dotnet new webapi -minimal -n ResponseCachingApi
cd ResponseCachingApi

Add the Microsoft.AspNetCore.ResponseCaching NuGet package:

dotnet add package Microsoft.AspNetCore.ResponseCaching
How to Use Response Caching for Faster Results – Nuget Package

Step 2: Set Up Response Caching

The first step is to integrate Response Caching Middleware into your ASP.NET Core Minimal API pipeline. This middleware handles caching logic and serves responses directly from the cache when possible, bypassing the endpoint logic entirely.

To enable Response Caching:

  • Register the ResponseCaching service within the builder.Services.AddResponseCaching() method.
  • Call app.UseResponseCaching() in the middleware pipeline to enable the caching system.

Here’s how the setup looks inside the Program.cs file:

builder.Services.AddResponseCaching();   // Register Response Caching service
...
app.UseResponseCaching();                // Enable the middleware

 Step 3: Added middleware to set response cache headers

  • Added a custom middleware to set HTTP cache headers
  • Sets Cache-Control: public, max-age=5
  • Sets Vary: User-Agent to match the original example’s behavior
app.Use(async (context, next) =>
{
    context.Response.GetTypedHeaders().CacheControl = new CacheControlHeaderValue
    {
        Public = true,
        MaxAge = TimeSpan.FromSeconds(5)
    };
    
    // Add Vary header for the User-Agent
    context.Response.Headers[HeaderNames.Vary] = "User-Agent";
    
    await next();
});

Step 3: Define the Endpoint

Our example demonstrates a /quotes endpoint that returns a collection of motivational quotes, along with a request counter and the current server time for demonstration purposes.

  • Response caching relies on HTTP headers, so no endpoint-specific configuration is needed

Here’s the endpoint definition:

app.MapGet("/quotes", () => {
    requestCounter++;
    var response = new {
        RequestNumber = requestCounter,
        ServerTime = DateTime.UtcNow,
        Quotes = quotes,
        CacheInfo = "This response will be cached for 5 seconds using Response Caching"
    };
    return Results.Ok(response);
})
.WithName("GetQuotes");
How to Use Response Caching for Faster Results in ASP.NET Core Minimal API

Step 5: Overall Program Setup

Here’s the full setup of your Program.cs file, including middleware and endpoint configuration:

using Microsoft.Net.Http.Headers;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();
builder.Services.AddResponseCaching();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
}

app.UseResponseCaching();

// Add middleware to set response cache headers
app.Use(async (context, next) =>
{
    context.Response.GetTypedHeaders().CacheControl = new CacheControlHeaderValue
    {
        Public = true,
        MaxAge = TimeSpan.FromSeconds(5)
    };
    
    // Add Vary header for the User-Agent
    context.Response.Headers[HeaderNames.Vary] = "User-Agent";
    
    await next();
});

app.UseHttpsRedirection();

// In-memory storage for demonstration (not thread-safe, for demo only)
var quotes = new[]
{
    "The best way to get started is to quit talking and begin doing.",
    "Don't let yesterday take up too much of today.",
    "It's not whether you get knocked down, it's whether you get up.",
    "The optimist sees opportunity in every difficulty."
};

// Request counter (for demonstration purposes)
int requestCounter = 0;

app.MapGet("/quotes", () =>
{
    requestCounter++;

    var response =  new
    {
        RequestNumber = requestCounter,
        ServerTime = DateTime.UtcNow,
        Quotes = quotes,
        CacheInfo = "This response will be cached for 5 seconds"
    };

    return Results.Ok(response);
})
.WithName("GetQuotes");

app.Run();

Explanation of How Response Caching Works

When you enable response caching by adding the ResponseCaching middleware and setting appropriate HTTP cache headers, the Response Caching Middleware intercepts requests and checks if a cached response can be served.

  1. First Request: When a client requests the /quotes endpoint for the first time, the application logic is executed, and the response is generated fresh. The middleware stores this response in the cache based on the HTTP cache headers. Example:
    • RequestNumber: 1
    • ServerTime: 2025-01-10T15:00:00
  2. Subsequent Requests (Cached): For all requests within 5 seconds of the first request (as specified by the max-age=5 directive), the middleware serves the cached response without executing the endpoint logic again. Example:
    • The RequestNumber remains 1 (cached value)
    • The ServerTime remains 2025-01-10T15:00:00
  3. Cache Expiry: After 5 seconds, the cache expires, and the next request is processed from scratch. The endpoint logic runs and generates a new value for RequestNumber and ServerTime.

Response Caching vs. Output Caching

FeatureResponse CachingOutput Caching
Caching MiddlewareRequires ResponseCaching MiddlewareRequires OutputCache Middleware
Caching SetupHTTP headers (Cache-Control, etc.) or [ResponseCache] attribute.CacheOutput() or [OutputCache] attribute
Cache ProtocolBased on HTTP caching standard (RFC 7234)ASP.NET Core specific implementation
Response VariationUses standard HTTP Vary headerFlexible with .Tag(...), VaryByQuery, etc.
Cache LocationBoth server and client (browser) cachingServer-side only
Client ParticipationBrowsers and proxies can also cacheOnly server manages the cache
Best Use CaseRESTful APIs that follow HTTP standards, public APIsAPIs requiring fine-grained server control over caching
How to Use Response Caching for Faster Results in ASP.NET Core Minimal API

Final Thoughts

Response Caching in ASP.NET Core is an easy and highly effective way to improve the performance of APIs by caching responses both on the server side and potentially in client browsers. This dramatically reduces server workload for frequently accessed resources like static data or rarely-changing endpoints.

By following the steps in this guide, you can add HTTP-standard response caching to your Minimal APIs, ensuring optimized performance and a faster user experience. The beauty of Response Caching is that it follows the HTTP caching protocol, which means browsers and proxy servers can also participate in the caching strategy, further reducing network traffic and server load.

You can build upon this foundation by varying cached responses using the Vary header, which allows you to create different cache entries based on request headers like Accept, Accept-Language, or User-Agent.

For more details on response caching, check out the official ASP.NET Core Documentation.

If you think your friends or network would find this article useful, please consider sharing it with them. Your support is greatly appreciated.

Thanks for reading!

🚀 Discover CodeSwissKnife, your all-in-one, offline toolkit for developers!

Click to explore CodeSwissKnife 👉

Leave A Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.