Вопрос

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

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

Возможно, я просто недостаточно внимательно присмотрелся, но я не видел ничего в спецификации 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.Полностью приватный, вы можете установить кэшируемость в ServerAndPrivate, но у вас также есть кэш вызовов.СетОмитВарыСтар(true) в противном случае кэш добавит Варьироваться:* заголовок к выходу, а вы этого не хотите.Я отредактирую это в ответе, когда получу разрешения на редактирование (или, если вы видите это, Тони, возможно, вы могли бы отредактировать свой ответ, чтобы включить этот вызов?)

Это было полезно?

Решение

Я думаю, вам нужно использовать HttpCacheability.ServerAndPrivate

Это должно дать вам контроль над кэшем:приватный в заголовках и позволяющий вам установить ETag.

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

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

Другие советы

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top