Kentico CMS Quick Tip: FluentCacheKeys - Consistent Cache Dependency Key Generation
Tags: kentico, cms, caching, csharp
Published: 2019-09-02 15:04:28

---
title: Kentico CMS Quick Tip: FluentCacheKeys - Consistent Cache Dependency Key Generation
published: true
description: Learn about the FluentCacheKeys library and how it can help you create valid and consistent cache dependency keys in your Kentico applications.
tags: kentico, cms, caching, csharp
series: Kentico Quick Tips
---

![keys](https://thepracticaldev.s3.amazonaws.com/i/qz775qwmt5cyve6w6a70.jpg)
<figcaption>Photo by <a href="https://unsplash.com/@bergerteam">Florian Berger</a> on <a href="https://unsplash.com">Unsplash</a></figcaption>

## 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](https://docs.kentico.com/k12sp/configuring-kentico/configuring-caching/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 🤓.

> {% link seangwright/kentico-12-design-patterns-part-12-database-query-caching-patterns-43hc %}

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](https://docs.kentico.com/k12sp/configuring-kentico/configuring-caching/setting-cache-dependencies) 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:

```csharp
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:

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

We can also use C# [string interpolation](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated) to help us substitute in variables instead of using string concatenation 👏.

```csharp
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](https://twitter.com/mtipton), 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](https://github.com/fluentassertions/fluentassertions), [FluentValidation](https://github.com/JeremySkinner/FluentValidation), and [GuardClauses](https://github.com/ardalis/GuardClauses).

{% github wiredviews/kentico-fluent-cache-keys %}

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:

```csharp
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:

```csharp
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:

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

And attachments:

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

Or media files:

```csharp
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](https://www.nuget.org/packages/WiredViews.Kentico.FluentCacheKeys/):

```bash
$ 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:

{% tag kentico %}

Or my Kentico blog series:

- [Kentico 12: Design Patterns](https://dev.to/search?q=Kentico%2012%20-%20Design%20Patterns)
- [Kentico CMS Quick Tips](https://dev.to/search?q=Kentico%20CMS%20Quick%20Tip)