codeflood logo

HTML Cache Lifetime

Any high performance Sitecore website will make good use of caching. After all, pulling already computed values from memory is much quicker than recomputing not to mention the required network trip to the DB to get the data to compute with.

When it comes to individual presentation component caching, there are several options to allow varying the cached output on a number of aspects. For example, the output can be varied by data, so the output of the component on different pages will be cached separately and hence show differently on said pages. Or the component cache entry may be varied by user which is useful if the component displays something about the currently logged in user.

But one thing that isn't present in the cache options of a single component in the layout definition dialog is the ability to define a timespan to cache the component for. Sometimes a component changes it's output over time without a publish operation occurring (which would clear the HTML cache) or the data source items changing. Take for example a component which displays ratings information pulled from a different system or from DMS data. According to the options available in the caching section of the component properties, we'd have to leave the component as not cached so it always showed the correct computed output.

But a component like this isn't always critical and it may be fine to have data up to 10 minutes old displayed. If we can do this then we can reduce server load and increase performance. And that's always a good thing isn't it?

Well, the component output caching is handled internally by the HtmlCache class. Poking around this class recently I discovered there was an overload of the SetHtml() method which accepts a TimeSpan. This looks promising! Further digging and I found a setting in the web.config file titled Caching.HtmlLifetime. This setting controls how long all component output is stored in the HtmlCache. So we could achieve the desired outcome of simply setting this value to 10 minutes. Keep in mind though that this setting is for all components within the Sitecore instance so all component output would expire after 10 minutes in the cache.

If you're working with a WebControl you've got more control. The Sitecore.Web.UI.WebControl.WebControl class contains a public CacheTimeout property which controls the cache entry lifetime for this component individually. All you have to do is set this property before the control is rendered. OK, that's cool, but what if you're using sublayouts, which are the most common presentation component used within Sitecore by far. Luckily the Sublayout class subclasses WebControl, so sublayouts also include this property. Just keep in mind that your codebehind class subclasses System.Web.UI.UserControl and not Sublayout because a sublayout actually wraps your user control. So to get access to the sublayout it's as simple as casting the Parent property to Sitecore.Web.UI.WebControls.Sublayout. The below code sample shows how you could set the CacheTimeout property of your Sublayout.

protected void Page_Load(object sender, EventArgs e)
{
  var sublayout = Parent as Sublayout;
  if (sublayout != null)
    sublayout.CacheTimeout = new TimeSpan(0, 0, 30);
}

Now if you set the component as cacheable in the presentation definition dialog the cache timeout will be used and the component output will be cached only for the duration specified. If the sublayout was statically placed you could also set the property in the markup where you add the sublayout to the containing control.

<sc:Sublayout
    runat="server"
    Path="/layouts/Sandbox/Date and Time.ascx"
    Cacheable="true"
    CacheTimeout="00:00:30" />

And same goes for XSLT renderings. (That's right, I said XSLT renderings. They absolutely have their place). Renderings are implemented in Sitecore through the Sitecore.Web.UI.WebControls.XslFile class which also subclasses Sitecore.Web.UI.WebControl.WebControl, so you can set the CacheTimeout property when statically placing the component, by setting the property in the markup. Unfortunately I cannot work out how you might set the Timeout through code when using an XSLT, but then again XSLT renderings are best suited for processing the Sitecore content tree which shouldn't be changing over time without a publish anyway.

And don't forget your last option, implement your own caching. If you find yourself in a position where Sitecore doesn't support your caching requirements, just implement them yourself. In fact, this advice can be applied to many different systems and scenarios. Don't always rely only on what your system/situation provides. Keep in mind that you can code it yourself...generally...as long as the architecture of the system was done right! :)

Comments

Great post, thanks for sharing. I remember doing this is the past too. He had Twitter settings as items in the CMS and a Sublayout that would use a C# Twitter API to get the recent tweets. I made the Tweet Listing sublayout HTML cache via the same time span code you have so we would not go over the hourly API limit. Very handy!

Hey Ali, Great writeup nice and clean and easy to follow. I had the same issue way back had help from john west who wrote up the same type piece: http://www.sitecore.net/Community/Technical-Blogs/John-West-Sitecore-Blog/Posts/2011/08/Schedule-Expiration-for-Output-Cache-Entries-with-the-Sitecore-ASPNET-CMS.aspx
What I've done in the past was to extend the Layout template to include a default cache time out option for the component and create a custom rendering parameter to allow unique filtering.
Remember the main goal of caching, it should always be extendable to the content author without requiring a developer to fix or make changes :)
Keep up the great work :)

Leave a comment

All fields are required.