Utiliser le cache de type DONUT avec asp.net mvc4

 01/01/2019 |   Admin |  C#


Introduction

Pour être simple, le cache Donut est utilisé pour mettre en cache une page entière SAUF une partie de la page. Le nom vient d'ailleurs de la !! le gateau avec le trou !

Avec MVC, le gros avantage c'est que l'on pourra s'affranchir du cache pour certaines vues partielles

Le cas le plus souvent rencontré

En fait j'ai décidé d'écrire cet article, après avoir plusieurs fois rencontré sur des forums, un problème de sécurité concernant la vue partielle _LoginPartial.cshtml

Si vous mettez en place un système d'authentification et que vous utiliser le cache comme dans l'exemple suivant, vous aurez un problème.

public class HomeController : Controller
{
[OutputCache(Duration=3000, Location= System.Web.UI.OutputCacheLocation.Server)]
public ActionResult Index()
{
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
return View();
}
}

Essayez de vous connecter à votre application avec un premier navigateur (ou ordinateur):

Hello + votre nom d'utilisateur s'affiche correctement

Puis, naviguer sur votre application depuis un autre navigateur ou ordinateur sans s'y être connecté:

Problème: la visite précédente a mis en cache certaines informations qui ne doivent pas être affichées à tout le monde. Il s'agit seulement d'un nom d'utilisateur mais imaginons quelque chose comme:

@if (User.IsInRole("Manager"))
{
Prix d'achat: @Model.PrixAchat
}

Ici, si la première mise en cache s'est faite par un utilisateur disposant du droit "Manager", tous les prochains visiteurs verront le prix d'achat affiché sur le site !

Solution

Utiliser le package MvcDonutCaching (Depuis Visual Studio, clique droit sur le projet, nuget packages, MvcDonutCaching)

Ensuite, l'utilisation du cache reste identique, à la seule différence que l'attribut se nomme [DonutOutputCache()]

 

Si on prend comme exemple le cas précédent (Avec le template de base MVC4, internet application), le code du controlleur de la page Index devient:

[DonutOutputCache(Duration = 3000, Location = System.Web.UI.OutputCacheLocation.Server)]
public ActionResult Index()
{
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
return View();
}

On déplace la vue partielle _LoginPartial.cshtml du dossier Shared vers le dossier Account

Puis on ajoute une méthode d'action dans le controlleur "Account" :

[Authorize]
[InitializeSimpleMembership]
public class AccountController : Controller
{
[AllowAnonymous]
public ActionResult _LoginPartial()
       {
              return PartialView();
       }
….
 
….

Enfin, on désactive le cache pour la vue partielle de cette facon:

@Html.Action("_LoginPartial", "Account", true)

true permet d'indiquer que l'on ne veut pas de cache pour cette vue. (MvcDonut ajoute cette propriété automatiquement au HtmlHelper)

Note: l'attribut suivant est utilisé pour cette démo.

[DonutOutputCache(Duration = 3000, Location = System.Web.UI.OutputCacheLocation.Server)

Dans la vraie vie il est préférable d'utiliser le web.config comme suivant:








Puis changer l'attribut:

[DonutOutputCache(CacheProfile="Cache50Minutes")]

L'intéret est que si l'on désire changer la valeur d'un attribut, on pourra le faire a un seul endroit. Demo

En rouge l'on peut voir que la page est en cache, en vert la vue est rechargée à chaque action !

Laisser un commentaire pour toute question sur la cache

Merci