Tags : Umbraco

Advanced macro caching in Umbraco using cookies

Tags : Umbraco

Have you ever wanted fine-grained control over macro caching in Umbraco?  I have.  ASP.NET usercontrols have a VaryByParam attribute in the @OutputCache directive, but Umbraco macros (seemingly) only give you the option of caching by page and/or visitor.  It turns out that if your macros have parameters, then the value of those parameters are used in the cache key – in the below example, the Region parameter has a value of “au”: 

In this case, I’m pulling the region value from a cookie, like so:

<umbraco:Macro runat="server" Alias="Logo" Region="[%region]" />

The site in my example has about 40 macros, 30 of which depend on this region value.  Perhaps you are now asking, “What if cookies are disabled?  Won’t those visitors get all the wrong content?”.  As it stands, yes, this is what would happen.  So you need to inspect the cookies early in the request.  Now, I have not figured out how to hook into the Umbraco begin request event (if one exists), so in code-behind of the base masterpage I’ve added a constructor which inspects the cookies.  This is executed before any macros are rendered.

Cookie Fiddling

Because of the peculiar way ASP.NET deals with cookies in the request & response, this is the fragment of code I used to set the cookie before Umbraco inspects it: 

if (Request.Cookies.AllKeys.Contains(cookie.Name))
{
    Request.Cookies.Remove(cookie.Name);
}
if (Response.Cookies.AllKeys.Contains(cookie.Name))
{
    Response.Cookies.Set(cookie);
}
else
{
    Response.Cookies.Add(cookie);
}

NB: Adding or setting a cookie in the response automatically adds a cookie to the request – if the cookie is already there, you’ll get a duplicate which will confuse Umbraco.

Regarding the macro parameters, you’ll need to define them in the markup (as above) and in the Developer section of the back office: 

 

However, if you’re using a .NET usercontrol as a macro, you don’t actually have to define the corresponding public property in the code behind to get caching. 

If you’re using a lot of caching, I thoroughly recommend the most excellent Macro Cache Disabler package.  It temporarily sets all macro cache durations to zero seconds.

Happy Caching!