Extensible Output Caching with ASP.NET 4 (VS 2010 and .NET 4.0 Series)

[In addition to blogging, I am also now using Twitter for quick updates and to share links. Follow me at: twitter.com/scottgu]

This is the fourteenth in a series of blog posts I’m doing on the upcoming VS 2010 and .NET 4 release.  Today’s post covers some of the output caching extensibility improvements being made to ASP.NET 4.  These can be used by all ASP.NET 4 applications – including those built using both ASP.NET Web Forms and ASP.NET MVC.

Output Caching Today

ASP.NET 1.0 introduced the concept of output caching, which enables developers to capture and store the generated output of pages, controls, controllers, and HTTP responses in an in-memory cache.  On subsequent web requests, ASP.NET can then serve content faster by retrieving and using the generated output from the cache instead of having to execute the page/controller to regenerate the output from scratch.  This can dramatically improve the performance of your application – especially in cases where your content is based on data within a database (since when the content is output cached you end up not having to hit the database on subsequent requests).

ASP.NET’s output caching system is flexible enough to enable you to cache different versions of content depending on the querystring/form-post parameters to a page/controller (for example: Browse.aspx?category=Beverages versus. Browse.aspx?category=Meat).  It also enables you to cache different versions based on the browser type or user-language preference of the client visiting your application. This allows you to cache a mobile version of a page separate from a version optimized for a desktop browser, as well as to vary the cache entries based on whether the user wants to read a page in English or French.  You can configure ASP.NET to cache a particular output cache entry for a specific period of time (for example: 1 minute – after which the next request will regenerate the content and cache it again).  You can also configure ASP.NET to dynamically invalidate a cache entry based on an external event (for example: if the database upon which the cached content depends changes). 

One limitation of output caching with ASP.NET V1->V3.5, though, is that the cache store itself is not extensible – and the cached content always has to be stored in-memory.

ASP.NET 4 Output Cache Extensibility

ASP.NET 4 adds an extensibility point to output caching that now enables developers to configure one or more custom output-cache providers. Output-cache providers can use any storage mechanism to persist output cached content. This makes it possible to easily create output-cache providers that store the cached content using any persistence mechanism – including local or remote disks, databases, cloud storage, and distributed cache engines (like memcached or velocity).

You can create a custom output-cache provider by creating a class that derives from the new System.Web.Caching.OutputCacheProvider class in ASP.NET 4.  Within your derived class you then override 4 public methods that provide implementations for adding/removing/retrieving/updating cached content (a unique key is passed to identify each separate cached entry).  You can then configure ASP.NET 4 to use your custom outputcache provider by registering it using the new <providers> subsection of the <outputCache> element within an application’s web.config file:

image

Above I’ve added a new output cache provider (which I’ve named “SampleCache”) that is implemented using the “ScottOutputCache” class within my OutputCacheSample.dll assembly.  I’ve also configured ASP.NET to use my “SampleCache” implementation as the default output cache implementation whenever content is output cached – this is done by setting the “defaultProvider” attribute on the <outputCache> element. 

And now, when I add an OutputCache directive to the top of any of .aspx page the content will be cached and stored using my ScottOutputCache provider:

<%@ OutputCache Duration="60" VaryByParam="None"  %>

Likewise, if I add an [OutputCache] attribute on any action method within an ASP.NET MVC Controller the content will also be cached and stored using my ScottOutputCache provider:

image

Customizing Which Output Cache Provider is Used

Above I configured ASP.NET to by default always cache content using my “SampleCache” provider whenever output caching is used within the application.

As a slightly more advanced option, developers can also configure ASP.NET to dynamically choose which output cache provider to use on a per-request basis.  This is useful for scenarios where you want to have a slightly richer set of cache semantics. For example, you might want to cache the “Home” page or "Top 10" requested pages of a site using the built-in ASP.NET in-memory provider (which will be super fast because the content will be in-memory), and then cache less frequently requested pages that get lower traffic on disk.

You can dynamically indicate which output cache provider to use on a per-request basis by overriding the GetOutputCacheProviderName() method within the Global.asax file of an application.  Below I’m indicating that for the “Home.aspx” page within my application I want to use the built-in in-memory ASP.NET output cache provider – and that I then want to use whatever is registered within the web.config file for every other request:

image

This ability to easily switch between providers depending on scenarios ends up enabling a bunch of really powerful scenarios.

Common Output Cache Providers

We’ll be shipping samples that demonstrate how to implement a disk-based output cache provider that stores cached content on the file-system.  We’ll also be shipping samples that demonstrate how to integrate output caching with the new Windows Server AppFabric Caching Service (formerly known as “Velocity”).  AppFabric’s caching service will be a free, fully supported, Microsoft distributed cache system.  It will also be easy to use the new ASP.NET 4 output caching extensibility with memcached – a popular open source distributed caching system.

