Контроль кэша: нет хранилища, необходимо повторное подтверждение не отправлено клиентскому браузеру в IIS7 + ASP.NET MVC
Я пытаюсь убедиться, что определенная страница никогда не кэшируется и не отображается, когда пользователь нажимает кнопку "Назад". Этот очень высоко оцененный ответ (в настоящее время 1068 голосов) говорит, чтобы использовать:
Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache");
Response.AppendHeader("Expires", "0");
Однако в IIS7 / ASP.NET MVC, когда я отправляю эти заголовки, клиент вместо этого видит эти заголовки ответа:
Cache-control: private, s-maxage=0 // that's not what I set them to
Pragma: no-cache
Expires: 0
Что случилось с заголовком контроля кеша? Перезаписывает ли что-то родное для IIS7 или ASP.NET? Я проверил свое решение, и у меня нет кода, который перезаписывает этот заголовок.
Когда я добавлю Response.Headers.Remove("Cache-Control");
Во-первых, это не имеет значения:
Response.Headers.Remove("Cache-Control");
Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache");
Response.AppendHeader("Expires", "0");
Когда я добавляю [OutputCache]
атрибут:
[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);
}
Затем заголовки ответа клиента изменяются на:
Cache-control: no-cache
Pragma: no-cache
Expires: 0
Который ближе, но все еще не заголовки, которые я хочу отправить. Где эти заголовки переопределяются и как я могу это остановить?
РЕДАКТИРОВАТЬ: Я проверил, и неправильные заголовки отправляются в Chrome, FF, IE и Safari, так что это выглядит проблема сервера, а не проблема, связанная с браузером.
2 ответа
Методом проб и ошибок я обнаружил, что один из способов правильно установить заголовки для IIS7 в ASP.NET MVC:
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.AppendCacheExtension("no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache");
Response.AppendHeader("Expires", "0");
Первая строка устанавливает Cache-control
в no-cache
, а вторая строка добавляет другие атрибуты no-store, must-revalidate
,
Это может быть не единственный способ, но он предоставляет альтернативный метод, если более простой Response.AppendHeader("Cache-control", "no-cache, no-store, must-revalidate");
выходит из строя.
Другие связанные вопросы управления кэшем IIS7, которые могут быть решены этим:
- Что-то заставляет ответы иметь контроль кеша: частный в IIS7
- IIS7: настройка кэша не работает... почему?
- Заголовки кэширования клиента IIS7 + ASP.NET MVC не работают
- Установить контроль кэша для страниц ASPX
- Контроль кэша: нет хранилища, необходимо повторное подтверждение не отправлено клиентскому браузеру в IIS7 + ASP.NET MVC
Я хочу добавить что-то к ответу JK.:
Если вы устанавливаете для элемента управления кеша более ограничительное значение, чем оно есть, это нормально. (то есть: установка no-cache, когда это приватно)
Но, если вы хотите установить менее ограничительное значение, чем оно есть (то есть: установить значение private, когда оно не кэшируется), приведенный ниже код не будет работать:
Response.Cache.SetCacheability(HttpCacheability.Private);
Потому что метод SetCacheablitiy имеет этот код ниже и устанавливает флаг кеша только в том случае, если он более строгий:
if (s_cacheabilityValues[(int)cacheability] < s_cacheabilityValues[(int)_cacheability]) {
Dirtied();
_cacheability = cacheability;
}
Чтобы преодолеть это в.net mvc, вам нужно получить экземпляр HttpResponseMessage и назначить CacheControlHeaderValue
к его Headers.CacheControl
значение:
actionExecutedContext.Response.Headers.CacheControl = new CacheControlHeaderValue
{
MaxAge = TimeSpan.FromSeconds(3600),
Private = true
};
Экземпляр HttpResponseMessage
доступно в фильтрах действий. Вы можете написать фильтр действий для установки значений заголовка кэша, например так:
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,
};
}
}
Если вам нужны эти заголовки глобально в вашем приложении MVC. Добавьте этот класс.
[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);
}
}
Для глобального использования добавьте его в FilterConfig.
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new CustomHeaders());
}
}
Или используйте эти заголовки только на конкретном контроллере.
[Authorize]
[CustomHeaders]
public class HomeController : Controller
{
[AllowAnonymous]
public ActionResult Index()
Примечание: вы можете использовать IIS и web.config для других заголовков. Например, для статического контента, такого как ваши пакеты (jquery,bootstrap). Поищите в этих разделах customheaders, staticcontent.