Almacenamiento en caché de respuestas de ASP.NET Core

Por Rick Anderson y Kirk Larkin

Vea o descargue el código de ejemplo (cómo descargarlo)

El almacenamiento en caché de respuestas reduce el número de solicitudes que realiza un cliente o proxy en un servidor web. El almacenamiento en caché de respuesta también reduce la cantidad de trabajo que realiza el servidor web para generar una respuesta. El almacenamiento en caché de respuestas se establece en encabezados.

El atributo ResponseCache establece encabezados de almacenamiento en caché de respuesta. Los clientes y los servidores proxy intermedios deben respetar los encabezados para almacenar en caché las respuestas en RFC 9111: almacenamiento en caché HTTP.

Para el almacenamiento en caché del lado servidor que sigue a la especificación de almacenamiento en caché HTTP 1.1, use Middleware de almacenamiento en caché de respuesta. El middleware puede utilizar las propiedades ResponseCacheAttribute para influir en el comportamiento del almacenamiento en caché del lado del servidor.

Middleware de almacenamiento en caché de respuestas:

  • Habilita el almacenamiento en caché de respuestas del servidor basadas en encabezados de caché HTTP. Implementa la semántica de almacenamiento en caché HTTP estándar. Cachés basadas en encabezados de caché HTTP, como los servidores proxy.
  • Normalmente no se recomienda en aplicaciones de interfaz de usuario, como Razor Pages, porque los exploradores suelen establecer encabezados de solicitud que impiden el almacenamiento en caché. El almacenamiento en caché de resultados, que está disponible en ASP.NET Core 7.0 y versiones posteriores, beneficia a las aplicaciones de interfaz de usuario. Con el almacenamiento en caché de resultados, la configuración decide qué se debe almacenar en caché independientemente de los encabezados HTTP.
  • Puede ser beneficioso para las solicitudes públicas de API HEAD o GET de los clientes en los que se cumplen las condiciones para el almacenamiento en caché.

Para probar el almacenamiento en caché de respuestas, use Fiddler u otra herramienta que pueda establecer explícitamente encabezados de solicitud. Se prefiere establecer explícitamente los encabezados para probar el almacenamiento en caché. Para más información, consulte Solución de problemas.

Almacenamiento en caché de respuesta basado en HTTP

RFC 9111: almacenamiento en caché HTTP describe cómo deben comportarse las cachés de Internet. El encabezado HTTP principal que se usa para el almacenamiento en caché es Cache-Control, que se usa para especificar directivas de caché. Las directivas controlan el comportamiento del almacenamiento en caché a medida que las solicitudes van desde los clientes a los servidores y a medida que las respuestas van desde los servidores de vuelta a los clientes. Las solicitudes y respuestas se mueven a través de servidores proxy y los servidores proxy también deben cumplir con la especificación de almacenamiento en caché HTTP 1.1.

Las directivas Cache-Control más comunes se muestran en la siguiente tabla.

Directiva Acción
pública Una memoria caché puede almacenar la respuesta.
private Una caché compartida no debe almacenar la respuesta. Una caché privada puede almacenar y reutilizar la respuesta.
max-age El cliente no acepta una respuesta cuya antigüedad es mayor que el número de segundos especificado. Ejemplos: max-age=60 (60 segundos), max-age=2592000 (1 mes)
no-cache En las solicitudes: una memoria caché no debe usar una respuesta almacenada para satisfacer la solicitud. El servidor de origen vuelve a generar la respuesta del cliente y el middleware actualiza la respuesta almacenada en su caché.

En las respuestas: la respuesta no se debe usar para una solicitud posterior sin validación en el servidor de origen.
no-store En las solicitudes: una memoria caché no debe almacenar la solicitud.

En las respuestas: una memoria caché no debe almacenar ninguna parte de la respuesta.

En la tabla siguiente se muestran otros encabezados de caché que desempeñan un papel en el almacenamiento en caché.

