Запретить кэширование в ASP.NET MVC для определенных действий с использованием атрибута

У меня есть ASP.NET приложение MVC 3. Это приложение запрашивает записи через JQuery. JQuery вызывает действие контроллера, которое возвращает результаты в формате JSON. Я не смог доказать это, но я обеспокоен тем, что мои данные могут кэшироваться.

Я хочу, чтобы кэширование применялось только к определенным действиям, а не ко всем действиям.

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

8 ответов


чтобы убедиться, что JQuery не кэширует результаты, в ваших методах ajax поместите следующее:

$.ajax({
    cache: false
    //rest of your ajax setup
});

или для предотвращения кэширования в MVC мы создали собственный атрибут, вы можете сделать то же самое. Вот наш код:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed 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]. Или сделать это для всех, вы можете просто поместить атрибут в класс базового класса, от которого вы наследуете свои контроллеры (если у вас есть), как у нас здесь:

[NoCache]
public class ControllerBase : Controller, IControllerBase

вы можете также украсьте некоторые действия этим атрибутом, если вам нужно, чтобы они не были кэшируемыми, а не украшали весь контроллер.

если ваш класс или действий не было NoCache когда он был отображен в вашем браузере, и вы хотите проверить, что он работает, помните, что после компиляции изменений вам нужно сделать "жесткое обновление" (Ctrl+F5) в вашем браузере. Пока вы этого не сделаете, Ваш браузер сохранит старую кэшированную версию и не обновит ее с помощью "обычного обновления" (F5).


вы можете использовать встроенный атрибут кэша для предотвращения кэширования.

для .net Framework:[OutputCache(NoStore = true, Duration = 0)]

для .net Core:[ResponseCache(NoStore = true, Duration = 0)]

имейте в виду, что невозможно заставить браузер отключить кэширование. Лучшее, что вы можете сделать, это предоставить предложения, которые большинство браузеров будут уважать, обычно в виде заголовков или мета-тегов. Этот атрибут декоратора отключит кэширование сервера, а также добавит этот заголовок:Cache-Control: public, no-store, max-age=0. Он не добавляет мета-теги. При желании, их можно добавить вручную в представлении.

кроме того, jQuery и другие клиентские фреймворки попытаются обмануть браузер, чтобы не использовать его кэшированную версию ресурса, добавив материал в url-адрес, например метку времени или GUID. Это эффективно для того, чтобы браузер снова запрашивал ресурс, но на самом деле не предотвращает кэширование.

на последней ноте. Вы должны понимать, что ресурсы также могут быть кэшированы между сервером и клиентом. ISP, прокси и другие сетевые устройства также кэшируют ресурсы и часто используют внутренние правила, не глядя на фактический ресурс. С этим ничего не поделаешь. Хорошей новостью является то, что они обычно кэшируются для более коротких временных рамок, таких как секунды или минуты.


все, что вам нужно, это:

[OutputCache(Duration=0)]
public JsonResult MyAction(

или, если вы хотите отключить его для всего контроллера:

[OutputCache(Duration=0)]
public class MyController

несмотря на дебаты в комментариях здесь, этого достаточно, чтобы отключить кэширование браузера - это вызывает ASP.Net чтобы выдать заголовки ответов, сообщающие браузеру, что срок действия документа истекает немедленно:

OutputCache Duration=0 Response Headers: max-age=0, s-maxage=0


в действии контроллера добавьте к заголовку следующие строки

    public ActionResult Create(string PositionID)
    {
        Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
        Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0.
        Response.AppendHeader("Expires", "0"); // Proxies.

здесь NoCache атрибут, предложенный mattytommo, упрощенный с помощью информации из ответа Криса Мошини:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class NoCacheAttribute : OutputCacheAttribute
{
    public NoCacheAttribute()
    {
        this.Duration = 0;
    }
}

для MVC6 (DNX на), нет System.Web.OutputCacheAttribute

Примечание: при установке NoStore параметр Duration не учитывается. Можно задать начальную продолжительность первой регистрации и переопределить ее пользовательскими атрибутами.

но у нас есть Microsoft.AspNet.Mvc.Filters.ResponseCacheFilter

 public void ConfigureServices(IServiceCollection services)
        ...
        services.AddMvc(config=>
        {
            config.Filters.Add(
                 new ResponseCacheFilter(
                    new CacheProfile() { 
                      NoStore=true
                     }));
        }
        ...
       )

можно переопределить начальный фильтр с помощью пользовательского атрибута

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public sealed class NoCacheAttribute : ActionFilterAttribute
    {
        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            var filter=filterContext.Filters.Where(t => t.GetType() == typeof(ResponseCacheFilter)).FirstOrDefault();
            if (filter != null)
            {
                ResponseCacheFilter f = (ResponseCacheFilter)filter;
                f.NoStore = true;
                //f.Duration = 0;
            }

            base.OnResultExecuting(filterContext);
        }
    }

вот вариант использования

    [NoCache]
    [HttpGet]
    public JsonResult Get()
    {            
        return Json(new DateTime());
    }

кэширование вывода в MVC

[OutputCache(NoStore = true, Duration = 0, Location="None", VaryByParam = "*")]

OR
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]


правильное значение атрибута дляAsp.Net MVC Core для предотвращения кэширования браузера (включая Internet Explorer 11) составляет:

[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]

как описано в документации Microsoft:

кэширование ответов в ASP.NET Core-NoStore и местоположение.Нет!--11-->