177

Вопрос по asp.net-mvc, jquery, c#, asp.net-mvc-3, .net – Запретить кэширование в ASP.NET MVC для определенных действий с использованием атрибута

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

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

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

Если вы предполагаете, что что-то кэшируется, я рекомендую вам ознакомиться с механизмами управления кэшем здесь:<a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9" rel="nofollow noreferrer">w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9</a>

Apr 05, 2012, 10:01 AMот

8ответов

1

Output Caching in MVC

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

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

13

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

    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.
0

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

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

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

Кэширование ответов в ASP.NET Core - NoStore и Location.None

4

Для MVC6 (DNX), здесь нетSystem.Web.OutputCacheAttribute

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

Но у нас есть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());
    }
47

Все, что тебе нужно:

[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

292

Чтобы убедиться, что 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).

5

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

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

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

Для .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. Это эффективно, когда браузер снова запрашивает ресурс, но на самом деле не мешает кешированию.

На последнем замечании. Вы должны знать, что ресурсы могут также кэшироваться между сервером и клиентом. Интернет-провайдеры, прокси-серверы и другие сетевые устройства также кэшируют ресурсы, и они часто используют внутренние правила, не обращая внимания на реальный ресурс. Вы не можете ничего с этим поделать. Хорошей новостью является то, что они обычно кешируются на более короткие промежутки времени, например, секунды или минуты.

RelatedQuestions