Encabezado Función
Age Una estimación de la cantidad de tiempo en segundos desde que la respuesta se generó o validó correctamente en el servidor de origen.
Expira Tiempo a partir del cual la respuesta se considera obsoleta.
Pragma Existe para la compatibilidad con versiones anteriores con cachés HTTP/1.0 para establecer el comportamiento no-cache. Si el encabezado Cache-Control está presente, el encabezado Pragma se ignora.
Vary Especifica que no se debe enviar una respuesta almacenada en caché a menos que todos los campos de encabezado Vary coincidan tanto en la solicitud original de la respuesta almacenada en caché como en la nueva solicitud.

El almacenamiento en caché basado en HTTP respeta las directivas de solicitud Cache-Control

RFC 9111: almacenamiento en caché HTTP (sección 5.2. Cache-Control) requiere una memoria caché para respetar un encabezado válido Cache-Control enviado por el cliente. Un cliente puede realizar solicitudes con un valor de encabezado no-cache y forzar al servidor a generar una nueva respuesta para cada solicitud.

Respetar siempre los encabezados de solicitud de cliente Cache-Control tiene sentido si considera el objetivo del almacenamiento en caché HTTP. En la especificación oficial, el almacenamiento en caché está diseñado para reducir la latencia y la sobrecarga de red de satisfacer las solicitudes en una red de clientes, servidores proxy y servidores. No es necesariamente una manera de controlar la carga en un servidor de origen.

No hay ningún control de desarrollador sobre este comportamiento de almacenamiento en caché al usar el Middleware de almacenamiento en caché de respuesta porque el middleware se adhiere a la especificación de almacenamiento en caché oficial. Se ha agregado compatibilidad con el almacenamiento en caché de salida para controlar mejor la carga del servidor en .NET 7. Para más información, vea Almacenamiento en caché de salida.

Atributo ResponseCache

ResponseCacheAttribute especifica los parámetros necesarios para establecer los encabezados apropiados en el almacenamiento en caché de respuesta.

Advertencia

Deshabilite el almacenamiento en caché para el contenido que contiene información para los clientes autenticados. El almacenamiento en caché solo debe habilitarse para el contenido que no cambia en función de la identidad de un usuario o si un usuario ha iniciado sesión.

VaryByQueryKeys varía la respuesta almacenada por los valores de la lista especificada de claves de consulta. Cuando se proporciona un único valor de *, el middleware varía las respuestas según todos los parámetros de la cadena de consulta de la solicitud.

El middleware de almacenamiento en caché de respuesta debe estar habilitado para establecer la propiedad VaryByQueryKeys. De lo contrario, se produce una excepción en tiempo de ejecución. No hay un encabezado HTTP correspondiente para la propiedad VaryByQueryKeys. La propiedad es una característica HTTP controlada por middleware de almacenamiento en caché de respuesta. Para que el middleware sirva una respuesta almacenada en caché, la cadena de consulta y el valor de cadena de consulta deben coincidir con una solicitud anterior. Por ejemplo, considere la secuencia de solicitudes y resultados que se muestran en la tabla siguiente:

Solicitud Devuelto desde
http://example.com?key1=value1 Servidor
http://example.com?key1=value1 Software intermedio
http://example.com?key1=NewValue Servidor

El servidor devuelve la primera solicitud y se almacena en caché en middleware. El middleware devuelve la segunda solicitud porque la cadena de consulta coincide con la solicitud anterior. La tercera solicitud no está en la memoria caché de middleware porque el valor de la cadena de consulta no coincide con una solicitud anterior.

ResponseCacheAttribute se usa para configurar y crear (a través de IFilterFactory) un Microsoft.AspNetCore.Mvc.Internal.ResponseCacheFilter. ResponseCacheFilter realiza el trabajo de actualizar los encabezados HTTP y las características adecuados de la respuesta. El filtro:

  • Quita los encabezados existentes para Vary, Cache-Control y Pragma.
  • Escribe los encabezados adecuados en función de las propiedades establecidas en ResponseCacheAttribute.
  • Actualiza las características del almacenamiento en caché de respuesta HTTP si se establece VaryByQueryKeys.

