Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

ASP.NET Core Response Cache

DZone's Guide to

ASP.NET Core Response Cache

Does ASP.NET Core have an output cache? If so, where can you find it and how can you use it? In this tutorial, you'll learn just that!

· Web Dev Zone
Free Resource

Tips, tricks and tools for creating your own data-driven app, brought to you in partnership with Qlik.

Where is the output cache in ASP.NET Core? Is it gone? No, it’s there but in new and better extensible form, and it is called now response caching. This blog post shows how to use response caching on ASP.NET Core and provides tips about some of the internals of it.

In ASP.NET Core caching is solved as a middleware service that comes with Microsoft.AspNetCore.ResponseCaching NuGet package. In MVC, caching is driven by the ResponseCache attribute. It’s possible to use the ResponseCache attribute without also response caching the middleware to just set response headers. This way, it is possible to tell the browser to cache content, and also cache or proxy servers on the way that can read these headers to find out how to cache page.

By default, response caching uses memory based cache, but there are extension points that allow you to use custom cache storage providers. This blog post doesn’t cover extensibility. It just covers the basics and focuses on stateless public sites.

Using Response Caching

After adding package reference to Microsoft.AspNetCore.ResponseCaching we can register response caching middleware in Startup class using AddResponseCaching() and UseResponseCaching() extension methods.

public void ConfigureServices(IServiceCollection services)
{
    // ...


    services.AddResponseCaching();
    services.AddMvc();

    // ...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{

    // ...

    app.UseResponseCaching();

    app.UseMvc(routes =>
    {

        routes.MapRoute(
            name: "Default",
            template: "{controller=Home}/{action=Index}/{id?}",
            defaults: ""
        );

    });            
}

For MVC controller action we add ResponseCache attribute. The following example shows primitive controller action that returns just a simple view it has.


[ResponseCache(Duration = 30)]
public IActionResult Article()
{

    return View();
}

This is enough to get caching to work with minimal effort. When we run our application and request controller action that is cached we get the following result:

ASP.NET Core response caching output


For a full list of the cache settings that are available check out the following pages from official documentation:

Caching profiles can be defined in application Startup class and they are supported by ResponseCache attribute.

Conditions for Caching

The response caching middleware page by Microsoft lists conditions that a request must meet for caching:

  • The request must result in a 200 (OK) response from the server.
  • The request method must be GET or HEAD.
  • Terminal middleware, such as Static File Middleware, must not process the response prior to the Response Caching Middleware.
  • The Authorization header must not be present.
  • Cache-Control header parameters must be valid, and the response must be marked public and not marked private.
  • The Pragma: no-cache header/value must not be present if the Cache-Control header is not present, as the Cache-Control header overrides the Pragma header when present.
  • The Set-Cookie header must not be present.
  • Vary header parameters must be valid and not equal to *.
  • The Content-Length header value (if set) must match the size of the response body.
  • The HttpSendFileFeature is not used.
  • The response must not be stale as specified by the Expires header and the max-age and s-maxage cache directives.
  • Response buffering is successful, and the total length of the response is smaller than the configured limit.
  • The response must be cacheable according to the RFC 7234 specifications. For example, the no-store directive must not exist in request or response header fields. See 'Section 3: Storing Responses in Caches of the RFC document' for details.

Problems with Cookies

Currently, it is not possible to use cookies with response caching. As soon as the cookies header is present the caching of the request is considered impossible. Services like Application Insights and Antiforgery system by ASP.NET Core don’t work with response caching because they use cookies or set cache headers.

For Application Insights and services like this, it is technically possible to create custom middleware based on default one if cookies are still needed for client-side libraries and there are no dependencies with the application or session state.

Troubleshooting Caching

To some degree, it is possible to monitor response caching. The library uses the ASP.NET Core logging framework to log some activities by response caching middleware. The screen fragment below shows some response caching middleware logs.

aspnet-core-response-caching-log

Sadly, it does not report reasons why the response was not added to the cache. It would help greatly to test our response caching in different environments.

If logs are not enough, then we can always include projects from the response caching GitHub repository to our solution and run these on the debugger to see what’s going on.

When debugging response caching with the browser make sure that the developers' tools that come with the browser don’t set any cookies or cache headers that may affect response caching.

Getting Rid of ARR Affinity Cookie on Azure Web Sites

If your site doesn’t need Application Request Routing (ARR) you can disable the ARR affinity cookie by adding the following block of settings to the web.config of your web application.


<system.webServer>
   <httpProtocol>
    <customHeaders>
      <add name="ARR-Disable-Session-Affinity" value="true"/>
    </customHeaders>
  </httpProtocol>
</system.webServer>

After this modification, there is no more ARR cookies available in your site.

Wrapping up

Although I got response caching to work, I didn’t get it work with Application Insights and other services that work in a browser and that use cookies. Still, I was able to create a simple prototype of a public facing application that is cookieless and uses ASP.NET Core response caching. In this example, I used a memory based cache as I wrote my proof-of-concept code. It was easy to set ResponseCache attributes to controller actions that I wanted to cache. Troubleshooting was a little bit tricky because response cache logs are limited and browser tools may get in the way with their handling of cache headers. As a conclusion, I can say that response caching works okay but needs some improvements to be easier to use.

Explore data-driven apps with less coding and query writing, brought to you in partnership with Qlik.

Topics:
asp.net core ,web dev ,caching

Published at DZone with permission of Gunnar Peipman, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}