Вопрос по asp.net, http, c#, caching – Почему HttpCacheability.Private подавляет ETag?

25

При написании собственного IHttpHandler я столкнулся с поведением, которое я не ожидал в отношении объекта HttpCachePolicy.

Мой обработчик вычисляет и устанавливает тег сущности (используя метод SetETag для HttpCachePolicy, связанный с текущим объектом ответа). Если я устанавливаю открытый элемент управления кэшированием, используя метод SetCacheability, все работает как чудо, и сервер отправляет заголовок электронного тега. Если я установлю это как приватное, заголовок электронного тега будет подавлен.

Возможно, я просто не выглядел достаточно усердно, но я не видел в спецификации HTTP / 1.1 ничего, что могло бы оправдать такое поведение. Почему вы не хотите отправлять E-Tag в браузеры, в то же время запрещая прокси хранить данные?

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; } }
}

Вернусь

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

Но если мы изменим его на публичный, он вернется

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

Я запустил это на сервере разработки ASP.NET и IIS6 до сих пор с одинаковыми результатами. Также я не могу явно установить ETag, используя

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

ОбновитьМожно добавить заголовок ETag вручную при запуске в IIS7, я подозреваю, что это вызвано тесной интеграцией между ASP.NET и конвейером IIS7.

осветлениеЭто длинный вопрос, но основной вопрос заключается в следующем:Почему ASP.NET делает это, как я могу обойти это и должен ли я?

Обновить: Я собираюсь принятьТони ответ так как это по существу правильно (иди Тони!). Я обнаружил, что если вы хотите полностью эмулировать HttpCacheability.Private, вы можете установить кеширование на ServerAndPrivate, но у вас также есть кеш вызовов.SetOmitVaryStar(правда) в противном случае кэш добавитВарь: * заголовок к выходу, и вы не хотите этого. Я отредактирую это в ответ, когда получу разрешения на редактирование (или, если вы видите Тони, возможно, вы могли бы отредактировать свой ответ, чтобы включить этот вызов?)

Ваш Ответ

3   ответа
17

Это должно дать вам контроль кэша: private в заголовках и позволит вам установить ETag.

Документация по этому вопросу должна быть немного лучше.

Редактировать: Маркус обнаружил, что у вас также есть вызов cache.SetOmitVaryStar (true), иначе кеш добавит заголовок Vary: * к выводу, и вам это не нужно.

Я не знаю, еслиэтот ответ на другой вопрос описывает причину, по которой @Markus добавляет вызовSetOmitVaryStar(), но в ASP.NET 4.0 он больше не нужен. Sphinxxx
0

Если, как и я, вы недовольны упомянутым здесь обходным приемом использования Cacheability.ServerAndPrivate и действительно хотите вместо этого использовать Private - возможно, потому что вы настраиваете страницы индивидуально для пользователей, и нет смысла кэшировать на сервере - тогда по крайней мере В .NET 3.5 вы можете установить ETag через Response.Headers.Add, и это прекрасно работает.

Нотабене если вы сделаете это, вы должны будете сами сравнить заголовки клиентов и обработку ответов HTTP 304 - не уверены, что .NET позаботится об этом за вас при нормальных обстоятельствах.

Вы всегда можете просто позвонитьHttpCachePolicy.SetNoServerCaching отключить кэширование вывода (то есть кэширование на сервере). Это переопределяет "серверную" частьHttpCacheability.ServerAndPrivate. William Gross
@WilliamGross Вероятно, это должен быть принятый ответ! Спасибо. James
3

К сожалению, если вы посмотрите наSystem.Web.HttpCachePolicy.UpdateCachedHeaders() в .NET Reflector вы видите оператор if, специально проверяющий, что Cacheability не является Private перед выполнением каких-либо операций с ETag. В любом случае, я всегда обнаруживал, чтоLast-Modified/If-Modified-Since хорошо работает с нашими данными и в любом случае немного проще контролировать в Fiddler.

Похожие вопросы