You can learn more about how to create providers by watching Stefan Schackow’s ASP.NET 4 Core Runtime talk at PDC 2009.  You can also learn more about AppFabric’s Caching service from this PDC 2009 talk.

Summary

The addition of output-cache provider extensibility to ASP.NET 4 enables developers to easily pursue more aggressive and more intelligent output-caching strategies for web sites and applications.  These can significantly improve the performance and responsiveness of applications, and improve both end-user experiences as well as reduce the amount of server resources required. 

Hope this helps,

Scott

18 Comments

  • Do you have any plans for F# express editions? As it's quite hard for students to afford full version VS 2010. btw I love your blog posts with pictures

  • That's great stuff Scott, I think the custom Output provider option is simply awesome.

  • great stuff...

  • What about Velocity? Will there be a provider for it?

  • Nice;
    Duration time in second, right?

  • This sounds like a great improvement!

    I'm eager to find out whether this makes the cache more controllable. At present, if you want to clear the cache stored by the OutputCache of an ASP.NET MVC view, you have to specify the absolute virtual path, and query string parameters are ignored. This means if you clear the cache for "/blog/posts" it also clears the cache for "/blog/posts?page=2", "/blog/posts?page=3", etc, and there is no way to make cache clearance more or less selective.

    1. The only way to clear the output cache is with a specific absolute virtual path. So you need to know the URL for every page you want to clear. It's a shame you can't clear the

    I'm about to launch a fairly high-profile (major UK media company) new multimedia web application which I built with ASP.NET MVC. OutputCache profiles were a powerful ally, the performance and speed of the application are really impressive.

  • Customizing output cache provider is awesome.
    Very nice feature in deed

  • Am I right in thinking that Velocity is a little like CDN in that the cached pages will live at some endpoint, so that the sites servers do not have to take a hit for them? Does this mean that once someone Gets a page that is marked to be Cached, that it is pushed out to the distributed cache? will this have an overhead? (Is it time form me to RTM? :))

  • >>> These can significantly improve the performance and responsiveness of applications, and improve both end-user experiences as well as reduce the amount of server resources required.

    I disagree. Actually I disagree with a whole concept of advertising this feature (output caching) by ASP.NET team each time a new version of ASP.NET is released (starting from ASP.NET 1.0). You should never use ouput caching agressively. It is not resource-free and does consume much memory on the server especially on servers which serve much traffic. Check out how much in terms of $$$ you pay more for memory vs. you pay for CPU for contemporary servers. Take a single server which serves 200-500K page views per day and do the math.

  • Are there any enhancements to facilitate Donut / Donut Hole caching scenarios?

  • Great new feature. Excelent work!

  • Scott, if you use Velocity as an output cache provider in a server farm scenario, do all the servers keep their own cached pages or do they share the pool? i.e. so that a page can be cached by one server and then other servers can pick up the cached copy instead of compiling from scratch.

  • Is there plans to be able to remove a specific key from the OutputCache collection instead of just dumping the entire collection for the specific path when using VaryByParam? This was a huge disadvantage of using OutputCache instead of the cache object directly. Which if you look at the sealed class it has a private overloaded method that accepts a path and a key but because of it's accessibility could not be used.

  • Very nice feature, good job1

  • Do you provide also samples for sharedcache?

  • >>> >>> These can significantly improve the performance and responsiveness of applications, and improve both end-user experiences as well as reduce the amount of server resources required.

    >>> I disagree. Actually I disagree with a whole concept of advertising this feature (output caching) by ASP.NET team each time a new version of ASP.NET is released (starting from ASP.NET 1.0). You should never use ouput caching agressively. It is not resource-free and does consume much memory on the server especially on servers which serve much traffic. Check out how much in terms of $$$ you pay more for memory vs. you pay for CPU for contemporary servers. Take a single server which serves 200-500K page views per day and do the math.

    I disagree with you. I work on a content management system that serves millions of requests and generates very complex pages based on XML templates. Without OutputCache enabled the servers simply can't keep up with the requests; there's too much work to be done to generate the final markup in a timely fashion, even with a lot of man hours spent reducing tasks as much as possible and working with profilers to identify bottlenecks.

    OutputCache coupled with memcached keeps the site extremely stable and contrary to your opinion the memory usage is considerably less than what is required to perform these tasks manually on each request. Pages are handed back to the user in .3 seconds instead of 2.5 seconds.

    I'm talking 2 million plus unique impressions here per day. For this site, OutputCache = uptime, no cache = dead. That's a demonstrable fact.

  • Thank you. I enjoy reading this blog so much. Can we have a printable version? So can read on the train ride home.

  • Nice article!!

    Caching is a wonderful tool for the developers to enhance the performance and scalability of the app as these are the things which directly affect the experience of the end-users. As far as ASP.NET caching is concerned, it is good for small web farms only because it is stand alone and in-process in nature. So it’s better to use distributed cache like NCache for larger web farms. Apart from these limitations of ASP.NET Cache, it is helpful tool for the developers.

Comments have been disabled for this content.