Global Office Directory
More Products
Share this page
Home > Community > Technical Blogs > John West Sitecore Blog > Custom Caching Criteria with the Sitecore ASP.NET CMS
The Sitecore Caching for SSL + non-SSL sublayout thread on the Sitecore Developer Network (SDN) forums prompted me to write this blog post about extending the Sitecore ASP.NET layout engine with additional VaryBy caching options.
The Presentation Component Reference manual on SDN provides information about the VaryBy options that Sitecore uses to cache the output of presentation components. This blog post describes how to add an additional VaryBy option (VaryByScheme, for HTTP or HTTPS), but could be informative to anyone attempting to override Sitecore's logic for embedding presentation controls.
You may have wondered why to implement a Sitecore web control you inherit from Sitecore.Web.UI.WebControl and override DoRender() instead of inheriting from System.Web.UI.Control and overriding the Render() method as you might do on projects that don't involve Sitecore. For one thing, using Sitecore's WebControl class gives you the ability to bind your control to a Sitecore placeholder. But more importantly in the context of this post, the Sitecore base class exposes all of the VaryBy properties, and the Render() method in Sitecore.Web.UI.WebControl manages caching - if an entry is in the cache, the Render() method retrieves that HTML, otherwise the Render() method invokes DoRender().
The HTML cache for the output of presentation components works much like a big hashtable. Each time the layout engine invokes a control, if caching is enabled, Sitecore builds a hash key by calling its GetCacheKey() method. This method calls the GetCachingID() method, which returns an identifier for the presentation component, such as the path to the .ascx or .xslt file. The GetCacheKey() method then adds tokens to this value based on the VaryBy caching options specified for the presentation component.
Because Sitecore's Sublayout and XslFile controls each inherit from WebControl, they benefit from this functionality automatically. When you use a sublayout or an XSL file, Sitecore doesn't just run the .aspx or .xslt, but invokes a web control (Sitecore.Web.UI.WebControls.Sublayout or Sitecore.Web.UI.WebControls.XslFile) that renders the file. The Sublayout contrul uses path to the .aspx file as the caching ID; the XslFile control uses the path to the .xslt file.
Sublayouts and XSL files automatically use the file path as the caching ID, but you should override the GetCachingID() method in all of your custom web controls. The base class for web controls included with this solution provides an override that returns the namespace and name of the class as the caching ID.
Some solutions could benefit from custom VaryBy options, such as when using the same presentation components in both HTTP and an HTTPS sites. You can implement a solution based on this prototype, which adds a custom VaryByScheme attribute to the caching keys for all presentation components..
Sitecore uses something like the factory pattern when binding presentation controls to placeholders. For more information about the configuration factory, see my blog post The Sitecore ASPNET CMS Configuration Factory. It looks to me like the general factory instantiates separate factories for building each type of presentation control. To override the types returned by the factory, override the factories.
To use this solution:
This solution applies automatically when binding dynamically using placeholders. If you bind sublayouts or XSL renderings statically using the <sc:sublayout> and <sc:xslfile> controls, to get the described functionality, you need to update those references to use the sublayout and XSL controls included in this solution, typically by adding the following element to the /configuration/system.web/pages/controls element in the web.config file, and then updating the namespaces for sublayout and xslfile controls in .aspx and .ascx files from sc to ss (<sc:sublayout> becomes <ss:sublayout>):
<add tagPrefix="ss" namespace="Sitecore.Sharedsource.Web.UI.WebControls" assembly="assembly"/>
I implemented factories only for sublayouts and XSL controls, but not for method renderings, URL renderings, web controls, or XML controls. You can create these according to your requirements where appropriate. I provided a base class for web controls to return the namespace and class; your controls should inherit from this or override the GetCachingID() method to call the corresponding method to return a unique identifier for the class.
Extending the CMS user interfaces with a checkbox to control the custom VaryBy option would require additional work. You can disable the caching option by setting the VaryByScheme property to false on individual presentation components.
Note the logic in the VaryByScheme property of the WebControl, Sublayout, and XslFile classes (I realize it's debatable whether logic should be allowed in a property, and these classes demonstrate my side of that argument). The goal here is that you coud add a data template with a VaryByScheme checkbox to the base templates for the sublayout and rendering definition items, and use that to determine whether to vary by scheme. Because there is no UI to enable the caching option when binding the control to a placeholder, this code assumes that caching should vary by scheme by default, and only excludes this option if the checkbox in the data template for the presentation control is not selected. It's a little unusual to inspect the rendering definition item when binding the rendering to a placeholder, but this was the only approach I could think of without extending the UI with additional caching options, which would have been more for something that wouldn't necessarily have added much value.
I couldn't find a way to achieve my goal without to add the same logic to three classes: WebControl, Sublayout and XslFile (I wrote a helper class, but it didn't feel right so I removed it). The root of the problem is that I can't change the base class for XslFile or Sublayout to my WebControl implementation without copying entire classes from Sitecore, which I thought would be worse than the duplication (any time you upgrade Sitecore, you would have to check those classes for changes from Sitecore).
I used the CMS 6.5 Technology Preview for this analysis. For more information about caching, see the Cache Configuration Reference on SDN. For even more information about caching with Sitecore, see my blog post Caching Options in the Sitecore ASP.NET CMS.
If you have any additional information about caching individual presentation components with Sitecore, please comment on this blog post.
Tags: API, Architecture, Infrastructure
- Christopher Giddings May 16, 2011 at 9:03 PM
- John West May 17, 2011 at 10:06 AM
- Martijn van der Put May 19, 2011 at 3:19 PM
- Martijn van der Put May 20, 2011 at 7:56 AM
- John West May 20, 2011 at 9:14 AM
- Martijn van der Put May 26, 2011 at 2:11 PM
- John West May 26, 2011 at 7:31 PM
- Martijn van der Put May 26, 2011 at 11:57 PM
- John West May 27, 2011 at 6:43 AM
- Martijn van der Put May 27, 2011 at 7:05 AM
- John West May 27, 2011 at 9:20 AM
- Martijn van der Put May 27, 2011 at 1:06 PM
- John West May 27, 2011 at 1:16 PM
- John West June 14, 2011 at 12:12 PM
- Robbert Hock June 21, 2011 at 1:04 PM
- John West August 22, 2011 at 12:04 PM
- Kamruz Jaman November 16, 2011 at 4:26 AM
- John West November 16, 2011 at 2:33 PM
John has over ten years of experience in the CMS industry. His areas of focus include the Sitecore community, Web industry research, Sitecore technical documentation, and product management.
This website is designed to be fully functional with scripts disabled in browser. Please contact the webmaster for any suggestions