Mise en cache par fragments de la page
Outre la mise en cache de sortie de la totalité d'une page, ASP.NET permet de mettre facilement en cache des parties du contenu d'une page. Ce procédé porte le nom de mise en cache par fragments. Vous devez désigner des parties de votre page au moyen d'un contrôle utilisateur, avant de les marquer pour la mise en cache à l'aide de la directive @ OutputCache présentée à la section précédente. Cette directive spécifie la durée (en secondes) pendant laquelle le contenu de sortie du contrôle utilisateur doit être mis en cache sur le serveur, ainsi que des conditions facultatives qui déterminent sa variation.
Par exemple, la directive suivante commande à ASP.NET de mettre en cache de sortie le contrôle utilisateur pendant 120 secondes et de modifier le cache à l'aide des chaînes de requête « CategoryID » et « SelectedID » ou des paramètres de publication de formulaires.
<%@ OutputCache Duration="120" VaryByParam="CategoryID;SelectedID"%>
L'attribut VaryByParam est extrêmement puissant et permet aux auteurs du contrôle utilisateur de commander à ASP.NET de mettre en cache/enregistrer plusieurs instances d'une partie de cache de sortie sur le serveur. Par exemple, les URL suivantes vers la page hôte du cache de contrôle utilisateur précédent séparent les instances du contenu du contrôle utilisateur.
http://localhost/mypage.aspx?categoryid=foo&selectedid=0 http://localhost/mypage.aspx?categoryid=foo&selectedid=1
La logique d'un contrôle utilisateur peut donc générer dynamiquement un contenu différent (mis en cache séparément) selon les arguments fournis.
Outre l'attribut VaryByParam, la mise en cache par fragments prend également en charge l'attribut VaryByControl. Alors que l'attribut VaryByParam modifie les résultats mis en cache de fonction de paires nom/valeur envoyées à l'aide de POST ou de GET, l'attribut VaryByControl modifie des fragments mis en cache par des contrôles au sein du contrôle utilisateur. Par exemple :
<%@ OutputCache Duration="120" VaryByParam="none" VaryByControl="Category" %>
Remarquez qu'à l'instar des pages mises en cache de sortie, l'utilisation explicite de VaryByParam est obligatoire, même si cet attribut n'est pas utilisé.
Si le contrôle utilisateur contenait un contrôle de zone de liste déroulante appelé Category, la sortie du contrôle utilisateur varierait selon la valeur sélectionnée dans ce contrôle.
Comme il est possible d'imbriquer des contrôles utilisateur de manière récursive au sein d'une page (c'est-à-dire un contrôle utilisateur déclaré dans un autre contrôle serveur), vous pouvez également imbriquer des contrôles utilisateur mis en cache en sortie de manière récursive. Vous obtenez ainsi un puissant modèle de composition permettant aux parties mises en cache de comprendre d'autres sous-parties mises en cache.
L'exemple de code suivant illustre la mise en cache de deux sections de menu d'une page à l'aide d'un contrôle utilisateur déclaratif.
<%@ Register TagPrefix="Acme" TagName="Menu" Src="Menu.ascx" %>
<html>
<body>
<table>
<tr>
<td>
<Acme:Menu Category="LeftMenu" runat=server/>
</td>
<td>
<h1>Hi, the time is now: <%=DateTime.Now%> </h1>
</td>
<td>
<Acme:Menu Category="RightMenu" runat=server/>
</td>
<tr>
</table>
</body>
</html>
<%@ Register TagPrefix="Acme" TagName="Menu" Src="Menu.ascx" %>
<html>
<body>
<table>
<tr>
<td>
<Acme:Menu Category="LeftMenu" runat=server/>
</td>
<td>
<h1>Hi, the time is now: <%=Now%> </h1>
</td>
<td>
<Acme:Menu Category="RightMenu" runat=server/>
</td>
<tr>
</table>
</body>
</html>
<%@ Register TagPrefix="Acme" TagName="Menu" Src="Menu.ascx" %>
<html>
<body>
<table>
<tr>
<td>
<Acme:Menu Category="LeftMenu" runat=server/>
</td>
<td>
<h1>Hi, the time is now: <%=DateTime.Now%> </h1>
</td>
<td>
<Acme:Menu Category="RightMenu" runat=server/>
</td>
<tr>
</table>
</body>
</html>
|
|
C#
|
VB
|
JScript
|
|
L'exemple de code suivant illustre l'implémentation du contrôle utilisateur "Acme:Menu" avec prise en charge du cache.
<%@ OutputCache Duration="120" VaryByParam="none" %>
<script language="C#" 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/>
<%@ OutputCache Duration="120" VaryByParam="none" %>
<script language="VB" runat=server>
Public Category As String;
Sub Page_Load(sender As Object, e As EventArgs)
Dim conn As AdoConnection = New AdoConnection("MyDSN")
MyMenu.DataSource = conn.Execute("select * from menu where category=" & Category)
MyMenu.DataBind()
End Sub
</script>
<asp:datagrid id="MyMenu" runat=server/>
<%@ OutputCache Duration="120" VaryByParam="none" %>
<script language="JScript" runat=server>
public var Category:String;
function Page_Load(sender:Object, e:EventArgs) : void {
var conn:AdoConnection = new AdoConnection("MyDSN");
MyMenu.DataSource = conn.Execute("select * from menu where category=" + Category );
MyMenu.DataBind();
}
</script>
<asp:datagrid id="MyMenu" runat=server/>
|
|
C#
|
VB
|
JScript
|
|
Remarquez que cet exemple met en cache de sortie la réponse de chaque contrôle utilisateur pendant une période de 120 secondes. Toute la logique nécessaire pour recréer chaque contrôle utilisateur de menu en cas d'accès au cache sans résultat (soit parce que 120 secondes se sont écoulées, soit à cause de la saturation de la mémoire sur le serveur) est encapsulée proprement au sein du contrôle utilisateur.
L'exemple suivant illustre une mise en cache par fragments simple. L'exemple met en cache la sortie d'un contrôle qui extrait des données à partir d'une base de données SQL Server, tout en conservant les propriétés dynamiques de la page parente. Vous pouvez constater que la page est dynamique, car l'heure est mise à jour à chaque actualisation alors que le contrôle n'est mis à jour que toutes les 60 secondes.
Inconvénients
Remarque : Toute tentative de manipulation par programme d'un contrôle mis en cache de sortie à partir de sa page contenante entraîne une erreur. Par exemple, les tentatives d'utilisation d'une expression de liaison de données déclarative sur la balise du contrôle utilisateur génèrent des erreurs d'analyse, comme indiqué dans le code suivant.
<!-- The following tags generate parser errors. -->
<Acme:Menu Category='<%# Container.DataItem("Category")' runat="server"/>
La raison de ce phénomène est simple. Si le contenu d'un contrôle utilisateur est mis en cache de sortie, une instance du contrôle n'est créée que lors de la première demande. Par conséquent, une fois mis en cache, le contrôle n'est plus disponible. Il est plutôt conseillé d'encapsuler toute la logique nécessaire à la création du contenu d'un contrôle utilisateur directement au sein du contrôle. Cette opération s'effectue généralement dans l'événement Page_Load ou Page_PreRender du contrôle utilisateur.
Vous pouvez déclarer et utiliser d'autres paramètres de propriétés déclaratifs pour personnaliser le contrôle. Par exemple, le contrôle utilisateur ci-dessus peut être personnalisé de la manière suivante :
<Acme:Menu Category="LeftMenu" runat=server/>
<Acme:Menu Category="RightMenu" runat=server/>
Ces déclarations entraînent la génération du code approprié et son exécution par le compilateur de page si le contrôle est créé suite à un accè au cache sans résultat. Les développeurs de contrôles utilisateur peuvent accéder à ces paramètres comme s'il s'agissait d'un contrôle utilisateur non mis en cache.
Résumé de la section
- Outre la mise en cache de sortie de la totalité d'une page, ASP.NET permet de mettre facilement en cache des parties du contenu d'une page. Ce procédé porte le nom de mise en cache par fragments.
- Vous devez désigner des parties de votre page au moyen d'un contrôle utilisateur, avant de les marquer pour la mise en cache à l'aide de la directive @ OutputCache présentée à la section précédente.
- Comme il est possible d'imbriquer des contrôles utilisateur de manière récursive au sein d'une page (c'est-à-dire un contrôle utilisateur déclaré dans un autre contrôle serveur), vous pouvez également imbriquer des contrôles utilisateur mis en cache en sortie de manière récursive.
- Toute tentative de manipulation par programme d'un contrôle mis en cache de sortie à partir de sa page contenante entraîne une erreur. Il est plutôt conseillé d'encapsuler toute la logique nécessaire à la création du contenu d'un contrôle utilisateur directement au sein du contrôle, généralement dans l'événement Page_Load ou Page_PreRender du contrôle utilisateur.
- Il est possible de déclarer et d'utiliser d'autres paramètres de propriétés déclaratifs pour personnaliser le contrôle.
|