Tutorial de ASP.NET
Vista Previa de ASP.NET 2.0

Cacheado por fragmentos de página

Además de poder cachear la salida de una página entera, ASP.NET te proporciona una forma simple de cachear la salida de regiones de contenido de página, a la que se le ha dado el nombre de cacheado por fragmentos. Podemos delimitar áreas de nuestra página mediante un cotnrol de usuario, y marcarlas para que sean cacheadas usando la directiva @OutputCache de la que hemos hablado en la sección anterior. Esta directiva especifica la duración (en segundos) que debe estar cacheado en el servidor el contenido de salida del control de usuario, así como cualquier otra condición opcional por la cual debiera cambiar. Por ejemplo, la siguiente directiva le dice a ASP.NET que meta en la caché de salida al control de usuario durante 120 segundos, y que cambie el caché usando las cadenas de búsqueda "CategoryID" y "SelectedID" o los parámetros de envío del formulario.


  <%@ OutputCache Duration="120" VaryByParam="CategoryID;SelectedID"%>


El atributo VaryByParam es extremadamente potente y permite a los creadores de controles de usuario ordenar a ASP.NET para que almacene en caché múltiples instancias de una región de caché de salida en el servidor. Por ejemplo, las siguientes URLs distinguen entre distintas instancias de contenido del control de usuario del ejemplo anterior.

http://localhost/mypage.aspx?categoryid=foo&selectedid=0
http://localhost/mypage.aspx?categoryid=foo&selectedid=1

Por lo tanto, la lógica dentro de un control de usuario puede generar dinámicamente contenido diferente (que se cachea por separado) dependiendo de los argumentos que reciba. Además de permitir el atributo VaryByParam, el cacheado por fragmentos también permite un atributo VaryByControl. Mientras que el atributo VaryByParam cambia los resultados cacheados basándose en pares nombre-valor enviados mediante POST o GET, el atributo VaryByControl cambia el fragmento cacheado en base a controles dentro del control de usuario. Por ejemplo:

 
<%@ OutputCache Duration="120" VaryByParam="CategoryID;SelectedID"%>



Tened en cuenta que, como con las páginas con caché de salida, se requiere el uso explícito tanto de VaryByParam como de VaryByControl incluso si no se usa ninguno de los dos. Si el control de usuario contiene un control de lista desplegable llamado Categoría podríamos variar los resultados del control de usuario dependiendo del valor seleccionado dentro de la lista desplegable. El siguiente código de ejemplo muestra cómo meter en caché dos sección de menú de una página mediante un control de usuario declarativo.

<%@ Page Language="C#" %>
<%@ Register TagPrefix="Acme" TagName="Menu" Src="Menu.ascx" %>

<html>
<body>
<table>
<tr>
<td>
<Acme:Menu Category="MenuIzquierdo" runat=server/>
</td>
<td>
<h1>Hola, la hora actual es: <%=DateTime.Now%> </h1>
</td>
<td>
<Acme:Menu Category="MenuDerecho" runat=server/>
</td>
<tr>
</table>
</body>
</html>
C#

El siguiente ejemplo demuestra la implementación del control de usuario "Acme:Menu" con soporte para caché.

<%@ Control Language="C#" ClassName="AcmeMenu" %>
<%@ OutputCache Duration="120" VaryByParam="none" %>

<script runat=server>

public String Category;

void Page_Load(Object sender, EventArgs e) {

AdoConnection conn = new AdoConnection("MyDSN");

MyMenu.DataSource = conn.Execute("select * from menu where category=" + Category );
MyMenu.DataBind();
}

</script>

<asp:datagrid id="MyMenu" runat=server/>
C#

Tened en cuenta que este ejemplo mete en la caché de salida la respuesta de cada control de usuario durante un periodo de 120 segundos. Toda la lógica necesaria para recrear cada control de usuario de tipo menú en caso de producirse un fallo en la caché (sea porque han pasado los 120 segundos o porque la memoria en el servidor se ha quedado corta) se ha encapsulado limpiamente dentro del control de usuario.

El siguiente ejemplo demuestra un cacheado de fragmentos simple. El ejemplo cachea la salida de un control que recupera datos desde una base de datos SQL Server, mientras que mantiene las propiedades dinámicas de la página padre. Se puede ver que la página es dinámica porque la hora se actualiza con cada refresco, mientras que el control de usuario sólo se actualiza cada 60 segundos.

Caché por fragmentos en C#


Nota: Cualquier intento de manipular mediante programación un control con la salida cacheada desde su página contenedora dará como resultado un error. Por ejemplo, intentar usar una expresión de enlace de datos declarativa en el control de usuario genera errores de parser, como vemos en el siguiente código.

<!-- Las siguientes etiquetas generan errores de parser -->

<Acme:Menu Categoria='<%# Container.DataItem("Categoria")' runat="server" />


La razón de esto es sencilla. En aquellos casos en los que el contenido de un control de usuario tenga su salida cacheada, se crea una instancia del control sólo en la primera petición que se le hace; de esa manera, una vez en la caché, el control ya no está disponible. En lugar de ello, deberíamos encapsular toda la lógica necesaria para crear el contenido de un control de usuario directamente dentro del mismo control; normalmente dentro de los eventos Page_Load o Page_PreRender del control de usuario.

Se pueden declarar y usar otros parámetros de propiedades declarativas al personalizar el control. Por ejemplo, podríamos personalizar el anterior control de usuario de la siguiente manera:

<Acme:Menu Categoria="MenuIzquierdo" runat="server"/>

<Acme:Menu Categoria="MenuDerecho" runat="server" />

Estas declaraciones hacen que el compilador de la página genere y ejecute el código apropiado en caso de que se haya creado al control como resultado de un fallo de caché. Así, los desarrolladores del control de usuario pueden acceder a estas propiedades tal y como lo harían con un control de usuario no cacheado.

API de cacheado de fragmentos Nuevo en 2.0

Además de usar la directiva @OutputCache, podemos ajustar mediante programación las opciones de caché para controles de usuario usando la CacheAPI. En el siguiente ejemplo, el control cambia el tiempo que permanece en caché basándose en el estado que se seleccione del control de lista desplegable. Puedes ver la hora a la que se dibujó el control y la hora a la que se limpiará la entrada de caché.

API de Caché por Fragmentos en C#