Spesso tornerà utile non copiare in cache l'intera pagina ma una parte di questa.
Per ottenere questo risultato abbiamo due tecniche:
- Fragment caching: Prendiamo i dati che vogliamo copiare in cache e li spostiamo all'interno di uno user control creato appositamente; copiamo in cache solo lo user control creato.
- Post-cache substitution: Identifichiamo il contenuto dinamico che non vogliamo copiare in cache e cambiamo il contenuto con il controllo Substitution.
Il Fragment caching è il più semplice dei due.
Comunque bisogna basarsi sulla quantità dei dati da tenere in cache, per scegliere quale delle due tecniche applicare.
Se abbiamo una piccola parte di dati che vogliamo tenere in cache, allora il Fragment caching tornerà al caso nostro. Se invece abbiamo solamente una piccola parte di contenuto dinamico, il Post-cache substitution è quello che farà per noi.
Implementazione
Fragment caching
Implementare il Fragment caching è alquanto semplice.
Basta creare un user control per la parte di codice che vogliamo copiare in cache.
Aggiungeremo la direttiva:
<%@ OutputCache Duration="20" VaryByParam="None" %>
nell'user control.
Vediamo se tutto realmente funziona.
Creiamo un'user control con questo codice:
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="WebUserControl1.ascx.cs" Inherits="WebApplication1.WebUserControl1" %>
<%@ OutputCache Duration="20" VaryByParam="None" %>
<div>
<asp:Label runat="server" ID="lblDate" />
</div>
protected void Page_Load(object sender, EventArgs e)
{
lblDate.Text = "Tempo:<br/>";
lblDate.Text += DateTime.Now.ToString();
}
E una bella pagina Default.aspx così:
<form id="form1" runat="server">
<div>
<asp:Label runat="server" ID="lblDate" />
</div>
<div>
<uc1:WebUserControl1 ID="WebUserControl11" runat="server" />
</div>
</form>
protected void Page_Load(object sender, EventArgs e)
{
lblDate.Text = "Tempo:<br/>";
lblDate.Text += DateTime.Now.ToString();
}
Proviamo la pagina e, ad ogni refresh, il contenuto dell'user control non verrà aggiornato a differenza della label nella pagina Default.aspx.
Post-cache substitution
Il Post-cache substitution è facile da implementare tanto quanto il Fragment caching.
Quel che cambia è il concetto alla base, è l'inverso del Fragment caching.
L'implementazione seguente è lato markup nella pagina Default.aspx, lo stesso effetto potremmo farlo solamente lato c#:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>
<%@ OutputCache Duration="20" VaryByParam="None" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
Copiato in cache:
<asp:Label ID="lblDate" runat="server" /><br />
Non copiato in cache:
<asp:Substitution ID="Substitution1" runat="server" MethodName="GetDate" />
</form>
</body>
</html>
Mentre lato codice:
protected void Page_Load(object sender, EventArgs e)
{
lblDate.Text = DateTime.Now.ToString() + "<br />";
}
private static string GetDate(HttpContext context)
{
return "<b>" + DateTime.Now.ToString() + "</b>";
}
Il metodo GetDate è statico perchè ASP.NET deve poter chiamare questo metodo anche quando la pagina non ha un'istanza disponibile (questo accade quando viene usata la pagina copiata in cache).
Anche in questo caso, come detto nei post precedenti, la page life cycle della nostra pagina non verrà eseguita. Ciò significa che non verrà creato alcun oggetto e nessun evento sarà lanciato.
Se il contenuto dinamico dipende da qualche valore creato a run-time o da un'altro controllo, allora avremo bisogno di basarci su un'altra tecnica di caching che vedremo nei prossimi post.
|