Optimizely Block Output Caching

There are lots of good quality Blog and Forum posts about differing ways to implement Block level Donut style Output caching in Optimizely.

The below is the approach I prefer to use. It keeps things simple while making sure that cache is unique for visitor groups and languages. Using this method cache will also be invalidated when a new version of a block is published.

Block controller

Add the Output Cache attribute to the Block Controller index method.

    [OutputCache(VaryByParam = "currentBlock", VaryByCustom = "language", Duration = 600)]
    public ActionResult Index(ProductListBlock currentBlock)

VaryByParam: Setting this to “currentBlock” will cache based on the ToString() method of the BlockData model returning the cache key. We add our logic there to make sure cache is refreshed appropriately.

VaryByCustom: Used to extend output caching with custom requirements. You must handle logic for the custom string by overriding the GetVaryByCustomString method in the Global.asax. We use this to cache language specific versions of our block.

Block Model

Override the Block model ToString() method to return unique cache keys for published versions of the block.

    public override string ToString()
    {
        var content = this as IContent;
        var changeTrackable = this as IChangeTrackable;

        if (content != null && changeTrackable != null)
            return $"{content.ContentGuid}-{changeTrackable.Saved.Ticks}-{EPiServer.Editor.PageEditing.PageIsInEditMode}";

        return base.ToString();
    }

Global.asax

Override the GetVaryByCustomString method in the Global.asax for the custom string passed into the OutputCache declaration. In our case this makes sure that language versions of the block are uniquely cached.

    public override string GetVaryByCustomString(HttpContext context, string custom)
    {
        if (custom == "language")
        {
            return HttpContext.Current.Request.Cookies["Language"]?.ToString();
        }
        return base.GetVaryByCustomString(context, custom);
    }

6 thoughts on “Optimizely Block Output Caching”

    1. Thanks Vincent! Although I can’t take a lot of credit as good content is already out there in blog and forum posts. I just tried a few approaches, decided what worked best for me and shared. Hope you are keeping well mate!

      Like

  1. Yeah this is way I’ve handled it for a long time. Although I’ve crafted a framework to add cache dependencies through the ISynchronizedCache system so that the strings are also based upon any ContentAreas and ContentReferences/PageReferences as the one limitation with this is it ONLY works with it’s own content.

    Like

      1. Sure I can grab you sometime and show you what I’ve done. Sadly as we’re all done I created a framework for an old agency I lost access to but I have a POC that I created for one of our teams that used it and built on it. Can show you the idea. Should probably blog about it sometime too :p The one thing recently on my radar is I don’t know if this works with .NET 5, I was told by some of our devs the caching doesn’t work the same they don’t think but have to look in to it

        Like

      2. Sounds good Scott 🙂 Yes the .Net 5 move is scary as there are so many seemingly small things like this that may require rework. But it’s much more exciting than it is scary. I can’t wait!

        Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: