Caching Web Pages
In this lesson, we will learn how to control response caching.
Responses returned by Web servers can be cached in various places during their path to their target client applications. They can be cached in various Internet intermediary nodes, and in the browser cache itself.
HTTP standard headers control the way a response must be cached and when it can be cached. ASP.NET Core supports Web response caching through the ResponseCacheAttribute
action filter that manipulates the HTTP headers that affect response caching. It also allows response caching on the Web server itself.
In the sections below, we will describe the HTTP caching headers, how to use the ResponseCacheAttribute
action filter, and how to cache responses on the server.
HTTP cache headers
The main HTTP header that affects response caching is Cache-Control
which can assume several commas separated values. The table below describes all allowed values:
Cache-Control value | Effect | Example |
---|---|---|
public | The response is not specific for a single user so, it can be stored in the browser and on all intermediary nodes. | public |
private | The response is specific for a single user so, it can be stored in the browser and in intermediary nodes that serve that specific user (usually just in the browser). | private |
max-age | The number of seconds the cache is considered valid. When this time expires the cached response is not accepted by the client and validation is asked to the server, which, in turn, can respond that the cached content is still valid or can provide a fresher response. | public, max-age=80 |
no-cache | The response can be cached but must be validated by the original server before being used. Therefore, a request to the server is issued anyway, to ask it if the cache is expired. | no-cache |
no-store | Response must not be cached. | no-store |
It is worth mentioning when max-age
expires with no-cache
, cache records continue to be stored. However, the server must confirm they are still valid. So the request must be transmitted to the server. Usually, the server answers with a new response that overrides all cached results.
Usually, servers also issue the Pragma: no-cache
header together with Cache-Control: no-cache
for retro compatibility with old specifications. However, the Pragma
header is now obsolete.
It is also possible to specify an absolute date+time after which the cache is no more valid with the Expires
header, as shown below:
Expires: Wed, 10 Mar 2021 07:28:00 GMT
The Vary
header is also important. It contains a comma-separated list of HTTP headers. A different cache entry is created for each combination of the listed header values, as shown below:
Vary: accept-encoding, accept-language
It is worth pointing out that GET
ASP.NET Core requests with different routes or query string parameters are cached in different entries since their URLs are different. Therefore, the cache must be refreshed only when a response to the same parameters changes.
Moreover, by default, ASP.NET Core only allows caching for GET
requests, as it assumes that the response to other verbs depends on the body content. Thus we should only worry about GET
requests caching.
The ResponseCacheAttribute action filter
The ResponseCacheAttribute
action filter can be used to configure all cache-related headers of an action method response. It can be applied both to the controller and to each action method. The action method configuration overrides the controller configuration.
It has a Location
property where ResponseCacheLocation.Any
, and ResponseCacheLocation.Client
values map respectively to the public
and private
Cache-Control
values.
The Duration
property maps to the max-age
Cache-Control
value.
The Vary
property maps directly to the Vary
header value.
Finally, when the NoStore
property is set, the no-store
value is added to the Cache-Control
header. While, when the Location
property is set to ResponseCacheLocation.None
the no-cache
value is added to the Cache-Control
header.
The example below allows caching of 3 minutes on both the browser and any intermediate node:
Get hands-on with 1400+ tech skills courses.