Атрибут ResponseCache не кэширует данные на стороне клиента

В приложении ASP.NET Core у меня есть метод действий, который возвращает некоторые данные. Я хотел кэшировать эти данные на стороне клиента. Поэтому на основе документации здесь я могу использовать атрибут ResponseCache для метода действия. Этот атрибут добавляет заголовок Cache-Control в ответ

Кэширование ответов относится к заданию заголовков, связанных с кешем, по HTTP ответы, сделанные действиями ASP.NET Core MVC. В этих заголовках указано, как вы хотите, чтобы клиентские и промежуточные (прокси) машины кэшировали ответы на определенные запросы (если вообще). Это может уменьшить количество запрашивает клиент или прокси-сервер для веб-сервера, поскольку в будущем запросы на одно и то же действие могут быть отправлены от клиента или прокси Кэш.

также

Кэширование ответов не кэширует ответы на веб-сервере. Это отличается от кэширования вывода, которое будет кэшировать ответы в памяти на сервер в более ранних версиях ASP.NET и ASP.NET MVC.

Так вот как выглядит мой метод действий

public class LookupController : Controller
{
    [HttpGet]
    [ResponseCache(Duration = 120)]
    public IEnumerable<StateProvinceLookupModel> GetStateProvinces()
    {
        return _domain.GetStateProvinces();
    }
}

Затем я вызываю метод с использованием браузера как http://localhost:40004/lookup/getstateprovinces Вот заголовки запроса и ответа

введите описание изображения здесь

Обратите внимание, что заголовки ответов имеют Cache-Control: public,max-age-120, как ожидалось. Однако, если обновить страницу с использованием F5 (до 120 секунд), то точка останова отладчика внутри метода действия GetStateProvince всегда будет хитом. Это означает, что он не передает данные на стороне клиента.

Есть ли что-то еще, что мне нужно сделать, чтобы включить кеширование на стороне клиента?

Обновление Я пробовал использовать IE, Chrome и POSTMAN без везения. Каждый раз, когда я набираю URL-адрес в адресной строке или удаляю обновление, клиент (то есть браузер или почтальон) делает метод вызова к действию.

Ответ 1

На самом деле атрибут ResponseCache работает как задумано.
Разница в том, что ответ кэшируется, если вы перемещаетесь по страницам своего веб-сайта (случай 1) или используете кнопки "назад" и "вперед" (не при обновлении страницы).

В качестве примера случая 1 у меня есть следующее:

Как вы увидите в статье " Кэширование ответов в ASP.Net Core 1.1", указано следующее:

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

Рекомендации:
[1]. Пример кэширования ответов ядра ASP.NET
[2]. Пример атрибута ResponseCache
[3]: Как контролировать кэширование веб-страниц во всех браузерах?

Ответ 2

Короче говоря, использование атрибута ResponseCache подобного следующему, достаточно для получения кэширования на основе срока действия на стороне клиента для работы в совершенно новом базовом проекте dotnet по умолчанию (включая async методы):

[HttpGet]
[ResponseCache(Duration = 120)]
public IEnumerable<StateProvinceLookupModel> GetStateProvinces()
{
    return _domain.GetStateProvinces();
}

Это работает правильно на скриншоте выше, так как Cache-Control: public,max-age=120 виден там. В большинстве случаев браузеры не будут отправлять последующие запросы до истечения срока действия (то есть в течение следующих 120 секунд или 2 минут), но это решение браузера (или другого клиента).

Если запрос отправляется независимо, у вас либо промежуточное ПО, либо конфигурация сервера, перезаписывающая заголовки ответа, или ваш клиент игнорирует директиву кэширования. На приведенном выше снимке экрана клиент игнорирует кэширование, поскольку там есть заголовок элемента управления кэшем.

Распространенные случаи, когда клиентский кеш игнорируется и запрос отправляется:

  • Chrome предотвращает любое кэширование при использовании HTTPS без сертификата (или недействительного сертификата, это часто встречается при локальной разработке, поэтому обязательно используйте HTTP при тестировании кэша или доверяйте самоподписанному сертификату)
  • Большинство инструментов разработчика браузера отключают кэширование по умолчанию при открытии, это можно отключить
    • Браузеры обычно отправляют дополнительные заголовки, Chrome отправляет Cache-Control: no-cache
  • Обновление напрямую (т.е. Ctrl + F5) заставит большинство браузеров не использовать кеш и делать запрос независимо от возраста
    • Браузеры обычно отправляют дополнительные заголовки, Chrome отправляет Cache-Control: max-age=0 (это видно на скриншоте)
  • Почтальон отправляет заголовок Cache-Control: no-cache что позволяет обходить локальный кеш, что приводит к отправке запросов; Вы можете отключить его в диалоговом окне настроек, в этом случае запросы больше не будут отправляться с вышеуказанной конфигурацией кэша клиента

На данный момент мы вышли за рамки основанного на истечении срока действия клиентского кэширования, и сервер так или иначе получит запрос, и произойдет другой уровень кэширования: вы можете заставить сервер ответить кодом 304 Not Modified (который затем снова работает клиенту, чтобы интерпретировать любым способом, который он хочет) или использовать кэш на стороне сервера и ответить с полным содержанием. Или вы не можете использовать любое последующее кэширование и просто выполнить всю обработку запросов снова на сервере.


Примечание. Атрибут ResponseCache не следует путать с services.AddResponseCaching() & app.UseResponseCaching() промежуточное ПО в конфигурации запуска, поскольку оно предназначено для кэширования на стороне сервера (которое по умолчанию использует кэш в памяти при использовании промежуточного ПО).). Промежуточное программное обеспечение не требуется для клиентского кэширования, атрибут сам по себе достаточен.

Ответ 3

Прежде всего, я хочу кое-что уточнить, и я уверен, что вы уже это знали.

  • ResponseCache никак не равен OutputCache.

  • ResponseCache соответствует моему заголовку мышления, но он не кэширует ничего на стороне сервера.

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

Предварительный просмотр версии ASP.NET core 1.1

https://blogs.msdn.microsoft.com/webdev/2016/10/25/announcing-asp-net-core-1-1-preview-1/

Они внедряют новое промежуточное ПО кэширования ответов. Кэширование ответов Middleware

Демонстрация этого доступна здесь. https://github.com/aspnet/ResponseCaching/blob/dev/samples/ResponseCachingSample/Startup.cs