Ajouter du contenu dynamique à une page mise en cache

Louis-Guillaume MORAND (Traduction)

Apprenez comment mixer du contenu dynamique avec du contenu mis en cache dans une même page. La substitution post-cache vous autorise à afficher du contenu dynamique, comme une bannière de publicité ou des news, à l'intérieur d'une page qui a été mise en cache.

- Titre : Ajouter du contenu dynamique à une page mise en cache

- Auteur : Louis-Guillaume MORAND (Traduction)

- Parution : 1 mai 2009

- Licence : Copyright ® 2009 Equipe dotnet. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- Traduction

- Introduction

- Utilisation de la substitution Post-Cache

- Utiliser la substitution Post-Cache dans des méthodes Helpers

- Conclusion

- Remerciements

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.

Models\News.cs

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.

Views\Home\Index.aspx

<%@ 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.

Controllers\HomeController.cs

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.

Views\Home\Index.aspx (with RenderBanner() method)

<%@ 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.