JASoft.org

El blog de José Manuel Alarcón Aguín. Programación web y mucho más...

MENÚ - JASoft: JM Alarcón

ASP.NET: Cómo eliminar la caché de salida (OutputCache) una página o control

Los que me conocéis o habéis ido a alguna de mis charlas sabéis que soy un gran defensor de las técnicas de Caché de salida en las páginas para mejorar el rendimiento y la respuesta de las aplicaciones. De hecho en este blog he hablado ya bastantes veces sobre la Caché en sus diversas variantes. Así que quizá resulte chocante que hoy vaya a hablar sobre justo lo contrario: cómo eliminar la caché de salida (OutputCache) de una página.

Como es sabido, para habilitar la caché de salida de una página o control lo único que tenemos que hacer es añadir una directiva similar a esta al  principio de la página, justo tras la directiva de página:

<%@ OutputCache Duration="60" VaryByParam="None" %>

Los parámetros que se pueden usar son variados y no voy a entrar aquí en detalles pues todo programador de ASP.NET debe conocerlos (si alguien necesita formación sobre desarrollo web, ya sabe ;-)). Es posible hacer caché de la página completa, sólo de algunas partes, de todo menos algunos puntos concretos, que la caché dependa de cualquier parámetro o control, de una variable de QueryString, etc... Incluso definir nuestra propia política de cacheado en función de lo que queramos. En fin, una maravilla, fácil de usar y con resultados espectaculares cuando se aplica juiciosamente.

Pero, como toda herramienta, se puede volver en nuestra contra en un momento dado. ¿Qué pasa si algo ha cambiado y necesitamos que una determinada página -cacheada por un buen rato- se actualice inmediatamente con nueva visualización? En este caso necesitaremos que la caché de la página se elimine de inmediato. Es posible crear una dependencia de caché para que ésta dependa de un archivo, una consulta a una base de datos o casi cualquier otro recurso, pero en ocasiones querremos hacer algo más sencillo.

Luego veremos un caso mucho más claro de porqué queremos borrar este tipo de caché, pero primero quiero ver un caso más simple y su solución, más fácil también.

En el caso de simplemente querer eliminar la caché para una página la solución es bastante sencilla, si bien poco conocida por parte de los programadores de ASP.NET. La clase HttpResponse ofrece un método que sirve precisamente para eso: RemoveOutputCacheItem.

El único parámetro que necesita este método es la ruta absoluta virtual (es decir, empezando por "/") de la página cuya caché queremos liberar. Así, por ejemlo, para liberar la caché de la página actual haríamos lo siguiente:

HttpResponse.RemoveOutputCacheItem(Request.CurrentExecutionFilePath)

Esto en teoría, claro, porque lo primero que hará la mayoría es correar a una página de pruebas, habilitar la caché y poner un botón que haga lo de la línea anterior. El resultado: ¡no le va a funcionar!

El motivo es que, una vez que cacheamos la página completa, al llamarla de nuevo, incluso al pulsar un botón, ésta se saca directamente de la caché y su ciclo de vida normal no se ejecuta, por lo tanto no le funcionarán los eventos. Para conseguirlo con este método es necesario hacer la llamada desde otra página (luego explicaré cómo conseguirlo en la misma página con otro método).

En este archivo (3,95Kb) he incluido una página que, cuando es accedida desde cualquier otra, invalida la caché de ésta primera (en caso de haberla). Así, para eliminar la caché de cualquier página sólo es necesario colocar un enlace a BorraCache.aspx en ella y listo, con este código: 

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        'Obtengo la página desde la que he llegado aquí
        Dim uriAnterior As Uri = Request.UrlReferrer
        If Not uriAnterior Is Nothing Then
            Dim sRuta As String = uriAnterior.AbsolutePath
            HttpResponse.RemoveOutputCacheItem(sRuta)
            lblInfo.Text = "Se ha borrado la caché de la página " + sRuta
        Else
            lblInfo.Text = "Esta página no puede ser llamada directamente. Llámala desde una página cacheada para eliminarla de la caché de salida."
        End If
    End Sub

