Traduction▲
Cet article est la traduction la plus fidèle possible de l'article original : Adding Dynamic Content to a Cached Page
Introduction▲
En utilisant le cache de sortie (output caching), vous pouvez radicalement améliorer les performances d'une application Asp.Net MVC. Au lieu de générer de nouveau une page à chaque fois qu'elle est appelée, la page peut être générée et mise en cache en mémoire pour plusieurs utilisateurs.
Mais il y a un problème. Comment cela se passe-t-il si vous devez afficher du contenu dynamique dans la page? Par exemple, imaginons que vous vouliez afficher une bannière de publicité dans la page. Vous ne voulez pas que la bannière soit mise en cache et que chaque utilisateur voie la même publicité. Vous ne gagneriez pas d'argent de cette façon!
Heureusement, il existe une solution simple. Vous pouvez utiliser une fonctionnalité du framework ASP.Net qui se nomme la substitution post-cache. Cette fonctionnalité vous permet de remplacer du contenu dynamique dans une page qui a été mise en cache en mémoire.
Normalement, quand vous affichez une page mise en cache en utilisant l'attribut [OutputCache], la page est mise en cache à la fois sur le serveur et sur le client (navigateur Web). Lorsque vous utilisez la substitution post-cache, la page est mise en cache uniquement sur le serveur.
Utilisation de la substitution Post-Cache▲
Utiliser la substitution post-cache requiert deux étapes. Tout d'abord, vous devez définir une méthode qui retourne une chaine de caractères représentant le contenu dynamique que vous voulez insérer dans la page en cache. Ensuite, vous appelez la méthode HttpResponse.WriteSubstitution() pour injecter le contenu dynamique dans la page.
Imaginez, par exemple, que vous voulez afficher aléatoirement différents nouveaux éléments dans une page en cache. La classe News dans le code suivant expose une unique méthode RenderNews() qui retourne aléatoirement un élément de type News, depuis une collection de trois News.
using
System;
using
System.
Collections.
Generic;
using
System.
Web;
namespace
MvcApplication1.
Models
{
public
class
News
{
public
static
string
RenderNews
(
HttpContext context)
{
var
news =
new
List<
string
>
{
"Gas prices go up!"
,
"Life discovered on Mars!"
,
"Moon disappears!"
};
var
rnd =
new
Random
(
);
return
news[
rnd.
Next
(
news.
Count)];
}
}
}
Comme nous l'avons vu, il faut ensuite appeler la méthode HttpResponse.WriteSubstitution(). La méthode WriteSubstitution() définit le code pour remplacer une région de la page en cache par du contenu dynamique. La méthode WriteSubstitution() est utilisée pour afficher les news aléatoires dans la vue.
<%
@ Page Language=
"C#"
AutoEventWireup=
"true"
CodeBehind=
"Index.aspx.cs"
Inherits=
"MvcApplication1.Views.Home.Index"
%>
<%
@ Import Namespace=
"MvcApplication1.Models"
%>
<!
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>
Index</
title>
</
head>
<
body>
<
div>
<%
Response.
WriteSubstitution
(
News.
RenderNews);
%>
<
hr />
The content of this
page is
output cached.
<%=
DateTime.
Now %>
</
div>
</
body>
</
html>
La méthode RenderNews est passée à la méthode WriteSubstitution(). Notez que la méthode RenderNews n'est pas appelée (il n'y a pas de parenthèses). A la place, une référence vers la méthode est passée à WriteSubstitution().
La vue Index est mise en cache. La vue est retournée par le contrôleur (voir code suivant) Notez que l'action Index() est décorée avec l'attribut [OutputCache] qui a pour conséquence de mettre en cache la vue Index pendant 60 secondes.
using
System.
Web.
Mvc;
namespace
MvcApplication1.
Controllers
{
[HandleError]
public
class
HomeController :
Controller
{
[OutputCache(Duration=
60
, VaryByParam=
"none"
)]
public
ActionResult Index
(
)
{
return
View
(
);
}
}
}
Même si la vue est mise en cache, différents news sont affichés lorsque vous appelez la page Index. Lorsque vous appelez cette page, l'heure affichée par la page ne change pas pendant 60 secondes. Le fait que l'heure ne change pas prouve que la page est mise en cache. Pourtant, le contenu injecté par la méthode WriteSubstitution() – la news aléatoire – change à chaque requête.
Utiliser la substitution Post-Cache dans des méthodes Helpers▲
Une manière plus facile d'utiliser la substitution post-cache est d'encapsuler l'appel dans la méthode WriteSubstitution() dans un helper de méthode personnalisé. Cette approche est illustrée par le code suivant.
using
System;
using
System.
Collections.
Generic;
using
System.
Web;
using
System.
Web.
Mvc;
namespace
MvcApplication1.
Helpers
{
public
static
class
AdHelper
{
public
static
void
RenderBanner
(
this
HtmlHelper helper)
{
var
context =
helper.
ViewContext.
HttpContext;
context.
Response.
WriteSubstitution
(
RenderBannerInternal);
}
private
static
string
RenderBannerInternal
(
HttpContext context)
{
var
ads =
new
List<
string
>
{
"/ads/banner1.gif"
,
"/ads/banner2.gif"
,
"/ads/banner3.gif"
};
var
rnd =
new
Random
(
);
var
ad =
ads[
rnd.
Next
(
ads.
Count)];
return
String.
Format
(
"<img src='{0}' />"
,
ad);
}
}
}
Le code précédent contient une classe statique qui expose deux méthodes: RenderBanner() et RenderBannerInternal(). La méthode RenderBanner() représente le helper actuel. La méthode étend la classe HtmlHelper de base du framework Asp.Net MVC ainsi vous pouvez appeler Html.RenderBanner() dans une vue comme n'importe quel autre méthode helper.
La méthode RenderBanner() appelle la méthode HttpResponse.WriteSubstitution() passant la méthode RenderBannerInternal() à la méthode WriteSubsitution().
La méthode RenderBannerInternal() est une méthode privée. Cette méthode ne sera pas exposée en tant que helper. La méthode RenderBannerInternal() retourne aléatoirement une image de bannière de publicité depuis une liste de bannières disponibles.
La vue Index modifiée (voir code suivant) illustre comment vous pouvez utiliser le helper RenderBanner(). Notez qu'une directive additionnelle <%@ Import %> est incluse au début de la vue pour importer l'espace de noms MvcApplication1.Helpers. Si vous négligez l'import de cet espace de noms, alors la méthode RenderBanner() n'apparaitra par en tant que méthode dans la propriété HTML.
<%
@ Page Language=
"C#"
AutoEventWireup=
"true"
CodeBehind=
"Index.aspx.cs"
Inherits=
"MvcApplication1.Views.Home.Index"
%>
<%
@ Import Namespace=
"MvcApplication1.Models"
%>
<%
@ Import Namespace=
"MvcApplication1.Helpers"
%>
<!
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>
Index</
title>
</
head>
<
body>
<
div>
<%
Response.
WriteSubstitution
(
News.
RenderNews);
%>
<
hr />
<%
Html.
RenderBanner
(
);
%>
<
hr />
The content of this
page is
output cached.
<%=
DateTime.
Now %>
</
div>
</
body>
</
html>
Lorsque vous appelez la page rendue par la vue (code précédent), une bannière différente est affichée à chaque requête. La page est mise en cache, mais la bannière de publicité est injectée dynamiquement par le helper RenderBanner().
Conclusion▲
Ce tutoriel a expliqué comment vous pouvez mettre à jour dynamiquement du contenu dans une page mise en cache. Vous avez appris comment utiliser la méthode HttpResponse.WriteSubstitution() pour autoriser du contenu dynamique à être injecté dans une page "cachée". Vous avez aussi appris comment encapsuler l'appel à la méthode WriteSubstitution() à l'intérieur d'une méthode HTML helper.
Utilisez le caching dès que possible, cela peut avoir un impact important sur les performances de vos applications Web. Comme expliqué dans ce tutoriel, vous pouvez utiliser le caching même sur des pages contenant du contenu dynamique.
Remerciements▲
Merci à dourou05 pour les corrections apportées à l'article.