it-swarm.com.de

Cache-Steuerung: Kein Speichern, Muss-Überprüfung wird nicht an den Client-Browser in IIS7 + ASP.NET MVC gesendet

Ich versuche, sicherzustellen, dass eine bestimmte Seite nie zwischengespeichert wird und nie angezeigt wird, wenn der Benutzer auf die Zurück-Schaltfläche klickt. Diese sehr hoch bewertete Antwort (derzeit 1068 Upvotes) sagt, dass verwendet wird:

Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache");
Response.AppendHeader("Expires", "0");

Wenn ich in IIS7/ASP.NET MVC diese Header jedoch sende, werden dem Client stattdessen diese Antwortheader angezeigt:

Cache-control: private, s-maxage=0 // that's not what I set them to
Pragma: no-cache
Expires: 0

Was ist mit dem Cache-Control-Header passiert? Überschreibt etwas, das in IIS7 oder ASP.NET enthalten ist? Ich habe meine Lösung überprüft und ich habe keinen Code, der diesen Header überschreibt.

Wenn ich zuerst Response.Headers.Remove("Cache-Control"); hinzufüge, macht es keinen Unterschied:

Response.Headers.Remove("Cache-Control");
Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache");
Response.AppendHeader("Expires", "0");

Wenn ich ein [OutputCache]-Attribut hinzufüge:

[OutputCache(Location = OutputCacheLocation.None)]
public ActionResult DoSomething()
{
   Response.Headers.Remove("Cache-Control");
   Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
   Response.AppendHeader("Pragma", "no-cache");
   Response.AppendHeader("Expires", "0");

   var model = DoSomething();
   return View(model);
}

Dann ändern sich die Client-Antwortheader in:

Cache-control: no-cache
Pragma: no-cache
Expires: 0

Was näher ist, aber immer noch nicht die Header, die ich senden möchte. Wo werden diese Header überschrieben und wie kann ich das verhindern?

BEARBEITEN: Ich habe geprüft und die falschen Header werden an Chrome, FF, IE und Safari gesendet.

23
JK.

Durch Versuch und Irrtum habe ich herausgefunden, dass eine Möglichkeit, die Header für IIS7 in ASP.NET MVC richtig festzulegen, folgende ist:

Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.AppendCacheExtension("no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache");
Response.AppendHeader("Expires", "0");

Die erste Zeile setzt Cache-control auf no-cache und die zweite Zeile fügt die anderen Attribute no-store, must-revalidate hinzu.

Dies ist möglicherweise nicht der einzige Weg, bietet jedoch eine alternative Methode, wenn die einfachere Response.AppendHeader("Cache-control", "no-cache, no-store, must-revalidate"); fehlschlägt.

Andere verwandte IIS7-Cache-Steuerungsfragen, die dadurch gelöst werden können, sind:

36
JK.

Wenn Sie diese Header global in Ihrer MVC-Anwendung benötigen. Fügen Sie diese Klasse hinzu.

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class CustomHeaders : System.Web.Mvc.ActionFilterAttribute
{
    [OutputCache(Location = System.Web.UI.OutputCacheLocation.None)]
    public override void OnActionExecuted(ActionExecutedContext context)
    {
        context.RequestContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        context.RequestContext.HttpContext.Response.Cache.AppendCacheExtension("no-store, must-revalidate");
        context.RequestContext.HttpContext.Response.AppendHeader("Pragma", "no-cache");
        context.RequestContext.HttpContext.Response.AppendHeader("Expires", "0");

        base.OnActionExecuted(context);
    }
}

Für die globale Verwendung fügen Sie es der FilterConfig hinzu.

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
        filters.Add(new CustomHeaders());
    }
}

Oder verwenden Sie diese Header nur für einen bestimmten Controller.

[Authorize]
[CustomHeaders]
public class HomeController : Controller
{
    [AllowAnonymous]
    public ActionResult Index()

Randbemerkung: Sie können IIS und web.config für andere Header verwenden. Zum Beispiel für statische Inhalte wie Ihre Bundles (Jquery, Bootstrap). Suchen Sie nach diesen Abschnitten customheaders, staticcontent.

0
ivw

Ich möchte etwas zu JK s Antwort hinzufügen:
Wenn Sie das Cache-Steuerelement auf einen restriktiveren Wert setzen, als es bereits ist, ist es in Ordnung. (d. h: No-Cache einstellen, wenn es privat ist) 

Wenn Sie jedoch einen weniger einschränkenden Wert als setzen möchten (d. H .: Einstellung auf privat, wenn kein Cache vorhanden ist), funktioniert der folgende Code nicht: 

Response.Cache.SetCacheability(HttpCacheability.Private);

Weil die SetCacheablitiy-Methode diesen Code enthält und das Cache-Flag nur setzt, wenn es restriktiver ist: 

if (s_cacheabilityValues[(int)cacheability] < s_cacheabilityValues[(int)_cacheability]) {
    Dirtied();
   _cacheability = cacheability;
}

Um dies in .net mvc zu umgehen, müssen Sie eine Instanz von HttpResponseMessage abrufen und ihrem Headers.CacheControl-Wert eine CacheControlHeaderValue zuweisen: 

actionExecutedContext.Response.Headers.CacheControl = new CacheControlHeaderValue
                                   {
                                       MaxAge = TimeSpan.FromSeconds(3600),
                                       Private = true
                                   };

Eine Instanz von HttpResponseMessage ist in Aktionsfiltern verfügbar. Sie können einen Aktionsfilter schreiben, um Cache-Header-Werte wie folgt festzulegen: 

public class ClientSideCacheAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        var response = actionExecutedContext.ActionContext.Response;
        response.Headers.CacheControl = new System.Net.Http.Headers.CacheControlHeaderValue
        {
            MaxAge = TimeSpan.FromSeconds(9999),
            Private = true,
        };
    }
}
0
Veysel Özdemir