Domanda

Durante la scrittura di un IHttpHandler personalizzato mi sono imbattuto in un comportamento che non mi aspettavo riguardante l'oggetto HttpCachePolicy.

Il mio gestore calcola e imposta un tag di entità (utilizzando il metodo SetETag su HttpCachePolicy associato all'oggetto di risposta corrente).Se imposto il controllo della cache su pubblico utilizzando il metodo SetCacheability, tutto funziona a meraviglia e il server invia l'intestazione dell'e-tag.Se lo imposto su privato, l'intestazione dell'e-tag verrà soppressa.

Forse semplicemente non ho guardato abbastanza attentamente, ma non ho visto nulla nelle specifiche HTTP/1.1 che possa giustificare questo comportamento.Perché non vorresti inviare E-Tag ai browser impedendo comunque ai proxy di archiviare i dati?

using System;
using System.Web;

public class Handler : IHttpHandler {
    public void ProcessRequest (HttpContext ctx) {
        ctx.Response.Cache.SetCacheability(HttpCacheability.Private);
        ctx.Response.Cache.SetETag("\"static\"");
        ctx.Response.ContentType = "text/plain";
        ctx.Response.Write("Hello World");
    }

    public bool IsReusable { get { return true; } }
}

Sarà di ritorno

Cache-Control: private
Content-Type: text/plain; charset=utf-8
Content-Length: 11

Ma se lo rendiamo pubblico, ritornerà

Cache-Control: public
Content-Type: text/plain; charset=utf-8
Content-Length: 11
Etag: "static"

Finora l'ho eseguito sul server di sviluppo ASP.NET e IIS6 con gli stessi risultati.Inoltre non sono in grado di impostare esplicitamente l'ETag utilizzando

Response.AppendHeader("ETag", "static")

Aggiornamento:È possibile aggiungere manualmente l'intestazione ETag durante l'esecuzione in IIS7, sospetto che ciò sia causato dalla stretta integrazione tra ASP.NET e la pipeline IIS7.

Una precisazione:È una domanda lunga ma la domanda fondamentale è questa: perché ASP.NET fa questo, come posso aggirarlo e dovrei?

Aggiornamento:accetterò La risposta di Tony poiché è essenzialmente corretto (vai Tony!).Ho scoperto che se vuoi emulare completamente HttpCacheability.Private puoi impostare la memorizzazione nella cache su ServerAndPrivate ma hai anche la cache delle chiamate.SetOmitVaryStar(true) altrimenti la cache aggiungerà il file Variare:* header sull'output e non lo vuoi.Lo modificherò nella risposta quando avrò le autorizzazioni di modifica (o se vedi questo Tony forse potresti modificare la tua risposta per includere quella chiamata?)

È stato utile?

Soluzione

Penso che sia necessario utilizzare HttpCacheability.ServerAndPrivate

Questo dovrebbe darti il ​​controllo della cache:private nelle intestazioni e ti consente di impostare un ETag.

La documentazione a riguardo deve essere leggermente migliore.

Modificare: Markus ha scoperto che hai anche chiamato cache.SetOmitVaryStar(true) altrimenti la cache aggiungerà il Vary:* intestazione sull'output e non lo vuoi.

Altri suggerimenti

Sfortunatamente se guardi System.Web.HttpCachePolicy.UpdateCachedHeaders() in .NET Reflector vedi che c'è un'istruzione if che controlla specificamente che la Cacheability non sia privata prima di eseguire qualsiasi operazione ETag.In ogni caso l'ho sempre riscontrato Last-Modified/If-Modified-Since funziona bene per i nostri dati ed è comunque un po' più facile da monitorare in Fiddler.

Se come me non sei soddisfatto della soluzione alternativa qui menzionata dell'utilizzo di Cacheability.ServerAndPrivate e vuoi davvero utilizzare Private invece, forse perché stai personalizzando le pagine individualmente per gli utenti e non ha senso memorizzare nella cache sul server, allora almeno in .NET 3.5 puoi impostare ETag tramite Response.Headers.Add e funziona correttamente.

N.B.se lo fai devi implementare tu stesso il confronto delle intestazioni del client e la gestione della risposta HTTP 304 - non sono sicuro che .NET si occupi di questo per te in circostanze normali.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top