Vary

Este encabezado solo se escribe cuando se establece la propiedad VaryByHeader. La propiedad establecida al valor de la propiedad Vary. En el ejemplo siguiente se usa la propiedad VaryByHeader:

[ApiController]
public class TimeController : ControllerBase
{
    [Route("api/[controller]")]
    [HttpGet]
    [ResponseCache(VaryByHeader = "User-Agent", Duration = 30)]
    public ContentResult GetTime() => Content(
                      DateTime.Now.Millisecond.ToString());

Vea los encabezados de respuesta con Fiddler u otra herramienta. Los encabezados de respuesta incluyen:

Cache-Control: public,max-age=30
Vary: User-Agent

El código anterior requiere añadir los servicios de Middleware de almacenamiento en caché de respuesta AddResponseCaching a la colección de servicios y configura la aplicación para usar el middleware con el método de extensión UseResponseCaching.

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 y Location.None

NoStore invalida la mayoría de las demás propiedades. Cuando esta propiedad se establece en true, el encabezado Cache-Control se establece en no-store. Si Location se establece en None:

  • El valor de Cache-Control está establecido en no-store,no-cache.
  • El valor de Pragma está establecido en no-cache.

Si NoStore es false y Location es None, Cache-Control y Pragma se establecen en no-cache.

NoStore normalmente se establece en true para las páginas de error. A continuación se generan encabezados de respuesta que indican al cliente que no almacene la respuesta.

[Route("api/[controller]/ticks")]
[HttpGet]
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
public ContentResult GetTimeTicks() => Content(
                  DateTime.Now.Ticks.ToString());

El código anterior incluye los siguientes encabezados en la respuesta:

Cache-Control: no-store,no-cache
Pragma: no-cache

Para aplicar ResponseCacheAttribute a todas las respuestas de página del controlador MVC de la aplicación o Razor Pages, agréguelo con un filtro MVC o filtro de Razor Pages.

En una aplicación MVC:

builder.Services.AddControllersWithViews().AddMvcOptions(options => 
    options.Filters.Add(
        new ResponseCacheAttribute
        {
            NoStore = true, 
            Location = ResponseCacheLocation.None
        }));

Para un enfoque aplicable a Razor Pages, consulte La adición de ResponseCacheAttribute a la lista de filtros globales MVC no se aplica a Razor Pages (dotnet/aspnetcore #18890). El ejemplo proporcionado en el comentario del problema se escribió para las aplicaciones destinadas a ASP.NET Core antes de la publicación de las API mínimas en la versión 6.0. Para las aplicaciones 6.0 o posteriores, cambie el registro del servicio en el ejemplo a builder.Services.AddSingleton... para Program.cs.

Ubicación y duración

Para habilitar el almacenamiento en caché, Duration debe establecerse en un valor positivo y Location debe ser Any (el valor predeterminado) o Client. El marco establece el encabezado Cache-Control con el valor de ubicación seguido del max-age de la respuesta.

Las opciones de Location de Any y Client se traducen en valores de encabezado de Cache-Control de public y private, respectivamente. Como se indica en la sección NoStore y Location.None, la configuración de Location en None establece los encabezados Cache-Control y Pragma en no-cache.

Location.Any (Cache-Control establecido en public) indica que el cliente o cualquier proxy intermedio puede almacenar en caché el valor, incluido el middleware de almacenamiento en caché de respuesta.

Location.Client (Cache-Control establecido en private) indica que solo el cliente puede almacenar en caché el valor. Ninguna caché intermedia debe almacenar en caché el valor, incluido el middleware de almacenamiento en caché de respuesta.

Los encabezados de control de caché indican a los clientes y a los proxies intermediarios cuándo y cómo almacenar en caché las respuestas. No hay garantía de que los clientes y proxies respeten RFC 9111: almacenamiento en caché HTTP. El middleware de almacenamiento en caché de respuesta siempre sigue las reglas de almacenamiento en caché establecidas por la especificación.

En el ejemplo siguiente se muestran los encabezados generados estableciendo Duration y dejando el valor predeterminado Location:

[Route("api/[controller]/ms")]
[HttpGet]
[ResponseCache(Duration = 10, Location = ResponseCacheLocation.Any, NoStore = false)]
public ContentResult GetTimeMS() => Content(
                  DateTime.Now.Millisecond.ToString());

El código anterior incluye los siguientes encabezados en la respuesta:

Cache-Control: public,max-age=10

Perfiles de caché

En lugar de duplicar la configuración de la caché de respuesta en muchos atributos de acción del controlador, los perfiles de caché se pueden configurar como opciones al establecer MVC/Razor Pages. Los valores encontrados en un perfil de caché al que se hace referencia son usados como predeterminados por ResponseCacheAttribute y se sobrescriben por cualquier propiedad especificada en el atributo.

En el ejemplo siguiente se muestra un perfil de caché de 30 segundos:

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();

El siguiente código hace referencia al perfil de caché Default30:

[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());
}

El encabezado de respuesta resultante del perfil de caché Default30 incluye:

Cache-Control: public,max-age=30

El atributo [ResponseCache] se puede aplicar a:

