loading...
WiredViews

Kentico CMS Quick Tip: FluentCacheKeys - Consistent Cache Dependency Key Generation

seangwright profile image Sean G. Wright ・5 min read

Kentico Quick Tips (10 Part Series)

1) Kentico CMS Quick Tip: Ensuring Successful Backups in Azure App Service 2) Kentico CMS Quick Tip: Azure Search with Faceted Document Categories 3 ... 8 3) Kentico CMS Quick Tip: Integration Testing Roles 4) Kentico CMS Quick Tip: FluentCacheKeys - Consistent Cache Dependency Key Generation 5) Kentico CMS Quick Tip: Automatic Static File Fingerprinting 6) Kentico CMS Quick Tip: Minimal JSON Web APIs with IHttpHandler and .ashx Files 7) Kentico CMS Quick Tip: Faking A Live Site For Integration Testing 8) Kentico CMS Quick Tip: Understanding E-Commerce XML Structures 9) Kentico CMS Quick Tip: Creating an Email Whitelist For Testing Kentico EMS 10) Kentico CMS Quick Tip: Azure Active Directory Authentication

keys

Photo by Florian Berger on Unsplash

Kentico 💕 Caching

Data-driven Content Management Systems, like Kentico CMS, rely heavily on caching to enable flexible content composition while still delivering information as quickly as possible to site visitors.

The Portal Engine technology, which has driven the majority of Kentico applications prior to Kentico 12, provided caching configuration out-of-the-box and allowed for highly configurable caching at the data, component,file, and page levels.

Now, developers carry more of the responsibility for caching the data they use to run their Kentico 12 MVC applications 💪.

Fortunately the APIs for caching in custom code, provided by Kentico, are both powerful and relatively simple to use.

The Importance of Cache Dependency Keys

In a previous post (linked below), I wrote about how we can cache the results of our database queries using software design patterns like Aspect Oriented Programming, Dependency Injection, and the Single Responsibility Principle 🤓.

In that post I also detailed how specifying the correct cache dependency keys, for the data being cached, was important for guaranteeing the cache's Validity.

When content is updated in the CMS, we expect the caches of the (now out of date) data will be evicted from the cache 👢.

We take the risk of this not happening if we don't specify the correct cache dependency keys when we store something in the cache 😨.

Cache dependency keys are effectively the glue between specific content or information in the CMS and the data cached in our MVC application.

Building Cache Dependency Keys Can Be Tricky

So, now you might be thinking to yourself, "This seems pretty important, how do we ensure we are creating the correct keys 🤷‍♀️?"

Well, Kentico does provide a nice table of cache key patterns for all the various types of data we might cache (pages, attachments, media files) 👍.

These patterns are strings with runtime data from our application substituted in for specific placeholders:

string key = "node|<site name>|<alias path>|<culture>";

When the tokens (like <site name>) are replaced with real site values, we end up with a key like the following:

string key = "node|corporatesite|/home|en-us";

We can also use C# string interpolation to help us substitute in variables instead of using string concatenation 👏.

string siteName = "Sandbox";
string nodeAliasPath = "/home";
string culture = "en-us";

string key = $"node|{siteName}|{nodeAliasPath}|{culture}";