Obviamente es una prueba de concepto, y en una aplicación real no deberíamos incluirla de esta manera pues podría llamarla cualquiera para eliminar nuestra aplicación, pero sirve para captar la idea y poder usarla, por ejemplo, desde una página de administración protegida.

En el próximo post voy a continuar con este tema y a explicar algo mucho más interesante: Cómo eliminar selectivamente la caché de la página actual.

Imagina esta situación: tienes una página en caché que los usuarios normales pueden ver pero no editar, pero que los administradores puedes cambiar usando los botones apropiados. Si simplemente activas la caché, como hemos visto, ninguno de los eventos normales saltará, así que los administradores tampoco podrán editar nada, ni tampoco se verán los cambios que han hecho hasta que la caché se refresque.

En el próximo post veremos cómo conseguir esto.

José Manuel Alarcón
Banner

Comentarios (4) -

Muy interesante el tema Felicidades.
Cuando sale la otra parte?
Quiero saber como eliminar la cache y volverla a crear; o como ampliar el tiempo de la cache de toda la pagina desde el ultimo acceso, es decir por ejemplo aumentarle cada ultimo acceso otra vez la duracion(Duration="60") al parecer con lo que escribiras en el proximo post podre hacer esto que quiero.
Saludos!

Responder

Pues en cuanto saque un hueco, que espero sea hoy o mañana :-)

Lo de prorrogarlo automáticament eno lo explicaré, pero es muy sencillo: es especificar una "Sliding Expiration", aunque tendrás que hacerlo por código, no en la directiva.

Busca en google:

Output caching "Sliding Expiration"

y verás mucha información.

Saludos

JM

Responder

Hola Jose Manuel.
Estoy con una web que muestra una lista de imágenes. Resulta que cada vez que actualizo una imagen, ésta no se actualiza hasta que refresco la caché (ctrl+F5).
He probado a poner a la src de las imágenes una "version"
<img src="/imagenes/imagen.jpg?v=20" /> (con un new System.Random().Next(0,100)), así me lo realiza correctamente pero no se si es la mejor forma de hacerlo, ya que cuando analizo la web en páginas para ver que cosas están bien y que cosas están mal me indica una que pone: (Remove query strings from static resources), indicándome todos los src de las imagenes de la web con un parámetro.
¿El tema del OutputCache puede servir para que al modificar una imagen la web la detecte como nueva y se descargue la nueva imagen?

Espero haberme explicado bien.

Un saludo y muchas gracias por toda la información que ofreces, se agradece mucho.

Responder

Spain José Manuel Alarcón

Hola Tony,

Lo que describes de añadirle un parámetro y variarlo cada vez que actualices el recurso es algo muy utilizado, y de hecho nosotros mismos en campusMVP lo usamos bastante.
Es normal que los analizadores de código te digan que las quites: precisamente porque sino no se hace caché de las mismas y al ser recursos estáticos que no cambian a menudo quieres que se cacheen, pero si el parámetro es el mismo no se pedirán de nuevo al servidor mientras no cambies dicho parámetro por otro valor. Así también vas versionando fácilmente los archivos estáticos.

También puedes configurar IIS para que cachee estos elementos solamente durante unos días u horas, pero entonces no se actualizarán cuando los cambies sino cuando toque. Además hay otros lugares donde se hace caché que no están bajo tu control, como por ejemplo los caché-proxy de algunas empresas. Con el truco del parámetro conseguirás que funcione también con éstos.

OutputCache no te sirve porque esa es una directiva que se coloca en páginas ASPX y no en contenidos estáticos y está pensada para reutilizar resultados de ejecución de páginas y controles.

Espero haberte ayudado.

Saludos.

Responder

Agregar comentario