Understanding About Response Caching ASP.NET Core – Windows ASP.NET Core Hosting 2024 | Review and Comparison

Storage of response output is known as response caching. Response caching is a technique used by browsers and other clients to save a server’s response so that it can be promptly and effectively retrieved in response to future requests. Response caching in ASP.NET Core lessens server load and enhances user experience in online applications. This blog’s goal is to give a thorough explanation of how response caching works in ASP.NET Core.

What is Response Caching?

The server can swiftly retrieve responses for subsequent requests by storing them in memory or on disk using the response cache. When a request is sent to the server, caching techniques scan the cache for responses. The cache returns the response rather than creating a new one. Utilizing response caching lessens some server workload and server requests.

Note: HTTP caching directives and how we can control caching behavior using them

Response Caching Headers

To cache the response, the ‘Client and Server’ exchange HTTP header data. HTTP caching directives and how to use them to regulate caching behavior. The response’s caching options are defined by cache control. When the cache-control header is present in the response, it is the obligation of browsers, clients, and proxy servers to respect it.

The following are the Main Response Caching Headers.

  • Cache-Control
  • Pragma
  • Vary
  • Cache-Control Header

The primary header type for response caching is Cache-Control. In ASP.Net Core, you can use the Response object in your controller’s action method to include a Cache-Control header. To begin, let’s look at the standard cache-control directives:

  1. public: this cache can store the response either on the client side or at a shared location.
  2. private: This Private Cache always stores Client Side Response But does Not Shred the Cache From The Client Side.
  3. max-age: this cache-control header represents a time to hold a response in the cache.
  4. no-cache: this value indicates that the client should not cache the response.
  5. no-store: this cache must not store the response.

Pragma Header

The Pragma header can regulate cache performance for ASP.NET Core. Instructions for the server and client are contained in the Pragma header. If the answer is annotated with Cache-Control, pragma is skipped.

Vary Header

This method’s request message includes the Vary http response header, and the response’s URL serves as its body.

ResponseCache Attribute

In the ASP.NET Core web app, ResponseCache attributes define header all properties for response cache headers. Each endpoint or the controller level can use this attribute.

You can discover a handful of the cache attribute’s input parameters below.

Duration

The response’s cached duration in seconds can be set or retrieved. This sets the “cache-control” header’s “max-age” value. The duration of this property will result in the production of the max-age header, which is used to define the cache lifetime.

Location

sets the Location, which specifies where to cache data from a specific URL. The client uses the Location as a cached response if it is decorated with “ResponseCacheLocation.Client,” which sets “cache-control” to the private header.

The Location in this illustration is embellished with “ResponseCacheLocation.The “Pragma” header is set to “no-cache,” and “None” acts as the “cache-control” mechanism.

Note: Use Swagger to run API endpoints in the browser or click links on web pages if you can check the cache response.

Otherwise, regardless of the response cache settings, the browser will always request a new answer from the server side if you attempt to refresh the page or return to the URI page.

public class HomeController: Controller
{
    [HttpGet]
    [ResponseCache(Duration = 180, Location = ResponseCacheLocation.Any)]
    public IActionResult getCache()
    {
        return Ok($"Responses are generated on {DateTime.Now}");
    }
}

The max-age header, which we use to specify the duration of the cache for 3 minutes (180 seconds), will be produced by this Duration attribute. The cache-control header’s Location will be defined by the Location property.

So, check these response headers from the API endpoint and:

cache-control: public,max-age=180

The response originates from the disk cache, according to the status code:

Status Code: 200

Private

Only the Location property in ResponseCacheLocation.Client needs to be changed from public to private:

public class HomeController: Controller
{
    [HttpGet]
    [ResponseCache(Duration = 180, Location = ResponseCacheLocation.Client)]
    public IActionResult getCache()
    {
        return Ok($"Responses are generated on {DateTime.Now}");
    }
}

By setting the cache control header’s value to private, only the client will be able to cache the answer.

cache-control: private,max-age=180

No-Cache

Let’s change Location to ResponseCacheLocation for the time being. None:

public class HomeController: Controller
{
    [HttpGet]
    [ResponseCache(Duration = 180, Location = ResponseCacheLocation.None)]
    public IActionResult getCache()
    {
        return Ok($"Responses are generated on {DateTime.Now}");
    }
}

The client cannot utilize a cached answer without first checking it with the server since the cache-control and pragma headers are set to no-cache:

cache-control: no-cache,max-age=180

pragma: no-cache

Each time, the browser doesn’t use the cached response; instead, the server creates a fresh response.

