Отключить кеш браузера для всего сайта ASP.NET


199

Я ищу способ отключить кэш браузера для всего сайта ASP.NET MVC

Я нашел следующий метод:

Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
Response.Cache.SetNoStore();

А также метод метатега (он не будет работать для меня, так как некоторые действия MVC отправляют частичный HTML / JSON через Ajax, без заголовка, метатега).

<meta http-equiv="PRAGMA" content="NO-CACHE">

Но я ищу простой способ отключить кеш браузера для всего сайта.


Ответы:


92
HttpContext.Current.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
HttpContext.Current.Response.Cache.SetValidUntilExpires(false);
HttpContext.Current.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Response.Cache.SetNoStore();

Все запросы сначала направляются через default.aspx - при условии, что вы можете просто вставить туда код.


17
Я бы положил его в Global.asax.cs в Application_BeginRequest (). Я не доверяю этой вещи default.aspx ... Другой вопрос: имеет ли это приоритет над атрибутами [OutputCache]?
— chris166

5
Мне нравится идея простого создания фильтра глобальных действий, чтобы все было так. Отменяет необходимость беспокоиться о Default.aspx и Global.asax.
— Кит Адлер

13
Помещение этого в Application_BeingRequest может вызвать некоторые проблемы. Если ваши изображения маршрутизируются через среду выполнения .net (что может произойти, если вы используете сопоставление с подстановочными знаками для хороших URL-адресов), то никакие изображения не будут кэшироваться в браузере. Это может ДЕЙСТВИТЕЛЬНО замедлить загрузку вашей страницы, так как каждый запрос страницы будет перезагружать все изображения.
— Хербрандсон

4
Использование чего-либо программно всегда переопределит любой объявленный атрибут. Другими словами, использование кода OP переопределит любой объявленный атрибут [OutputCache].
— Дэйв Блэк,

Любые мысли о том, как курить тест и убедиться, что отключение кэша на самом деле работает?
— Paaone

366

Создайте класс, который наследуется от IActionFilter.

public class NoCacheAttribute : ActionFilterAttribute
{  
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
        filterContext.HttpContext.Response.Cache.SetValidUntilExpires(false);
        filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
        filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        filterContext.HttpContext.Response.Cache.SetNoStore();

        base.OnResultExecuting(filterContext);
    }
}

Затем поместите атрибуты, где это необходимо ...

[NoCache]
[HandleError]
public class AccountController : Controller
{
    [NoCache]
    [Authorize]
    public ActionResult ChangePassword()
    {
        return View();
    }
}

19
Вместо HttpContext.Current.Response вам, вероятно, следует использовать filterContext.HttpContext.Response, так как HttpContext.Current возвращает предварительный MVC-объект HttpContext, а filterContext.HttpContext возвращает post-MVC HttpContextBase. Это повышает тестируемость и последовательность.
— mkedobbs

5
IActionFilter уже реализован в ActionFilterAttribute, поэтому вам не нужно повторять его.
— Эндрю Дейви

104
В текущих версиях ASP.NET MVC вы можете просто использовать OutputCacheAttribute для предотвращения кэширования: [OutputCache (NoStore = true, Duration = 0, VaryByParam = "None")]
— Эшли Тейт

9
Я хотел бы отметить, что я только что провел несколько дней, используя каждое решение «вставь это в свой код для остановки кэширования» под солнцем для ASP.NET MVC, включая принятый ответ на этот вопрос, но безрезультатно. Этот ответ - атрибут - сработал. +1 Реп, если бы я мог ...
— Том Кидд

5
Возможно, вы захотите добавить if (filterContext.IsChildAction) return;сверху - это предотвратит внешнее действие, которое не будет кэшироваться, если оно вызывает дочернее действие, которое украшено NoCacheатрибутом. Другими словами, NoCacheатрибут не попадет в другие действия, если они выполнят дочерние действия. Кроме того, имя класса должно NoCacheAttributeсоответствовать общепринятому соглашению об именах атрибутов.
— Якуб Конецки

132

Вместо того, чтобы кататься самостоятельно, просто используйте то, что предоставлено для вас.

Как упоминалось ранее, не отключайте кэширование для всего. Например, сценарии jQuery, интенсивно используемые в ASP.NET MVC, должны быть кэшированы. На самом деле в идеале вы должны использовать CDN для тех или иных, но я хочу сказать, что некоторый контент должен быть кэширован.

Здесь я считаю, что лучше всего не использовать [OutputCache] везде, а использовать класс:

