Output Cache
Vary by Options

Jan 17

Introduction

In a recent internal build the Sitefinity team has added a new feature request allowing one to control the Vary By options for output caching. I wrote a post a while back talking about how to add this functionality in. But now, I am glad to say, this post is almost completely obsolete.

By default Sitefinity caches a copy of each page based in its User Agent string. In the past this was handy when we may have supplied different Html based on a browser due to its rendering quirks. Today this is a terrible waste of cache resource. We don't create different Html for different browsers any more and not only that the same browser on different machines can generate a vast array of different User agent strings anyway.

In short if you leave this set you are most likely saving a cached copy of your page per visitor.

Vary Cache By Setting

With release 8.2.5908.0 you now have some extra options in your cache profiles.

  • Vary By User Agent
  • Vary By Header
  • Vary By Custom

Now rather than having to write your own RouteHandler class you just need to select the options.

By default I deselect the vary by options.

Output Cache Vary By

The one thing I still use from my old route handler is to negate any cache returns on Page Post backs.

Vary by Custom

Recently I had one requirement where on an eCommerce site I needed to display different prices depending on a user role. Once I had done that I was left with the issue that if the page was cached then the user always got that cached page and prices no matter what role they were assigned. My options where to either make Ajax web requests to get the prices after the page was loaded or not cache the page.

With 8.2.5908.0 I now have a much better option.

To start I created a new cache profile, VaryByWholeSaleRole, and I fill in the Vary By Custom field with a name. (See previous image above.) I use the same name for convenience.

I then assign this cache profile to the pages that I want to use it. For me it was my product list and product details pages.

Next I need to add to my global class an override to return my own output cache rule.

ASP.NET determines\stores different versions of a page based on a string. So we just need to return a unique string for the different versions. Lets see what I did.

public override String GetVaryByCustomString(HttpContext context, String custom)
{
    if (custom == "VaryByWholeSaleRole")
    {
        ClaimsIdentityProxy identity = ClaimsManager.GetCurrentIdentity();
        RoleManager roleManager = RoleManager.GetManager();
 
        if (roleManager.IsUserInRole(identity.UserId, "Wholesalers"))
        {
            return "Wholesaler";
        }
 
        return "Standard";
    }
    return base.GetVaryByCustomString(context, custom);
}

I first check if the page is my new custom variable. (Later I can add more options of course). I then check if the current user belongs to my Wholesaler role. If so, I return a string key of Wholesaler else Standard. Its that simple.

So now I only store two cached versions of the page which is what I want. I haven't had to slow my page by removing the page cache altogether or write a new web service to load the prices after the page has loaded.

This is a really big help and I think Sitefinity should have, (maybe they will at a later date), done a much bigger announcement about it rather than just a little note in a internal build release.

Either way it is there now and I welcome it.


Darrin Robertson - Sitefinity Developer

Thanks for reading and feel free to comment - Darrin Robertson

If I was really helpful and you would buy me a coffee if you could, yay! You can.


Leave a comment
Load more comments

Make a Comment

recapcha code