Отключить кеш браузера для всего сайта 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.