[System.Web.Mvc.OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public class NoCacheController  : Controller
{
}

Все ваши контроллеры, для которых вы хотите отключить кэширование, затем наследуются от этого контроллера.

Если вам необходимо переопределить значения по умолчанию в классе NoCacheController, просто укажите параметры кэша в вашем методе действия, и параметры в вашем методе Action будут иметь приоритет.

[HttpGet]
[OutputCache(NoStore = true, Duration = 60, VaryByParam = "*")]
public ViewResult Index()
{
  ...
}

4
@Ozziepeeps, ваш комментарий не верный. Документы msdn обсуждают кеширование браузера, а также простой тест покажет, что этот атрибут изменяет заголовок ответа элемента управления кэшированием на «Cache-Control: public, no-store, max-age = 0» с «Cache-Control: private» без используя атрибут.
— Адам Тюльпер - MSFT

2
Кроме того, вы можете контролировать все три местоположения (сервер, прокси-сервер, клиент) с помощью этого атрибута, так что абсолютно можете контролировать за пределами кэша сервера. Смотрите asp.net/mvc/tutorials/… для получения дополнительной информации.
— Адам Тюльпер - MSFT

1
+1 «Если вам нужно переопределить значения по умолчанию в классе NoCacheController, просто укажите настройки кэша в вашем методе действия, и настройки в вашем методе Action будут иметь приоритет».
— Кораем

2
Обратите внимание, что если вы используете [System.Web.Mvc.OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]на уровне класса, у вас не может быть PartialViews в вашем классе.
— Река Вивиан

1
Метод OutputCache не препятствовал кешированию IE, когда присутствовали два условия: 1) действие не принимало параметров и 2) действие возвращало только текст через Content (someText). Когда я возвращаю JSON и принимаю параметр, кэширование IE должным образом побеждено.
— Кейси Спикман

10

Возможно, вы захотите отключить кэширование в браузере для всех страниц, отображаемых контроллерами (например, HTML-страниц), но оставьте кэширование на месте для таких ресурсов, как скрипты, таблицы стилей и изображения . Если вы используете связывание и минимизацию MVC4 +, вам следует сохранить длительность кэширования по умолчанию для скриптов и таблиц стилей (очень длительные, поскольку кэш становится недействительным на основании изменения уникального URL-адреса, а не на основе времени).

В MVC4 +, чтобы отключить кэширование браузера на всех контроллерах, но сохранить его для всего, что не обслуживается контроллером, добавьте это в FilterConfig.RegisterGlobalFilters:

filters.Add(new DisableCache());

Определите DisableCacheследующим образом:

class DisableCache : ActionFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    }
}

К сожалению, это не работает, так как нажатие кнопки «Назад» после выхода отображает страницу.
— ʙᴀᴋᴇʀ ʙᴀᴋᴇʀ

6

Я знаю, что этот ответ не на 100% связан с вопросом, но он может кому-то помочь.

Если вы хотите отключить кэш браузера для всего веб-сайта ASP.NET MVC , но хотите сделать это ВРЕМЕННО, то лучше отключить кэш в вашем браузере.

Вот скриншот в Chrome


Это именно то, что я искал ... во время разработки, если я изменяю файл .js, это большая боль, чтобы получить это немедленно, когда у меня возникают проблемы с небольшими циклами устранения неполадок / обновления / тестирования. Это прекрасно, спасибо! Просто облегчил отладку моей клиентской жизни
— jleach

2

Я реализовал все предыдущие ответы и все еще имел одно представление, которое не работало правильно.

Оказалось, что имя представления, с которым у меня возникла проблема, было названо «Недавние». Видимо это смутило браузер Internet Explorer.

После того, как я изменил имя представления (в контроллере) на другое имя (я выбрал «Recent5»), вышеприведенные решения начали работать.


0

Вы можете попробовать приведенный ниже код в файле Global.asax.

protected void Application_BeginRequest()
    {
        Response.Cache.SetCacheability(HttpCacheability.NoCache);
        Response.Cache.SetExpires(DateTime.UtcNow.AddHours(-1));
        Response.Cache.SetNoStore();
    }

-1

UI

<%@ OutPutCache Location="None"%>
<%
    Response.Buffer = true;
    Response.Expires = -1;
    Response.ExpiresAbsolute = System.DateTime.Now.AddSeconds(-1);
    Response.CacheControl = "no-cache";
%>

Задний план

Context.Response.Cache.SetCacheability(HttpCacheability.NoCache); 
Response.Expires = -1;          
Response.Cache.SetNoStore();

1
нужна пояснительная проза, даже если она технически правильна
— рмалайтер
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.