Out the box, sitecore offers several options for caching the output of sublayouts. Some of the options you have for this are things like ‘vary by querystring’ and ‘vary by data’. This post will demonstrate how to setup custom sublayout cache keys.
Behind the scenes Sitecore builds up a cache key by appending together information from the current request based on the parameters selected in the caching options. The result of this being the cache key is longer, the more permutations you select.
For typical builds, the out the box options cover all scenarios however what do you do if you need to customise this?
In a recent project we exploited * (or wildcard) items so we could accomodate data fed from an external api. This would map known url patterns to one node in the tree, allowing the presentation components on the page to be set in sitecore but the data in the body content be fed from and external system. The mvc routing dll solves the same problem in a similar fashion.
With the default cache options we ran into the issue that the cache key for each wildcard page would always be the same since the ‘vary by data’ option used the items id, rather than the dynamic url we were assigning. Essentially every page would share the cache key for the * node.
Solution
There are only two steps needed for this implementation:
- Create custom implementation of a sublayout
- Create custom sublayout factory
Custom sublayout
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
using System; using System.Web; using Sitecore.Web.UI.WebControls; namespace ###.Presentation.Cms.UI { public class StarItemSublayout : Sublayout { /// <summary> /// Setup custom cache key which includes Rawurl, hence allowing caching for * item sublayouts /// </summary> public override string GetCacheKey() { if (!String.IsNullOrEmpty(base.GetCacheKey())) { return String.Concat(base.GetCacheKey(), HttpContext.Current.Request.RawUrl).ToLower(); } return String.Empty; } } } |
To use this on the front end, you would then embed in the markup using:
1 |
<tc:StarItemSublayout runat="server" Path="~/###/Sublayouts/Common/Header.ascx" Cacheable="false" /> |
If you want sublayouts instantiated from Sitecore to make use of your new type, you need to update the sublayout renderingControl in the config:
1 2 3 4 5 |
<renderingControls> ... <control template="sublayout" type="###.Presentation.Cms.UI.StarItemRenderingType, ###.Presentation.Cms" propertyMap="Path=path" /> ... </renderingControls> |
And finally the new rendering type:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
using System; using System.Collections.Specialized; using System.Web.UI; using ###.Domain.Cms.Specialization.MvcRouting.Extensions; using Sitecore; using Sitecore.Diagnostics; using Sitecore.Reflection; using Sitecore.Web.UI; using Sitecore.Web.UI.WebControls; namespace ###.Presentation.Cms.UI { /// <summary> /// Custom rendering type which allows creation of StarItemSublayout /// </summary> public class StarItemRenderingType : SublayoutRenderingType { public override Control GetControl(NameValueCollection parameters, bool assert) { Sublayout sublayout = new Sublayout(); ///Check if we are on a wildcard (or mvc routed) item if (Sitecore.Context.Item.Name == "*" || !String.IsNullOrEmpty(MvcRouteUtility.MatchedRoute())) { ///Create custom sublayout which has more detailed cachekey sublayout = new StarItemSublayout(); } foreach (string str in parameters.Keys) { string str2 = parameters[str]; ReflectionUtil.SetProperty(sublayout, str, str2); } return sublayout; } } } |
In the example above the new sublayout is used for wildcard items as well as items which match an MVCRoute – this is some new functionality currently being developed by Steven Pope @ Sitecore UK.
Interesting post!
I’ve done something similar here but you are overriding more methods and apparently setting sublayout’s properties dynamically via reflection. Pretty sweet. What are the overloaded GetDesignTimeHtmlParameters() and GetDesignTimeLiveControl() properties for?
I think it may be due to some over zealous reflectoring. I’ll check the source tomorrow and update…
It looks like both solutions are v similar – proves it must work 🙂
Thanks for the feedback!
Now updated for slightly simpler implementation of RenderingType – rather than inheriting from RenderingType, it inherits from SublayoutRenderingType
Hi, any news about when VS2012 will be available?
Erm, ask Google perhaps?