Désactiver le cache du navigateur pour l'ensemble du site Web ASP.NET

199

Je recherche une méthode pour désactiver le cache du navigateur pour un site Web ASP.NET MVC complet

J'ai trouvé la méthode suivante:

Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
Response.Cache.SetNoStore();

Et aussi une méthode meta tag (cela ne fonctionnera pas pour moi, car certaines actions MVC envoient du HTML / JSON partiel via Ajax, sans head, meta tag).

<meta http-equiv="PRAGMA" content="NO-CACHE">

Mais je cherche une méthode simple pour désactiver le cache du navigateur pour un site Web entier.

Palani
la source

Réponses:

92
HttpContext.Current.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
HttpContext.Current.Response.Cache.SetValidUntilExpires(false);
HttpContext.Current.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Response.Cache.SetNoStore();

Toutes les demandes sont d'abord acheminées via default.aspx - donc en supposant que vous pouvez simplement insérer du code derrière.

Squiggs.
la source
17
Je le mettrais dans Global.asax.cs dans Application_BeginRequest (). Je ne fais pas confiance à cette chose default.aspx ... Une autre question: cela a-t-il priorité sur les attributs [OutputCache]?
chris166
5
J'aime l'idée de simplement créer un filtre d'action global et de mettre ces choses de cette façon. Nie la nécessité de se soucier de Default.aspx et Global.asax.
Keith Adler
13
Mettre cela dans Application_BeingRequest peut provoquer certains problèmes. Si vos images sont acheminées via le runtime .net (ce qui peut se produire si vous utilisez un mappage générique pour de belles URL), aucune image ne sera mise en cache sur le navigateur. Cela peut VRAIMENT ralentir les temps de chargement de votre page car chaque demande de page téléchargera à nouveau toutes les images.
herbrandson
4
L'utilisation de quoi que ce soit par programmation remplacera toujours tout attribut déclaré. En d'autres termes, l'utilisation du code OP remplacera tout attribut [OutputCache] déclaré.
Dave Black
Avez-vous des idées sur la façon de tester le tabac et de vérifier que la désactivation du cache fonctionne réellement?
paaone
366

Créez une classe qui hérite de IActionFilter.

public class NoCacheAttribute : ActionFilterAttribute
{  
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
        filterContext.HttpContext.Response.Cache.SetValidUntilExpires(false);
        filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
        filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        filterContext.HttpContext.Response.Cache.SetNoStore();

        base.OnResultExecuting(filterContext);
    }
}

Mettez ensuite les attributs là où vous en avez besoin ...

[NoCache]
[HandleError]
public class AccountController : Controller
{
    [NoCache]
    [Authorize]
    public ActionResult ChangePassword()
    {
        return View();
    }
}
JKG
la source
19
Plutôt que HttpContext.Current.Response, vous devriez probablement utiliser filterContext.HttpContext.Response puisque HttpContext.Current renvoie l'objet HttpContext pré-MVC et le filtreContext.HttpContext renvoie la HttpContextBase post-MVC. Il augmente la testabilité et la cohérence.
mkedobbs
5
IActionFilter est déjà implémenté sur ActionFilterAttribute, vous n'avez donc pas besoin de le répéter.
Andrew Davey
104
Dans les versions actuelles d'ASP.NET MVC, vous pouvez simplement utiliser OutputCacheAttribute pour empêcher la mise en cache: [OutputCache (NoStore = true, Duration = 0, VaryByParam = "None")]
Ashley Tate
9
Je voudrais souligner que je viens de passer plusieurs jours à utiliser chaque solution "mettez cela dans votre code pour arrêter la mise en cache" sous le soleil pour ASP.NET MVC, y compris la réponse acceptée à cette question, en vain. Cette réponse - l'attribut - a fonctionné. + 1M de représentant si je pouvais ...
Tom Kidd
5
Vous voudrez peut-être ajouter if (filterContext.IsChildAction) return;en haut - cela empêchera l'action extérieure d'être «non mise en cache» si elle appelle une action enfant décorée avec un NoCacheattribut. En d'autres termes, l' NoCacheattribut ne fuit pas vers d'autres actions s'il exécute des actions enfants. En outre, le nom de classe doit être NoCacheAttributeconforme à la convention de dénomination généralement acceptée pour les attributs.
Jakub Konecki
132

Au lieu de lancer le vôtre, utilisez simplement ce qui vous est fourni.

Comme mentionné précédemment, ne désactivez pas la mise en cache pour tout. Par exemple, les scripts jQuery largement utilisés dans ASP.NET MVC doivent être mis en cache. En fait, idéalement, vous devriez utiliser un CDN pour ceux-ci de toute façon, mais mon point est que certains contenus doivent être mis en cache.

Ce que je trouve fonctionne mieux ici que d'arroser le [OutputCache] partout, c'est d'utiliser une classe:

[System.Web.Mvc.OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public class NoCacheController  : Controller
{
}

Tous vos contrôleurs pour lesquels vous souhaitez désactiver la mise en cache, puis héritez de ce contrôleur.

Si vous devez remplacer les valeurs par défaut de la classe NoCacheController, spécifiez simplement les paramètres de cache de votre méthode d'action et les paramètres de votre méthode d'action auront la priorité.

[HttpGet]
[OutputCache(NoStore = true, Duration = 60, VaryByParam = "*")]
public ViewResult Index()
{
  ...
}
Adam Tuliper - MSFT
la source
4
@Ozziepeeps, votre commentaire n'est pas correct. Les documents msdn discutent de la mise en cache du navigateur ainsi qu'un test simple montrera que cet attribut modifie l'en-tête de réponse du contrôle du cache en "Cache-Control: public, no-store, max-age = 0" de "Cache-Control: private" sans en utilisant l'attribut.
Adam Tuliper - MSFT
2
également fyi - vous pouvez contrôler les trois emplacements (serveur, proxy, client) avec cet attribut afin de pouvoir absolument contrôler au-delà du cache du serveur. Voir asp.net/mvc/tutorials/… pour quelques détails supplémentaires.
Adam Tuliper - MSFT
1
+1 "Si vous devez remplacer les valeurs par défaut de la classe NoCacheController, spécifiez simplement les paramètres de cache de votre méthode d'action et les paramètres de votre méthode d'action auront la priorité."
Korayem
2
Veuillez noter que si vous utilisez [System.Web.Mvc.OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]au niveau de la classe, vous ne pouvez pas avoir des vues partielles dans votre classe.
Vivian River
1
La méthode OutputCache n'a pas empêché la mise en cache IE lorsque deux conditions étaient réunies: 1) l'action n'a pris aucun paramètre et 2) l'action n'a renvoyé que du texte via Content (someText). Lorsque je renvoie JSON et que je prends un paramètre, la mise en cache IE est correctement désactivée.
Kasey Speakman
10

Vous pouvez désactiver la mise en cache du navigateur pour toutes les pages rendues par les contrôleurs (c'est-à-dire les pages HTML), mais garder la mise en cache en place pour les ressources telles que les scripts, les feuilles de style et les images . Si vous utilisez le regroupement et la minification MVC4 +, vous souhaiterez conserver les durées de cache par défaut pour les scripts et les feuilles de style (très longues durées, car le cache est invalidé en fonction d'une modification d'une URL unique, et non en fonction du temps).

Dans MVC4 +, pour désactiver la mise en cache du navigateur sur tous les contrôleurs, mais le conserver pour tout ce qui n'est pas servi par un contrôleur, ajoutez ceci à FilterConfig.RegisterGlobalFilters:

filters.Add(new DisableCache());

Définissez DisableCachecomme suit:

class DisableCache : ActionFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    }
}
Edward Brey
la source
Malheureusement, cela ne semble pas fonctionner, car appuyer sur le bouton de retour après une déconnexion affiche la page.
ᴍᴀᴛᴛ ʙᴀᴋᴇʀ
6

Je sais que cette réponse n'est pas liée à 100% à la question, mais elle pourrait aider quelqu'un.

Si vous souhaitez désactiver le cache du navigateur pour l' ensemble du site Web ASP.NET MVC , mais que vous ne souhaitez le faire que TEMPORAIREMENT, il est préférable de désactiver le cache dans votre navigateur.

Voici une capture d'écran dans Chrome

Carlos Martinez T
la source
C'est exactement ce que je cherchais ... pendant le développement, si je change un fichier .js, c'est une douleur majeure de le faire passer immédiatement quand j'ai du mal à faire peu de cycles de dépannage / rafraîchissement / test. C'est parfait, merci! Je viens de faciliter la vie de débogage côté client
jleach
2

J'ai implémenté toutes les réponses précédentes et j'avais toujours une vue qui ne fonctionnait pas correctement.

Il s'est avéré que le nom de la vue avec laquelle je rencontrais le problème s'appelait «Récent». Apparemment, cela a confondu le navigateur Internet Explorer.

Après avoir changé le nom de la vue (dans le contrôleur) en un nom différent (j'ai choisi «récent5»), les solutions ci-dessus ont commencé à fonctionner.

DrHooverCraft
la source
0

Vous pouvez essayer le code ci-dessous dans le fichier Global.asax.

protected void Application_BeginRequest()
    {
        Response.Cache.SetCacheability(HttpCacheability.NoCache);
        Response.Cache.SetExpires(DateTime.UtcNow.AddHours(-1));
        Response.Cache.SetNoStore();
    }
NidhinSPradeep
la source
-1

UI

<%@ OutPutCache Location="None"%>
<%
    Response.Buffer = true;
    Response.Expires = -1;
    Response.ExpiresAbsolute = System.DateTime.Now.AddSeconds(-1);
    Response.CacheControl = "no-cache";
%>

Contexte

Context.Response.Cache.SetCacheability(HttpCacheability.NoCache); 
Response.Expires = -1;          
Response.Cache.SetNoStore();
Alpha
la source
1
a besoin de prose explicative, même si elle est techniquement correcte
rmalayter