  • Razor Pages: los atributos no se pueden aplicar a los métodos de controlador. Los exploradores usados con aplicaciones de interfaz de usuario impiden el almacenamiento en caché de respuestas.
  • Controladores MVC.
  • Métodos de acción de MVC: los atributos de nivel de método reemplazan la configuración especificada en los atributos de nivel de clase.

El siguiente código aplica el atributo [ResponseCache] a nivel de controlador y a nivel de método:

[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());
}

Recursos adicionales

Vea o descargue el código de ejemplo (cómo descargarlo)

El almacenamiento en caché de respuestas reduce el número de solicitudes que realiza un cliente o proxy en un servidor web. El almacenamiento en caché de respuesta también reduce la cantidad de trabajo que realiza el servidor web para generar una respuesta. El almacenamiento en caché de respuesta se controla mediante encabezados que especifican cómo desea que el cliente, el proxy y el middleware almacenen en caché las respuestas.

[ResponseCache] participa en la configuración de encabezados de almacenamiento en caché de respuesta. Los clientes y los servidores proxy intermedios deben respetar los encabezados para almacenar en caché las respuestas en RFC 9111: almacenamiento en caché HTTP.

Para el almacenamiento en caché del lado servidor que sigue a la especificación de almacenamiento en caché HTTP 1.1, use Middleware de almacenamiento en caché de respuesta. El middleware puede usar las propiedades [ResponseCache] para establecer encabezados de almacenamiento en caché del lado servidor.

Almacenamiento en caché de respuesta basado en HTTP

RFC 9111: almacenamiento en caché HTTP describe cómo deben comportarse las cachés de Internet. El encabezado HTTP principal que se usa para el almacenamiento en caché es Cache-Control, que se usa para especificar directivas de caché. Las directivas controlan el comportamiento del almacenamiento en caché a medida que las solicitudes van desde los clientes a los servidores y a medida que las respuestas van desde los servidores de vuelta a los clientes. Las solicitudes y respuestas se mueven a través de servidores proxy y los servidores proxy también deben cumplir con la especificación de almacenamiento en caché HTTP 1.1.

Las directivas Cache-Control más comunes se muestran en la siguiente tabla.

Directiva Acción
pública Una memoria caché puede almacenar la respuesta.
private Una caché compartida no debe almacenar la respuesta. Una caché privada puede almacenar y reutilizar la respuesta.
max-age El cliente no acepta una respuesta cuya antigüedad es mayor que el número de segundos especificado. Ejemplos: max-age=60 (60 segundos), max-age=2592000 (1 mes)
no-cache En las solicitudes: una memoria caché no debe usar una respuesta almacenada para satisfacer la solicitud. El servidor de origen vuelve a generar la respuesta del cliente y el middleware actualiza la respuesta almacenada en su caché.

