Amélioration des performances avec la mise en cache de la sortie (C#)
par Microsoft
Dans ce tutoriel, vous allez découvrir comment améliorer considérablement les performances de vos applications web ASP.NET MVC en tirant parti de la mise en cache de sortie. Vous apprenez à mettre en cache le résultat retourné par une action de contrôleur afin que le même contenu n’ait pas besoin d’être créé chaque fois qu’un nouvel utilisateur appelle l’action.
L’objectif de ce tutoriel est d’expliquer comment vous pouvez améliorer considérablement les performances d’une application MVC ASP.NET en tirant parti du cache de sortie. Le cache de sortie vous permet de mettre en cache le contenu retourné par une action de contrôleur. Ainsi, le même contenu n’a pas besoin d’être généré chaque fois que la même action de contrôleur est appelée.
Imaginez, par exemple, que votre application MVC ASP.NET affiche une liste d’enregistrements de base de données dans une vue nommée Index. Normalement, chaque fois qu’un utilisateur appelle l’action du contrôleur qui retourne la vue Index, l’ensemble d’enregistrements de base de données doit être récupéré à partir de la base de données en exécutant une requête de base de données.
Si, en revanche, vous tirez parti du cache de sortie, vous pouvez éviter d’exécuter une requête de base de données chaque fois qu’un utilisateur appelle la même action de contrôleur. La vue peut être récupérée à partir du cache au lieu d’être régénérée à partir de l’action du contrôleur. La mise en cache vous permet d’éviter d’effectuer un travail redondant sur le serveur.
Activation de la mise en cache de sortie
Vous activez la mise en cache de sortie en ajoutant un attribut [OutputCache] à une action de contrôleur individuelle ou à une classe de contrôleur entière. Par exemple, le contrôleur de la liste 1 expose une action nommée Index(). La sortie de l’action Index() est mise en cache pendant 10 secondes.
Listing 1 – Controllers\HomeController.cs
using System.Web.Mvc;
namespace MvcApplication1.Controllers
{
[HandleError]
public class HomeController : Controller
{
[OutputCache(Duration=10, VaryByParam="none")]
public ActionResult Index()
{
return View();
}
}
}
Dans les versions bêta de ASP.NET MVC, la mise en cache de sortie ne fonctionne pas pour une URL telle que http://www.MySite.com/
. Au lieu de cela, vous devez entrer une URL telle que http://www.MySite.com/Home/Index
.
Dans La liste 1, la sortie de l’action Index() est mise en cache pendant 10 secondes. Si vous préférez, vous pouvez spécifier une durée de cache beaucoup plus longue. Par exemple, si vous souhaitez mettre en cache la sortie d’une action de contrôleur pendant un jour, vous pouvez spécifier une durée de cache de 86400 secondes (60 secondes * 60 minutes * 24 heures).
Rien ne garantit que le contenu sera mis en cache pendant la durée spécifiée. Lorsque les ressources de mémoire deviennent faibles, le cache commence à supprimer automatiquement le contenu.
Le contrôleur d’accueil de la liste 1 retourne la vue Index dans la liste 2. Il n’y a rien de spécial dans cette vue. La vue Index affiche simplement l’heure actuelle (voir figure 1).
Liste 2 – Views\Home\Index.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Home.Index" %>
<!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>
The current time is: <%= DateTime.Now.ToString("T") %>
</div>
</body>
</html>
Figure 1 – Affichage Index mis en cache
Si vous appelez l’action Index() plusieurs fois en entrant l’URL /Accueil/Index dans la barre d’adresse de votre navigateur et en appuyant plusieurs fois sur le bouton Actualiser/recharger dans votre navigateur, l’heure affichée par la vue Index ne changera pas pendant 10 secondes. La même heure s’affiche, car la vue est mise en cache.
Il est important de comprendre que la même vue est mise en cache pour tous ceux qui visitent votre application. Toute personne appelant l’action Index() obtient la même version mise en cache de la vue Index. Cela signifie que la quantité de travail que le serveur web doit effectuer pour servir la vue Index est considérablement réduite.
La vue dans la liste 2 se trouve faire quelque chose de vraiment simple. La vue affiche simplement l’heure actuelle. Toutefois, vous pouvez tout aussi facilement mettre en cache une vue qui affiche un ensemble d’enregistrements de base de données. Dans ce cas, le jeu d’enregistrements de base de données n’a pas besoin d’être récupéré à partir de la base de données chaque fois que l’action du contrôleur qui retourne la vue est appelée. La mise en cache peut réduire la quantité de travail que votre serveur web et votre serveur de base de données doivent effectuer.
N’utilisez pas la directive %@ OutputCache %> de page <dans une vue MVC. Cette directive est en cours de Web Forms monde et ne doit pas être utilisée dans une application MVC ASP.NET.
Emplacement où le contenu est mis en cache
Par défaut, lorsque vous utilisez l’attribut [OutputCache], le contenu est mis en cache à trois emplacements : le serveur web, les serveurs proxy et le navigateur web. Vous pouvez contrôler exactement où le contenu est mis en cache en modifiant la propriété Location de l’attribut [OutputCache].
Vous pouvez définir la propriété Location sur l’une des valeurs suivantes :
· Tout
· Client
· Aval
· Serveur
· Aucun
· ServerAndClient
Par défaut, la propriété Location a la valeur Any. Toutefois, il existe des situations dans lesquelles vous pouvez souhaiter mettre en cache uniquement sur le navigateur ou uniquement sur le serveur. Par exemple, si vous mettez en cache des informations personnalisées pour chaque utilisateur, vous ne devez pas mettre en cache les informations sur le serveur. Si vous affichez des informations différentes pour différents utilisateurs, vous devez mettre en cache les informations uniquement sur le client.
Par exemple, le contrôleur de la liste 3 expose une action nommée GetName() qui retourne le nom d’utilisateur actuel. Si Jack se connecte au site web et appelle l’action GetName(), l’action retourne la chaîne « Hi Jack ». Si, par la suite, Jill se connecte au site web et appelle l’action GetName(), elle obtient également la chaîne « Hi Jack ». La chaîne est mise en cache sur le serveur web pour tous les utilisateurs après que Jack a initialement appelé l’action du contrôleur.
Listing 3 – Controllers\BadUserController.cs
using System.Web.Mvc;
using System.Web.UI;
namespace MvcApplication1.Controllers
{
public class BadUserController : Controller
{
[OutputCache(Duration = 3600, VaryByParam = "none")]
public string GetName()
{
return "Hi " + User.Identity.Name;
}
}
}
Très probablement, le contrôleur de la liste 3 ne fonctionne pas comme vous le souhaitez. Vous ne voulez pas afficher le message « Salut Jack » à Jill.
Vous ne devez jamais mettre en cache du contenu personnalisé dans le cache du serveur. Toutefois, vous pouvez mettre en cache le contenu personnalisé dans le cache du navigateur pour améliorer les performances. Si vous mettez en cache du contenu dans le navigateur et qu’un utilisateur appelle la même action de contrôleur plusieurs fois, le contenu peut être récupéré à partir du cache du navigateur au lieu du serveur.
Le contrôleur modifié dans Listing 4 met en cache la sortie de l’action GetName(). Toutefois, le contenu est mis en cache uniquement sur le navigateur et non sur le serveur. Ainsi, lorsque plusieurs utilisateurs appellent la méthode GetName(), chaque personne obtient son propre nom d’utilisateur et non le nom d’utilisateur d’une autre personne.
Listing 4 – Controllers\UserController.cs
using System.Web.Mvc;
using System.Web.UI;
namespace MvcApplication1.Controllers
{
public class UserController : Controller
{
[OutputCache(Duration=3600, VaryByParam="none", Location=OutputCacheLocation.Client, NoStore=true)]
public string GetName()
{
return "Hi " + User.Identity.Name;
}
}
}
Notez que l’attribut [OutputCache] dans listing 4 inclut une propriété Location définie sur la valeur OutputCacheLocation.Client. L’attribut [OutputCache] inclut également une propriété NoStore. La propriété NoStore est utilisée pour informer les serveurs proxy et le navigateur qu’ils ne doivent pas stocker une copie permanente du contenu mis en cache.
Variation du cache de sortie
Dans certains cas, vous pouvez souhaiter différentes versions mises en cache du même contenu. Imaginez, par exemple, que vous créez une page master/détail. La page master affiche une liste de titres de films. Lorsque vous cliquez sur un titre, vous obtenez les détails du film sélectionné.
Si vous mettez en cache la page de détails, les détails du même film s’affichent, quel que soit le film sur lequel vous cliquez. Le premier film sélectionné par le premier utilisateur sera affiché à tous les futurs utilisateurs.
Vous pouvez résoudre ce problème en tirant parti de la propriété VaryByParam de l’attribut [OutputCache]. Cette propriété vous permet de créer différentes versions mises en cache du même contenu lorsqu’un paramètre de formulaire ou un paramètre de chaîne de requête varie.
Par exemple, le contrôleur de la liste 5 expose deux actions nommées Master() et Details(). L’action Master() retourne une liste de titres de film et l’action Détails() retourne les détails du film sélectionné.
Listing 5 – Controllers\MoviesController.cs
using System.Linq;
using System.Web.Mvc;
using MvcApplication1.Models;
namespace MvcApplication1.Controllers
{
public class MoviesController : Controller
{
private MovieDataContext _dataContext;
public MoviesController()
{
_dataContext = new MovieDataContext();
}
[OutputCache(Duration=int.MaxValue, VaryByParam="none")]
public ActionResult Master()
{
ViewData.Model = (from m in _dataContext.Movies
select m).ToList();
return View();
}
[OutputCache(Duration = int.MaxValue, VaryByParam = "id")]
public ActionResult Details(int id)
{
ViewData.Model = _dataContext.Movies.SingleOrDefault(m => m.Id == id);
return View();
}
}
}
L’action Master() inclut une propriété VaryByParam avec la valeur « none ». Lorsque l’action Master() est appelée, la même version mise en cache de la vue maître est retournée. Tous les paramètres de formulaire ou de chaîne de requête sont ignorés (voir figure 2).
Figure 2 : affichage /Movies/Master
Figure 3 : affichage /Movies/Details
L’action Détails() inclut une propriété VaryByParam avec la valeur « Id ». Lorsque des valeurs différentes du paramètre Id sont passées à l’action du contrôleur, différentes versions mises en cache de la vue Détails sont générées.
Il est important de comprendre que l’utilisation de la propriété VaryByParam entraîne plus de mise en cache et pas moins. Une version mise en cache différente de la vue Détails est créée pour chaque version différente du paramètre Id.
Vous pouvez définir la propriété VaryByParam sur les valeurs suivantes :
* = Créez une version mise en cache différente chaque fois qu’un paramètre de chaîne de formulaire ou de requête varie.
none = Ne jamais créer d’autres versions mises en cache
Liste de paramètres de points-virgules = Créer différentes versions mises en cache chaque fois que l’un des paramètres de formulaire ou de chaîne de requête dans la liste varie
Création d’un profil de cache
Au lieu de configurer les propriétés du cache de sortie en modifiant les propriétés de l’attribut [OutputCache], vous pouvez créer un profil de cache dans le fichier de configuration web (web.config). La création d’un profil de cache dans le fichier de configuration web offre deux avantages importants.
Tout d’abord, en configurant la mise en cache de sortie dans le fichier de configuration web, vous pouvez contrôler la façon dont les actions du contrôleur mettez en cache le contenu dans un emplacement central. Vous pouvez créer un profil de cache et l’appliquer à plusieurs contrôleurs ou actions de contrôleur.
Ensuite, vous pouvez modifier le fichier de configuration web sans recompiler votre application. Si vous devez désactiver la mise en cache pour une application qui a déjà été déployée en production, vous pouvez simplement modifier les profils de cache définis dans le fichier de configuration web. Toutes les modifications apportées au fichier de configuration web sont détectées automatiquement et appliquées.
Par exemple, la <section configuration web de> mise en cache dans la liste 6 définit un profil de cache nommé Cache1Hour. La <section de mise> en cache doit apparaître dans la <section system.web> d’un fichier de configuration web.
Listing 6 – Section Mise en cache pour web.config
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="Cache1Hour" duration="3600" varyByParam="none"/>
</outputCacheProfiles>
</outputCacheSettings>
</caching>
Le contrôleur de la liste 7 illustre comment appliquer le profil Cache1Hour à une action de contrôleur avec l’attribut [OutputCache].
Listing 7 – Controllers\ProfileController.cs
using System;
using System.Web.Mvc;
namespace MvcApplication1.Controllers
{
public class ProfileController : Controller
{
[OutputCache(CacheProfile="Cache1Hour")]
public string Index()
{
return DateTime.Now.ToString("T");
}
}
}
Si vous appelez l’action Index() exposée par le contrôleur dans la liste 7, la même heure est retournée pendant 1 heure.
Résumé
La mise en cache de sortie vous offre une méthode très simple pour améliorer considérablement les performances de vos applications ASP.NET MVC. Dans ce tutoriel, vous avez appris à utiliser l’attribut [OutputCache] pour mettre en cache la sortie des actions du contrôleur. Vous avez également appris à modifier les propriétés de l’attribut [OutputCache], telles que les propriétés Duration et VaryByParam pour modifier la façon dont le contenu est mis en cache. Enfin, vous avez appris à définir des profils de cache dans le fichier de configuration web.