In my opinion they can be kinda hard to read 🧐 and very easy to typo ⌨... (don't forget all those pipes | !)

Another developer on our team, Michael, thought it would be a good idea to come up with a way to consistently generate these keys to avoid the issues noted above 💡.

I liked the idea a lot ⚡!

It could help us avoid bugs in what would inevitably be some repetitive code (lots of queries == lots of caching == lots of keys).

It could also help us when writing tests that ensure the correct cache keys are being created 😎.

So, I created a library and made it open source so the rest of the Kentico community could try it out and give some feedback 👐!

FluentCacheKeys

The library, FluentCacheKeys, is inspired 💗 by several other projects with readable and easy to use APIs, like FluentAssertions, FluentValidation, and GuardClauses.

GitHub logo wiredviews / kentico-fluent-cache-keys

Utility library for generating consistent cache dependency keys for Kentico CMS applications

Kentico Fluent Cache Keys

Utility library for generating consistent cache dependency keys for Kentico CMS applications

Install the NuGet Package

Examples

Creating cache keys for pages / documents / nodes

FluentCacheKey.ForPage().WithDocumentId(5)
FluentCacheKey.ForPage().WithNodeId(4)
FluentCacheKey.ForPage().RelationshipsOfNodeId(4)
FluentCacheKey.ForPage().OfSite("Sandbox").WithAliasPath("/home");

FluentCacheKey.ForPage().OfSite("Sandbox").WithAliasPath("/home", "en-us");

FluentCacheKey.ForPages().OfSite("Sandbox").OfClassName(HomePage.CLASS_NAME);

FluentCacheKey.ForPages().OfSite("Sandbox").UnderAliasPath("/home");

Creating cache keys for CMS objects / custom module classes

FluentCacheKey.ForObject().OfClassName(UserInfo.OBJECT_TYPE).WithName("administrator")
FluentCacheKey.

The library is built on .NET Standard 2.0, so it should work with any project using .NET Framework 4.6.1 or newer and any .NET Core project.

It also has tests, of course 🤘, so you can see examples and ensure the code works correctly.

You can check out the source code in the repository above, so here I'd like to give some examples of how it might be used.

If we want to create a key for the page in the CMS tree found under the alias path of /Products/Coffee/Light-Roast for the site named Sandbox, we could use the following call to produce the correct string:

FluentCacheKey
    .ForPage()
    .OfSite("Sandbox")
    .WithAliasPath("/Products/Coffee/Light-Roast");

The intellisense in Visual Studio will make sure that once you select your first method (in this case .ForPage()), only methods that make sense in that context will be allowed to follow (like .OfSite(string siteName)) 😊.

I also reversed some of the language of creating cache keys to make it more readable and intuitive:

FluentCacheKey
    .ForPages()
    .OfSite("Sandbox")
    .UnderAliasPath("/Products/Coffee/Light-Roast");

Here we immediately know that we are creating a dependency on multiple documents, due to .ForPages(), the pages need to all belong to the same site, and under the same path 🤗.

We can also create keys for CMS objects or custom Module class instances:

FluentCacheKey
    .ForObject()
    .OfClassName(UserInfo.OBJECT_TYPE)
    .WithId(2);

And attachments:

FluentCacheKey
    .ForAttachment()
    .WithGuid(new Guid("f4f35038-0b05-4e20-ae4e-807d9632a364"));

Or media files:

FluentCacheKey
    .ForMediaFile()
    .WithGuid(new Guid("a6df379b-6c14-4578-8817-298bfe54a4c3"));

To Kentico's credit, there aren't an overwhelming number of variations of cache key patterns, but it can be confusing that some take siteName while others don't. Do we remember which ones take a Document Id compared to a Node Id 🤯.

For these reasons, I think an API like this, that forces the correct values to be supplied, could be helpful.

I also like that the raw cache key strings aren't visible here, with all their pipes and specific order of tokens.


Feel free to install the NuGet package:

$ dotnet add package WiredViews.Kentico.FluentCacheKeys

Or just copy the code into your own project and make some changes if you'd like.


Summary

I hope this package either helps you organize and clarify your cache management code, or inspires you to come up with your own technique 😃.

I've been thinking about writing a tool to help build consistent cache item name parts, but I haven't solidified on anything I really like yet - there's too many variations and use-cases!

Let me know what you think or if you have any ideas for some utilities that could help in our Kentico projects 📝.

Thanks for reading 🙏!


If you are looking for additional Kentico content, checkout the Kentico tag here on DEV:

Or my Kentico blog series:

Kentico Quick Tips (10 Part Series)

1) Kentico CMS Quick Tip: Ensuring Successful Backups in Azure App Service 2) Kentico CMS Quick Tip: Azure Search with Faceted Document Categories 3 ... 8 3) Kentico CMS Quick Tip: Integration Testing Roles 4) Kentico CMS Quick Tip: FluentCacheKeys - Consistent Cache Dependency Key Generation 5) Kentico CMS Quick Tip: Automatic Static File Fingerprinting 6) Kentico CMS Quick Tip: Minimal JSON Web APIs with IHttpHandler and .ashx Files 7) Kentico CMS Quick Tip: Faking A Live Site For Integration Testing 8) Kentico CMS Quick Tip: Understanding E-Commerce XML Structures 9) Kentico CMS Quick Tip: Creating an Email Whitelist For Testing Kentico EMS 10) Kentico CMS Quick Tip: Azure Active Directory Authentication

Posted on by:

seangwright profile

Sean G. Wright

@seangwright

dev lead @WiredViews, founding partner @craftbrewingbiz. @Kentico Xperience MVP. love to learn / teach web dev & software engineering, collecting vinyl records, mowing my lawn, craft 🍺

WiredViews

Web Dev and Marketing Agency based in Cuyahoga Falls, OH.

Discussion

markdown guide
 

Very cool - thanks for sharing this Sean!