web-dev-qa-db-fra.com

Empêcher la mise en cache dans ASP.NET MVC pour des actions spécifiques à l'aide d'un attribut

J'ai une application ASP.NET MVC 3. Cette application demande des enregistrements via JQuery. JQuery rappelle une action du contrôleur qui renvoie les résultats au format JSON. Je n'ai pas été en mesure de le prouver, mais je crains que mes données ne soient mises en cache. 

Je veux seulement que la mise en cache soit appliquée à des actions spécifiques, pas à toutes les actions.

Existe-t-il un attribut que je peux appliquer à une action pour garantir que les données ne sont pas mises en cache? Si ce n'est pas le cas, comment puis-je m'assurer que le navigateur reçoit à chaque fois un nouvel ensemble d'enregistrements, au lieu d'un ensemble mis en cache?

177

Pour vous assurer que JQuery ne met pas les résultats en cache, sur vos méthodes ajax, mettez ce qui suit:

$.ajax({
    cache: false
    //rest of your ajax setup
});

Ou pour éviter la mise en cache dans MVC, nous avons créé notre propre attribut, vous pouvez en faire de même. Voici notre code:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed 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);
    }
}

Décorez ensuite votre contrôleur avec [NoCache]. OR pour le faire pour tout ce que vous pourriez simplement mettre l'attribut sur la classe de la classe de base dont vous héritez vos contrôleurs (si vous en avez un) comme nous avons ici:

[NoCache]
public class ControllerBase : Controller, IControllerBase

Vous pouvez également décorer certaines actions avec cet attribut si vous souhaitez qu'elles ne puissent pas être mises en cache, au lieu de décorer tout le contrôleur.

Si votre classe ou action ne comportait pas NoCache lorsqu’elle a été rendue dans votre navigateur et que vous souhaitez vérifier son bon fonctionnement, rappelez-vous qu’après la compilation des modifications, vous devez effectuer une "actualisation complète" (Ctrl + F5) dans votre navigateur. En attendant, votre navigateur conservera l'ancienne version en cache et ne l'actualisera pas avec un "rafraîchissement normal" (F5).

291
mattytommo

Vous pouvez utiliser l'attribut de cache intégré pour empêcher la mise en cache.

Pour le framework .net: [OutputCache(NoStore = true, Duration = 0)]

Pour le noyau .net: [ResponseCache(NoStore = true, Duration = 0)]

Sachez qu'il est impossible de forcer le navigateur à désactiver la mise en cache. Le mieux que vous puissiez faire est de fournir des suggestions que la plupart des navigateurs vont respecter, généralement sous la forme d'en-têtes ou de balises méta. Cet attribut de décorateur désactivera la mise en cache du serveur et ajoutera également cet en-tête: Cache-Control: public, no-store, max-age=0. Il n'ajoute pas de balises méta. Si vous le souhaitez, ceux-ci peuvent être ajoutés manuellement dans la vue.

En outre, JQuery et d’autres infrastructures clientes tenteront de persuader le navigateur de ne pas utiliser la version mise en cache d’une ressource en ajoutant des éléments à l’URL, comme un horodatage ou un GUID. Ceci est efficace pour que le navigateur demande à nouveau la ressource, mais n'empêche pas vraiment la mise en cache.

Sur une note finale. Vous devez savoir que les ressources peuvent également être mises en cache entre le serveur et le client. Les fournisseurs de services Internet, les mandataires et les autres périphériques réseau mettent également en cache les ressources. Ils utilisent souvent des règles internes sans se préoccuper des ressources réelles. Vous ne pouvez pas faire grand chose à ce sujet. La bonne nouvelle est qu'ils mettent généralement en cache des délais plus courts, tels que des secondes ou des minutes.

231
Jaguir

Tout ce dont tu as besoin c'est:

[OutputCache(Duration=0)]
public JsonResult MyAction(

ou, si vous souhaitez le désactiver pour un contrôleur entier:

[OutputCache(Duration=0)]
public class MyController

Malgré le débat dans les commentaires ici, cela suffit pour désactiver la mise en cache du navigateur. ASP.Net émet des en-têtes de réponse indiquant au navigateur que le document expire immédiatement:

OutputCache Duration=0 Response Headers: max-age=0, s-maxage=0

47
Chris Moschini

Dans l'action du contrôleur, ajoutez à l'en-tête les lignes suivantes

    public ActionResult Create(string PositionID)
    {
        Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
        Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0.
        Response.AppendHeader("Expires", "0"); // Proxies.
13
dfortun

Voici l'attribut NoCache proposé par mattytommo, simplifié en utilisant les informations de la réponse de Chris Moschini:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class NoCacheAttribute : OutputCacheAttribute
{
    public NoCacheAttribute()
    {
        this.Duration = 0;
    }
}
5
Konamiman

Pour MVC6 (DNX), il n'y a pas de System.Web.OutputCacheAttribute

Remarque: lorsque vous définissez NoStore, le paramètre Durée n'est pas pris en compte. Il est possible de définir une durée initiale pour le premier enregistrement et de la remplacer par des attributs personnalisés.

Mais nous avons Microsoft.AspNet.Mvc.Filters.ResponseCacheFilter

 public void ConfigureServices(IServiceCollection services)
        ...
        services.AddMvc(config=>
        {
            config.Filters.Add(
                 new ResponseCacheFilter(
                    new CacheProfile() { 
                      NoStore=true
                     }));
        }
        ...
       )

Il est possible de remplacer le filtre initial par un attribut personnalisé

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public sealed class NoCacheAttribute : ActionFilterAttribute
    {
        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            var filter=filterContext.Filters.Where(t => t.GetType() == typeof(ResponseCacheFilter)).FirstOrDefault();
            if (filter != null)
            {
                ResponseCacheFilter f = (ResponseCacheFilter)filter;
                f.NoStore = true;
                //f.Duration = 0;
            }

            base.OnResultExecuting(filterContext);
        }
    }

Voici un cas d'utilisation

    [NoCache]
    [HttpGet]
    public JsonResult Get()
    {            
        return Json(new DateTime());
    }
4
Davut Gürbüz

Mise en cache de sortie dans MVC

 [OutputCache (NoStore = true, Durée = 0, Emplacement = "Aucun", VaryByParam = "*")] 

 OU 
 [OutputCache (NoStore = true, Durée = 0, VaryByParam = "Aucun")]

1
Deepak

La valeur d'attribut correcte pour Asp.Net MVC Core afin d'empêcher la mise en cache du navigateur (y compris Internet Explorer 11) est la suivante:

[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]

comme décrit dans la documentation Microsoft:

Mise en cache de la réponse dans ASP.NET Core - NoStore et Location.None

0
Nenad