Caché de respuestas en ASP.NET Core

Por Rick Anderson y Kirk Larkin

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 configura en los encabezados.

El atributo ResponseCache establece los encabezados de almacenamiento en caché de respuesta. Los clientes y servidores proxy intermedios deben respetar los encabezados de las respuestas de almacenamiento en caché en la especificación RFC 9111: Almacenamiento en caché HTTP .

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

El middleware de almacenamiento en caché de respuestas permite almacenar en caché las respuestas del servidor basadas en encabezados de Cache-Control HTTP.

  • El comportamiento de almacenamiento en caché implementa la semántica de almacenamiento en caché HTTP estándar.

  • El almacenamiento en caché se basa en encabezados de caché HTTP similares al método usado por servidores proxy.

  • Esta forma de almacenamiento en caché es útil para las solicitudes públicas de API GET o HEAD de los clientes en los que se cumplen las condiciones de almacenamiento en caché .

  • En el caso de las aplicaciones de interfaz de usuario como Razor Pages, el almacenamiento en caché de respuestas no suele ser beneficioso. Los exploradores suelen establecer encabezados de solicitud que impiden el almacenamiento en caché.

    Almacenamiento en caché de salida (disponible en .NET 7 y versiones posteriores) es un mejor enfoque para las aplicaciones de interfaz de usuario. En este escenario, la configuración determina qué almacenar en caché independientemente de los encabezados HTTP.

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 obtener más información, consulte Solución de problemas > de middleware de almacenamiento en caché de respuestas.

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

Caché de respuesta basado en HTTP

La especificación 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 hacen su camino desde los clientes a los servidores y las respuestas hacen su camino de 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.