En las respuestas: la respuesta no se debe usar para una solicitud posterior sin validación en el servidor de origen.
no-store En las solicitudes: una memoria caché no debe almacenar la solicitud.

En las respuestas: una memoria caché no debe almacenar ninguna parte de la respuesta.

En la tabla siguiente se muestran otros encabezados de caché que desempeñan un papel en el almacenamiento en caché.

Encabezado Función
Age Una estimación de la cantidad de tiempo en segundos desde que la respuesta se generó o validó correctamente en el servidor de origen.
Expira Tiempo a partir del cual la respuesta se considera obsoleta.
Pragma Existe para la compatibilidad con versiones anteriores con cachés HTTP/1.0 para establecer el comportamiento no-cache. Si el encabezado Cache-Control está presente, el encabezado Pragma se ignora.
Vary Especifica que no se debe enviar una respuesta almacenada en caché a menos que todos los campos de encabezado Vary coincidan tanto en la solicitud original de la respuesta almacenada en caché como en la nueva solicitud.

El almacenamiento en caché basado en HTTP respeta las directivas de solicitud Cache-Control

RFC 9111: almacenamiento en caché HTTP (sección 5.2. Cache-Control) requiere una memoria caché para respetar un encabezado válido Cache-Control enviado por el cliente. Un cliente puede realizar solicitudes con un valor de encabezado no-cache y forzar al servidor a generar una nueva respuesta para cada solicitud.

Respetar siempre los encabezados de solicitud de cliente Cache-Control tiene sentido si considera el objetivo del almacenamiento en caché HTTP. En la especificación oficial, el almacenamiento en caché está diseñado para reducir la latencia y la sobrecarga de red de satisfacer las solicitudes en una red de clientes, servidores proxy y servidores. No es necesariamente una manera de controlar la carga en un servidor de origen.

