Вимкнути кеш браузера для всього веб-сайту 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-адрес), жодні зображення не будуть кешовані у веб-переглядачі. Це дійсно може уповільнити завантаження сторінки, оскільки кожен запит на сторінку знову завантажить усі зображення.
herbrandson

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 повертає об’єкт HttpContext до MVC, а filterContext.HttpContext повертає пост-MVC HttpConte. Це підвищує заповітність і послідовність.
mkedobbs

5
IActionFilter вже реалізований у ActionFilterAttribute, тому повторювати його не потрібно.
Ендрю Дейві

104
У поточних версіях ASP.NET MVC ви можете просто використовувати OutputCacheAttribute для запобігання кешування: [OutputCache (NoStore = true, тривалість = 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, просто вкажіть параметри кешу у вашому методі дій, і налаштування у вашому методі дій матимуть перевагу.

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

4
@Ozziepeeps, ваш коментар невірний. Документи msdn обговорюють кешування браузера, а також простий тест покаже, що цей атрибут змінює заголовок відповіді кеш-керування на "Кеш-контроль: загальнодоступний, без магазину, max-age = 0" з "Кеш-контроль: приватний" без використовуючи атрибут.
Адам Туліпер - MSFT

2
також fyi - ви можете керувати всіма трьома локаціями (сервер, проксі, клієнт) за допомогою цього атрибуту, щоб абсолютно можна було керувати за межами кеш-сервера. Дивіться на asp.net/mvc/tutorials/… для отримання додаткових відомостей.
Адам Туліпер - MSFT

1
+1 "Якщо вам потрібно змінити параметри за замовчуванням у класі NoCacheController, просто вкажіть налаштування кешу у вашому методі дій, і налаштування вашого методу Action матимуть перевагу."
Кораєм

2
Зауважте, що якщо ви використовуєте [System.Web.Mvc.OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]на рівні класу, ви не можете мати PartialView у своєму класі.
Вівіан-Рівер

1
Метод OutputCache не завадив кешувати IE, коли були два умови: 1) дія не мала параметрів і 2) дія повертала лише текст через вміст (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.

Після того, як я змінив ім'я перегляду (у контролері) на інше ім’я (я вибрав "Останній5"), рішення вище почали працювати.


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
потребує пояснювальної прози, навіть якщо це технічно правильно
rmalayter
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.