Directive Action
public Una 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 (un 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é.

Header Function
Age Proporciona una estimación de la cantidad de tiempo en segundos desde que la respuesta se generó o validó correctamente en el servidor de origen.
Expires Especifica el tiempo después del cual la respuesta se considera obsoleta.
Pragma Existe para la compatibilidad con versiones anteriores con almacenamientos en caché HTTP/1.0 para activar la acción 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

La especificación 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 del 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. .NET 7 y versiones posteriores incluye compatibilidad con el almacenamiento en caché para controlar mejor la carga del servidor. Para más información, vea Almacenamiento en caché de salida.

Atributo ResponseCache

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

Warning

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

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

El middleware de caché de respuestas 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 administrada por el middleware de almacenamiento en caché de respuestas. 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.

Request Devuelto desde
http://example.com?key1=value1 Server
http://example.com?key1=value1 Middleware
http://example.com?key1=NewValue Server

El servidor devuelve la primera solicitud y el middleware almacena en caché la solicitud. El middleware devuelve la segunda solicitud porque la cadena de consulta coincide con la solicitud anterior (primera). 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.

La clase ResponseCacheAttribute se usa para configurar y crear (a través de la interfaz IFilterFactory) un Microsoft.AspNetCore.Mvc.Internal.ResponseCacheFilter. ResponseCacheFilter realiza el trabajo de actualizar los encabezados HTTP y las características adecuados de la respuesta. 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 la característica HTTP de almacenamiento en caché de respuesta si la propiedad VaryByQueryKeys está establecida.

Variar el encabezado

Este encabezado solo se escribe cuando se establece la propiedad VaryByHeader. La propiedad pasa al valor Vary de la propiedad. 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 el método de los servicios del middleware de almacenamiento en caché de respuestas AddResponseCaching a la colección de servicios. El código 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();

Propiedades NoStore y Location.None

La propiedad NoStore ignora 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 la Location propiedad está establecida en None:

  • El encabezado Cache-Control se configura en no-store,no-cache.
  • El encabezado Pragma se configura en no-cache.

Si la propiedad NoStore se establece en false y la propiedad Location se establece en None, los encabezados Cache-Control y Pragma se establecen en no-cache.

Normalmente, la propiedad NoStore se establece en true para las páginas de error. El código siguiente genera 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 el ResponseCacheAttribute a todas las respuestas de controladores de MVC o de las páginas de Razor Pages de la aplicación, añada el atributo con el filtro de MVC o el filtro de Razor Pages.

En una aplicación MVC, agregue el código siguiente:

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

Para un enfoque que se aplica a las aplicaciones de Razor Pages, consulte el problema dotnet/aspnetcore #18890 en GitHub - . La adición de ResponseCacheAttribute a la lista de filtros globales de MVC no se aplica a Razor Pages. El ejemplo de comentario del problema se aplica a las aplicaciones de ASP.NET Core anteriores a la versión de Minimal API (ASP.NET Core versión 6.0). En el caso de las aplicaciones que tienen como destino la versión 6.0 y posteriores, cambie el registro de servicio usado en el ejemplo a builder.Services.AddSingleton... en el archivo Program.cs .

Propiedades de ubicación y duración

Para habilitar el almacenamiento en caché, la Duration propiedad 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 la propiedad Location de Any y Client se traducen en valores de encabezado Cache-Control de public y private, respectivamente. Como se indica en la sección NoStore y Location.None, establecer la propiedad Location en None establece los encabezados Cache-Control y Pragma en no-cache.

La configuración de la propiedad Location.Any (Cache-Control establecida en public) indica que el cliente o cualquier proxy intermedio puede almacenar el valor en caché, incluido el middleware de almacenamiento en caché de respuestas.

La configuración de la propiedad Location.Client (establecida en Cache-Controlprivate) indica que solo el cliente puede almacenar en caché el valor. Ninguna caché intermedia debe almacenar el valor en caché, incluido el middleware de almacenamiento en caché de respuestas.

Los encabezados de control de caché proporcionan instrucciones a los clientes y servidores proxy intermedios sobre cuándo y cómo almacenar en caché las respuestas. No hay ninguna garantía de que los clientes y servidores proxy respeten la especificación 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 la Duration propiedad y dejando el valor de propiedad 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 caché de respuestas en muchos atributos de acción del controlador, los perfiles de caché se pueden configurar como opciones al configurar páginas de MVC o Razor Pages. Los valores encontrados en un perfil de caché al que se hace referencia se usan como valores predeterminados por .ResponseCacheAttribute Las propiedades especificadas en el atributo invalidan los valores de perfil de caché a los que se hace referencia.

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

Puede aplicar el atributo [ResponseCache] a las Páginas, controladores MVC y métodos de acción MVC.

En Razor Pages, no se pueden aplicar atributos a métodos de controlador porque los exploradores usados con aplicaciones de interfaz de usuario impiden el almacenamiento en caché de respuestas. En un método de acción MVC, los atributos de nivel de método invalidan la configuración especificada en 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());
}

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 los encabezados de caché de respuesta. Los clientes y los servidores proxy intermedios deben respetar los encabezados para las respuestas de caché según el RFC 9111: HTTP Caching.

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

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.

Directive Action
public 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é.

Header Function
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.
Expires Tiempo a partir del cual la respuesta se considera obsoleta.
Pragma Existe para la compatibilidad con versiones anteriores con almacenamientos en caché HTTP/1.0 para activar la acción 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 del 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 puede ser manejada por cualquier servidor del grupo si los datos en caché del cliente están disponibles. ASP.NET Core funciona con cachés distribuidas de SQL Server, Redis, Postgres 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.

Warning

Deshabilite el almacenamiento en caché para el contenido que contiene información para los clientes autenticados. El almacenamiento en caché solo se debe habilitar 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 caché de respuestas 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 administrada por el middleware de almacenamiento en caché de respuestas. 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.

Request Result
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. 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 la funcionalidad de 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 o de Razor Pages de la aplicación, añádalo con un filtro de MVC o un 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 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 el valor en caché, incluido el middleware de almacenamiento en caché de respuestas.

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

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