Performance - Caching - Response caching
In this article
-
Enables caching server responses based on HTTP cache headers. Implements the standard HTTP caching semantics. Caches based on HTTP cache headers like proxies do.
-
Is typically not beneficial for UI apps such as Razor Pages because browsers generally set request headers that prevent caching. Output caching, which is available in ASP.NET Core 7.0 and later, benefits UI apps. With output caching, configuration decides what should be cached independently of HTTP headers.
-
May be beneficial for
public
GET or HEAD API requests from clients where the Conditions for caching are met.
HTTP-based response caching
Directive | Action |
---|---|
public | A cache may store the response. |
private | The response must not be stored by a shared cache. A ```private``` cache may store and reuse the response. |
max-age | The client doesn't accept a response whose age is greater than the specified number of seconds. Examples: max-age=60 (60 seconds), max-age=2592000 (1 month) |
no-cache | On requests: A cache must not use a stored response to satisfy the request. The origin server regenerates the response for the client, and the middleware updates the stored response in its cache. On responses: The response must not be used for a subsequent request without validation on the origin server. |
no-store | On requests: A cache must not store the request. On responses: A cache must not store any part of the response. |
Header | Function |
---|---|
Age | An estimate of the amount of time in seconds since the response was generated or successfully validated at the origin server. |
Expires | The time after which the response is considered stale. |
Pragma | Exists for backwards compatibility with HTTP/1.0 caches for setting no-cache behavior. If the Cache-Control header is present, the Pragma header is ignored. |
Vary | Specifies that a cached response must not be sent unless all of the Vary header fields match in both the cached response's original request and the new request. |
Cache-Control
directives
HTTP-based caching respects request ResponseCache attribute
Warning Disable caching for content that contains information for authenticated clients. Caching should only be enabled for content that doesn't change based on a user's identity or whether a user is signed in.
Request | Returned from |
---|---|
http://example.com?key1=value1 |
Server |
http://example.com?key1=value1 |
Middleware |
http://example.com?key1=NewValue |
Server |
-
Removes any existing headers for
Vary
,Cache-Control
, andPragma
. -
Writes out the appropriate headers based on the properties set in the
ResponseCacheAttribute
. -
Updates the response caching HTTP feature if VaryByQueryKeys is set.
Vary
[ApiController]
public class TimeController : ControllerBase
{
[Route("api/[controller]")]
[HttpGet]
[ResponseCache(VaryByHeader = "User-Agent", Duration = 30)]
public ContentResult GetTime() => Content(
DateTime.Now.Millisecond.ToString());
Cache-Control: public,max-age=30
Vary: User-Agent
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddResponseCaching();
var app = builder.Build();
app.UseHttpsRedirection();
// UseCors must be called before UseResponseCaching
//app.UseCors();
app.UseResponseCaching();
app.UseAuthorization();
app.MapControllers();
app.Run();
NoStore
and Location.None
-
Cache-Control
is set tono-store,no-cache
. -
Pragma
is set tono-cache
.
[Route("api/[controller]/ticks")]
[HttpGet]
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
public ContentResult GetTimeTicks() => Content(
DateTime.Now.Ticks.ToString());
builder.Services.AddControllersWithViews().AddMvcOptions(options =>
options.Filters.Add(
new ResponseCacheAttribute
{
NoStore = true,
Location = ResponseCacheLocation.None
}));
Location and Duration
[Route("api/[controller]/ms")]
[HttpGet]
[ResponseCache(Duration = 10, Location = ResponseCacheLocation.Any, NoStore = false)]
public ContentResult GetTimeMS() => Content(
DateTime.Now.Millisecond.ToString());
Cache profiles
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddResponseCaching();
builder.Services.AddControllers(options =>
{
options.CacheProfiles.Add("Default30",
new CacheProfile()
{
Duration = 30
});
});
var app = builder.Build();
app.UseHttpsRedirection();
// UseCors must be called before UseResponseCaching
//app.UseCors();
app.UseResponseCaching();
app.UseAuthorization();
app.MapControllers();
app.Run();
[ApiController]
[ResponseCache(CacheProfileName = "Default30")]
public class Time2Controller : ControllerBase
{
[Route("api/[controller]")]
[HttpGet]
public ContentResult GetTime() => Content(
DateTime.Now.Millisecond.ToString());
[Route("api/[controller]/ticks")]
[HttpGet]
public ContentResult GetTimeTicks() => Content(
DateTime.Now.Ticks.ToString());
}
-
Razor Pages: Attributes can't be applied to handler methods. Browsers used with UI apps prevent response caching.
-
MVC controllers.
-
MVC action methods: Method-level attributes override the settings specified in class-level attributes.
[ApiController]
[ResponseCache(VaryByHeader = "User-Agent", Duration = 30)]
public class Time4Controller : ControllerBase
{
[Route("api/[controller]")]
[HttpGet]
public ContentResult GetTime() => Content(
DateTime.Now.Millisecond.ToString());
[Route("api/[controller]/ticks")]
[HttpGet]
public ContentResult GetTimeTicks() => Content(
DateTime.Now.Ticks.ToString());
[Route("api/[controller]/ms")]
[HttpGet]
[ResponseCache(Duration = 10, Location = ResponseCacheLocation.Any, NoStore = false)]
public ContentResult GetTimeMS() => Content(
DateTime.Now.Millisecond.ToString());
}
Additional resources
-
Storing Responses in Caches
-
Cache-Control
-
Cache in-memory in ASP.NET Core
-
Distributed caching in ASP.NET Core
-
Detect changes with change tokens in ASP.NET Core
-
Response Caching Middleware in ASP.NET Core
-
Cache Tag Helper in ASP.NET Core MVC
-
Distributed Cache Tag Helper in ASP.NET Core