3

I tried to learn about Response Caching in .NET Core 3.1. But it didn't work as I wished. I viewed the network in Chrome devtool, and it showed the response header with cache-control: no-cache, no-store.

I also found that Response header was with HeaderCacheControl{public,max-age=100} in Actionfilter. It was the value I expected, but the actual response header in browser is no-cache.

Startup class:

public void ConfigureServices(IServiceCollection services)
{
    services.AddResponseCaching(options=> 
    {
        options.SizeLimit = 1024;
        options.MaximumBodySize = 1024 * 1024 * 100;
        options.UseCaseSensitivePaths = false;
    });
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{   
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    app.UseCookiePolicy();
    app.UseStaticFiles();
    app.UseRouting();
    app.UseAuthentication();
    app.UseAuthorization();
    app.UseResponseCaching();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default", 
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

Controller:

[ResponseCache(Duration = 100, NoStore = false)]
public IActionResult Index()
{
   
    return View();
}
Yu Hsu
  • 33
  • 1
  • 5
  • The order of your pipeline isn't right, you use the `ResponseCaching` middleware before `UseEndpoints` not in the beginning. And serving static files and routing must happen before authentication and authorization. – HMZ Oct 18 '20 at 23:48
  • Thanks. I followed your advice and fix the order of middleware. Also found the imformation in docs(https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-3.1#middleware-order). But, I still get "no-cache, no-store" after fixing it. – Yu Hsu Oct 19 '20 at 11:57

1 Answers1

5

This is normal behaviour, there are multiple factors that plays on if the page is retrieved from disk cache or not.

I'll try to list common scenarios on which a user would request a page and if it's cached or not.

  1. AddResponseCaching and UseResponseCaching controls server side caching while ResponseCacheAttribute controls client side caching via setting the appropriate headers.

The way i like to control client side caching is by setting profiles like the following:

services.AddControllersWithViews(options =>
{
    options.CacheProfiles.Add("Caching", new CacheProfile()
    {
        Duration = 120,
        Location = ResponseCacheLocation.Any,
        VaryByHeader = "cookie"
    });
    options.CacheProfiles.Add("NoCaching", new CacheProfile()
    {
        NoStore = true,
        Location = ResponseCacheLocation.None
    });

})

and you use it like this:

[ResponseCache(CacheProfileName = "Caching")]
  1. Chrome prevents any kind of caching when using HTTPS without a certificate or when the certificate is invalid (in development you are prompted to trust the development cert in order to work over HTTPS)

  2. Browsers disable caching when dev tools are open, they usually send a Cache-Control: no-cache

  3. Hitting reload on chrome (Ctrl + F5) also disables cache and sends a Cache-Control: max-age=0 header with your request which is respected by the server.

  4. If you wish to test your cache if it's really working, do the following:

    1. Open your Chrome dev tools and uncheck the Disable cache checkbox if it's checked.

    2. Request your page like you normally would.

    3. Not try to request the same page via an anchor tag in the page that reference the same page (you should see that the page is retrieved from disk cache) (if the conditions below are respected).

    4. Also you can navigate to your (cache activated) page from another page, if it's cached it will be pulled from the disk cache (if the conditions below are respected).

  5. Pages with Forms and/or any kind of Authorization won't be cached. Pages with Antiforgery token included will be sent with Cache-Control and Pragma headers to no-cache. You can see all the conditions for caching on MSDN.

  6. Also some tools like Fiddler and Postman send no-cache header by default.

HMZ
  • 2,949
  • 1
  • 19
  • 30
  • 3
    Thank you very much. The solution to my issue was sixth point in your scenario list. When I commented out the "Form" and Antiforgery token, it worked nicely. – Yu Hsu Oct 20 '20 at 14:06
  • @YuHsu If this answer solved your problem, mark it as the accepted answer. – HMZ Oct 20 '20 at 14:24
  • Can you please take a look at the question I posted? https://stackoverflow.com/questions/72755972/netcore-responsecache-does-not-work-for-some-routes – Offir Jun 25 '22 at 17:53