У меня есть метод действия, который я хочу кэшировать:
[OutputCache(Duration=60*5, Location=OutputCacheLocation.Any, VaryByCustom="index")]
public ActionResult Index()
{
return View();
}
При таком подходе:
public override string GetVaryByCustomString(HttpContext context, string custom)
{
context.Response.Cache.SetOmitVaryStar(true);
context.Response.Cache.VaryByHeaders["Cookie"] = true;
if (User.Identity.IsAuthenticated)
{
Debug.Print("Authenticated");
context.Response.Cache.SetNoServerCaching();
context.Response.Cache.SetCacheability(HttpCacheability.Private);
return null;
}
else
{
Debug.Print("Non authenticated");
return custom;
}
}
Идея заключалась в том, чтобы сохранить кешированную версию страницы для неаутентифицированных пользователей, но избегайте кеширования для аутентифицированных .
Я думал, что он всегда будет возвращать HTTP-заголовок Vary: Cookie
, но это не так.
Выполняя тест с помощью Fiddler и дважды отправляя один и тот же запрос, в первом HTTP-вызове все идет хорошо:
HTTP/1.1 200 OK
Cache-Control: public, max-age=300
Content-Type: text/html; charset=utf-8
Expires: Thu, 09 Feb 2012 10:53:36 GMT
Last-Modified: Thu, 09 Feb 2012 10:48:36 GMT
Vary: Cookie
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 09 Feb 2012 10:48:37 GMT
Content-Length: 441
Но во втором он перезаписывает заголовок:
HTTP/1.1 200 OK
Cache-Control: public, max-age=297
Content-Type: text/html; charset=utf-8
Expires: Thu, 09 Feb 2012 10:53:36 GMT
Last-Modified: Thu, 09 Feb 2012 10:48:36 GMT
Vary: *
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 09 Feb 2012 10:48:39 GMT
Content-Length: 441
Итак, насколько мне известно, браузеры не кэшировать запрос, даже если он является общедоступным, поскольку Vary: *
означает, что запрос был сгенерирован с параметрами, которых нет ни в URL-адресе, ни в заголовках HTTP. Есть ли способ исправить это?
С уважением.
ОБНОВЛЕНИЕ:
Аналогичным образом, когда я отправляю два идентичных аутентифицированных запроса, первый вызов получает модификатор private
, но не заголовок Vary
:
HTTP/1.1 200 OK
Cache-Control: private, max-age=300
Content-Type: text/html; charset=utf-8
Expires: Thu, 09 Feb 2012 12:43:14 GMT
Last-Modified: Thu, 09 Feb 2012 12:38:14 GMT
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 09 Feb 2012 12:38:14 GMT
Content-Length: 443
Но второй получает тот же ответ, что и неаутентифицированный запрос:
HTTP/1.1 200 OK
Cache-Control: public, max-age=298
Content-Type: text/html; charset=utf-8
Expires: Thu, 09 Feb 2012 12:44:32 GMT
Last-Modified: Thu, 09 Feb 2012 12:39:32 GMT
Vary: *
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 09 Feb 2012 12:39:33 GMT
Content-Length: 443
Я загрузил тестовый проект, показывающий проблему , так что, возможно, вы захотите попробовать.
Имейте в виду, что существует IHttpModule
, который устанавливает запрос как аутентифицированный или нет, в зависимости от того, есть ли в запросе cookie или нет, это не подход «реальной жизни», он предназначен только для в целях тестирования.
Проект содержит только веб-страницу со ссылкой на себя, ссылку для входа в систему и еще одну ссылку для выхода из системы:
HTTP 302
снова на главную страницу. HTTP 302
переадресации на домашнюю страницу. Ожидаемое / идеальное поведение будет следующим:
Но пока что это поведение:
Vary
в аутентифицированном ответе. Я не знаю, ошибаюсь ли я в кешировании, просто упускаю какую-то деталь или OutputCache
работает не очень хорошо, но я был бы признателен за любое руководство.
Ура.
ОБНОВЛЕНИЕ 2:
Я намерен использовать семантику кеширования HTTP, чтобы:
Если я изменю объявление OutputCache, чтобы выполнять кэширование только на сервере и предотвращать кеширование нисходящего и клиентского каналов:
[OutputCache(Duration=60*5, Location=OutputCacheLocation.Server, VaryByCustom="index")]
он ведет себя так, как ожидалось, но предотвращается кеширование нисходящего потока и клиента, а это не то, что я хочу.