No hay ningún control de desarrollador sobre este comportamiento de almacenamiento en caché al usar el Middleware de almacenamiento en caché de respuesta porque el middleware se adhiere a la especificación de almacenamiento en caché oficial. La compatibilidad con el almacenamiento en caché de salida para controlar mejor la carga del servidor es una propuesta de diseño para una futura versión de ASP.NET Core. Para más información, vea Agregar compatibilidad con el almacenamiento en caché de salida (dotnet/aspnetcore #27387).

Otra tecnología de almacenamiento en caché en ASP.NET Core

Almacenamiento en caché en memoria

El almacenamiento en caché en memoria usa la memoria del servidor para almacenar los datos almacenados en caché. Este tipo de almacenamiento en caché es adecuado para un solo servidor o varios servidores mediante la afinidad de sesión. La afinidad de sesión también se conoce como sesiones persistentes. La afinidad de sesión significa que las solicitudes de un cliente siempre se enrutan al mismo servidor para su procesamiento.

Para más información, consulte Caché en memoria en ASP.NET Core y Solución de problemas de afinidad de sesión de Azure Application Gateway.

Caché distribuida

Use una caché distribuida para almacenar datos en memoria cuando la aplicación se hospeda en una granja de servidores o en la nube. La memoria caché se comparte entre los servidores que procesan las solicitudes. Un cliente puede enviar una solicitud que controla cualquier servidor del grupo si los datos almacenados en caché del cliente están disponibles. ASP.NET Core funciona con cachés distribuidas de SQL Server, Redis y NCache.

Para más información, consulte Almacenamiento en caché distribuido en ASP.NET Core.

Asistente de etiquetas de caché

Almacene en caché el contenido de una vista de MVC o una página de Razor con el asistente de etiquetas de caché. El asistente de etiquetas de caché usa el almacenamiento en caché en memoria para almacenar datos.

Para más información, consulte Asistente de etiquetas de caché en ASP.NET Core MVC.

Asistente de etiquetas de caché distribuida

Almacene en caché el contenido de una vista de MVC o una página de Razor en escenarios distribuidos de la nube o granja de servidores web con el asistente de etiquetas de caché distribuida. El asistente de etiquetas de caché distribuida usa SQL Server, Redis o NCache para almacenar datos.

Para obtener más información, consulte Asistente de etiquetas de caché distribuida en ASP.NET Core.

Atributo ResponseCache

ResponseCacheAttribute especifica los parámetros necesarios para establecer los encabezados apropiados en el almacenamiento en caché de respuesta.

Advertencia

Deshabilite el almacenamiento en caché para el contenido que contiene información para los clientes autenticados. El almacenamiento en caché solo debe habilitarse para el contenido que no cambia en función de la identidad de un usuario o si un usuario ha iniciado sesión.

VaryByQueryKeys varía la respuesta almacenada por los valores de la lista especificada de claves de consulta. Cuando se proporciona un único valor de *, el middleware varía las respuestas según todos los parámetros de la cadena de consulta de la solicitud.

El middleware de almacenamiento en caché de respuesta debe estar habilitado para establecer la propiedad VaryByQueryKeys. De lo contrario, se produce una excepción en tiempo de ejecución. No hay un encabezado HTTP correspondiente para la propiedad VaryByQueryKeys. La propiedad es una característica HTTP controlada por middleware de almacenamiento en caché de respuesta. Para que el middleware sirva una respuesta almacenada en caché, la cadena de consulta y el valor de cadena de consulta deben coincidir con una solicitud anterior. Por ejemplo, considere la secuencia de solicitudes y resultados que se muestran en la tabla siguiente.

Solicitud Resultado
http://example.com?key1=value1 Devuelto desde el servidor.
http://example.com?key1=value1 Devuelto desde el middleware.
http://example.com?key1=value2 Devuelto desde el servidor.

El servidor devuelve la primera solicitud y se almacena en caché en middleware. El middleware devuelve la segunda solicitud porque la cadena de consulta coincide con la solicitud anterior. La tercera solicitud no está en la memoria caché de middleware porque el valor de la cadena de consulta no coincide con una solicitud anterior.

ResponseCacheAttribute se usa para configurar y crear (a través de IFilterFactory) un Microsoft.AspNetCore.Mvc.Internal.ResponseCacheFilter. ResponseCacheFilter realiza el trabajo de actualizar los encabezados HTTP y las características adecuados de la respuesta. El filtro:

  • Quita los encabezados existentes para Vary, Cache-Control y Pragma.
  • Escribe los encabezados adecuados en función de las propiedades establecidas en ResponseCacheAttribute.
  • Actualiza las características del almacenamiento en caché de respuesta HTTP si se establece VaryByQueryKeys.

Vary

Este encabezado solo se escribe cuando se establece la propiedad VaryByHeader. La propiedad establecida al valor de la propiedad Vary. En el ejemplo siguiente se usa la propiedad VaryByHeader:

[ResponseCache(VaryByHeader = "User-Agent", Duration = 30)]
public class Cache1Model : PageModel
{

Con la aplicación de ejemplo, vea los encabezados de respuesta con las herramientas de red del explorador. Los siguientes encabezados de respuesta se envían con la respuesta de la página Cache1:

Cache-Control: public,max-age=30
Vary: User-Agent

NoStore y Location.None

NoStore invalida la mayoría de las demás propiedades. Cuando esta propiedad se establece en true, el encabezado Cache-Control se establece en no-store. Si Location se establece en None:

  • El valor de Cache-Control está establecido en no-store,no-cache.
  • El valor de Pragma está establecido en no-cache.

Si NoStore es false y Location es None, Cache-Control y Pragma se establecen en no-cache.

NoStore normalmente se establece en true para las páginas de error. La página Cache2 de la aplicación de ejemplo genera encabezados de respuesta que indican al cliente que no almacene la respuesta.

[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public class Cache2Model : PageModel
{

La aplicación de ejemplo devuelve la página Cache2 con los encabezados siguientes:

Cache-Control: no-store,no-cache
Pragma: no-cache

Para aplicar ResponseCacheAttribute a todas las respuestas de página del controlador MVC de la aplicación o Razor Pages, agréguelo con un filtro MVC o filtro de Razor Pages.

En una aplicación MVC:

services.AddMvc().AddMvcOptions(options => 
    options.Filters.Add(
        new ResponseCacheAttribute
        {
            NoStore = true, 
            Location = ResponseCacheLocation.None
        }));

Para un enfoque aplicable a Razor Pages, consulte La adición de ResponseCacheAttribute a la lista de filtros globales MVC no se aplica a Razor Pages (dotnet/aspnetcore #18890).

Ubicación y duración

Para habilitar el almacenamiento en caché, Duration debe establecerse en un valor positivo y Location debe ser Any (el valor predeterminado) o Client. El marco establece el encabezado Cache-Control con el valor de ubicación seguido del max-age de la respuesta.

Las opciones de Location de Any y Client se traducen en valores de encabezado de Cache-Control de public y private, respectivamente. Como se indica en la sección NoStore y Location.None, la configuración de Location en None establece los encabezados Cache-Control y Pragma en no-cache.

Location.Any (Cache-Control establecido en public) indica que el cliente o cualquier proxy intermedio puede almacenar en caché el valor, incluido el middleware de almacenamiento en caché de respuesta.

Location.Client (Cache-Control establecido en private) indica que solo el cliente puede almacenar en caché el valor. Ninguna caché intermedia debe almacenar en caché el valor, incluido el middleware de almacenamiento en caché de respuesta.

Los encabezados de control de caché se limitan a indicar a los clientes y a los proxies intermediarios cuándo y cómo almacenar en caché las respuestas. No hay garantía de que los clientes y proxies respeten RFC 9111: almacenamiento en caché HTTP. El middleware de almacenamiento en caché de respuesta siempre sigue las reglas de almacenamiento en caché establecidas por la especificación.

En el ejemplo siguiente se muestra el modelo de página Cache3 de la aplicación de ejemplo y los encabezados generados estableciendo Duration y dejando el valor predeterminado de Location:

[ResponseCache(Duration = 10, Location = ResponseCacheLocation.Any, NoStore = false)]
public class Cache3Model : PageModel
{

La aplicación de ejemplo devuelve la página Cache3 con el siguiente encabezado:

Cache-Control: public,max-age=10

Perfiles de caché

En lugar de duplicar la configuración de la caché de respuesta en muchos atributos de acción del controlador, los perfiles de caché se pueden configurar como opciones al establecer MVC/Razor Pages en Startup.ConfigureServices. Los valores encontrados en un perfil de caché al que se hace referencia son usados como predeterminados por ResponseCacheAttribute y se sobrescriben por cualquier propiedad especificada en el atributo.

Configure un perfil de caché. El siguiente ejemplo muestra un perfil de caché de 30 segundos en Startup.ConfigureServices de la aplicación de ejemplo:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    services.AddMvc(options =>
    {
        options.CacheProfiles.Add("Default30",
            new CacheProfile()
            {
                Duration = 30
            });
    });
}

El modelo de página Cache4 de la aplicación de ejemplo hace referencia al perfil de caché Default30:

[ResponseCache(CacheProfileName = "Default30")]
public class Cache4Model : PageModel
{

ResponseCacheAttribute se puede aplicar a:

  • Razor Pages: los atributos no se pueden aplicar a los métodos de controlador.
  • Controladores MVC.
  • Métodos de acción de MVC: los atributos de nivel de método reemplazan la configuración especificada en los atributos de nivel de clase.

El encabezado resultante se aplica a la respuesta de la página Cache4 mediante el perfil de caché Default30:

Cache-Control: public,max-age=30

Recursos adicionales