NoStore

Determines whether to store the data by getting or setting the value. NoStore’s “cache-control” header is set to “no-store” if it is decorated with the value “true”. The parameter has ignored the values and has ignored the “Location”; otherwise, the values are “None”.

public class HomeController: Controller
{
    [HttpGet]
    [ResponseCache(Duration = 180, Location = ResponseCacheLocation.Any,NoStore =True)]
    public IActionResult getCache()
    {
        return Ok($"Responses are generated on {DateTime.Now}");
    }
}

The response header cache control is changed to no-store as a result. Therefore, the client shouldn’t save the response in caching:

cache-control: no-store

VaryByHeader

The “Vary” response header value is set or retrieved. We may set the vary header using ResponseCache’s VaryByHeader property:

The cached answer will be used as long as the request comes from the same client device because User-Agent is now the value for the VaryByHeader field. A new answer is obtained from the server once the User-Agent value on the client device changes. Let’s check this out.

public class HomeController: Controller
{
    [HttpGet]
    [ResponseCache(Duration = 180, Location = ResponseCacheLocation.Any,VaryByHeader="User-Agent")]
    public IActionResult getCache()
    {
        return Ok($"Responses are generated on {DateTime.Now}");
    }
}

In the response headers, check for the Vary header:

vary: User-Agent

The response header “Vary” has the value “User-Agent” when the application is running in desktop mode, as can be seen below.

  • user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36
  • user-agent: Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1

VaryByQueryKeys Property

The server can be made to produce a new response each time the response will change by using the VaryByQueryKeys property. The query string parameters have changed.

public class HomeController: Controller
{
    [HttpGet]
    [ResponseCache(Duration = 180, Location = ResponseCacheLocation.Any, VaryByQueryKeys = new string[] { "Id " })]
    public IActionResult getCache()
    {
        return Ok($"Responses are generated on {DateTime.Now}");
    }
}

For example, When the Id value change and then URI also change, and  we want to generate a new response:

/api/Home?Id=1

/api/Home?Id=2

Cache Profile

Given that most action methods in this project have the same input parameters, you can use Response Cache properties. All parameter options with ASP.Net Core are associated to one another in a Program class, which can be used in the Response Cache attribute to get rid of redundant parameter sets.

Cache3 is a brand-new cache profile with a 3 minute time limit and a public location.

builder.Services.AddControllers (option =>
{
   option.Cache Profiles.Add("Cache3",
      new CacheProfile()
      {
          Duration= 180,
          Location = ResponseCacheLocation.Any
      });
});
public class HomeController: Controller
{
    [HttpGet]
    [ResponseCache (Cache ProfileName ="Cache3")]
    public IActionResult getCache()
    {
        return Ok ($"Responses are generated on (DateTime.Now}");
    }
}

The defined cache-control response (see below):

cache-control: public,max-age=180

Caching Middleware

Although a response cache can be added by middleware, this method adds a response cache to each page.

Program.cs File

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddResponseCaching();

var app = builder.Build();

app.MapControllers();
app.UseResponseCaching () ;
app.Run();
public class HomeController: Controller
{
    [HttpGet]
    [ResponseCache(Duration = 180, Location = ResponseCacheLocation.Any, VaryByQueryKeys = new string[] { "Id" })]
    public IActionResult getCache(int Id)
    {
        return Ok($"Responses are generated on Id:{Id} at {DateTime.Now}");
    }
}

The response caching middleware should first be added using the AddResponseCaching() function, and then the app should be set up to use it using UseResponseCaching().

I’m done now. VaryByQueryKeys ought to now function because the middleware for response caching has been enabled.

Let’s launch the program and go to the /Home?id=1 endpoint.

The response was generated for Id:1 at 23-05-2022 05:52:50

The query string could be modified to get a different answer from the server.

The query string will now read as /Home?id=2:

The response was generated for Id:2 at 23-05-2022 05:53:45

Conclusion

Web applications may scale and operate more effectively thanks to the response caching feature of ASP.NET Core. By caching replies at the server or client level, it is possible to accelerate and enhance the effectiveness of page loading.

You can set up caching middleware in ASP.NET Core to cache replies according to the URL path, query string parameters, and HTTP headers. Cache location, cache key prefixes, and cache expiration durations are just a few of the parameters you can use to tailor the caching behavior.

Utilizing response caching in ASP.NET Core will improve user happiness and lower hosting costs. Response caching should be regarded as a major optimization approach when developing a website or web application that will receive a lot of traffic.