Data caching is a feature that Sitefinity conveniently enables by default. There are numerous settings aimed at providing admins the ability to cache their individual page content, which are labeled as Output Cache Profiles in Sitefinity’s advanced settings:
Out of the box, “No Caching”, “Standard Caching” (2 minutes), and “Long Caching” (20 minutes) will be available for global configuration or on a per page basis. Additionally, you can configure as many profiles as you like. Above, we have configured an additional extra long cache that guarantees to expire no matter how many users may be visiting the site.
Output cache strategies and techniques are worthy of their own blog post, but for now just know that output caches are used to save trips to the database and serve individual page content quickly to front-end users. However, in order to set output caches a user must first view the page and execute that initial trip to the database to fetch all the necessary data. Once that’s done, all subsequent page views for all users will be fast until the cache expires.
This is great for all subsequent users but we should try to minimize that initial load for that very first user. This initial step is inevitable and required. One strategy that we use to minimize this is Sitefinity’s cache manager. It’s leveraged for retaining static content across all pages and not just through individual page output caches.
These pieces of static content could be items in the header or footer of the site, widgets placed in many locations like featured news items, or rich elements that are on all pages. Below is an example of rich navigation that is placed on all pages on one of our sites:
This rich navigation is just a module that lets content admins provide richer content into their navigation at the top of all pages. This does not change often, can have a lot of content, and is consistent across the entire site. It’s a perfect candidate for removing from the individual page cache and into a global cache.
The first step for getting this into the cache is building a new control for rendering the data. For this we created a new controller for grabbing the main navigation dynamic module data:
Nothing so far is overly complex about this controller. The MainNav controller has a set of public properties for managing some functionality. There’s a property for the number of hours data is cached and a pair of properties for managing how navigation elements may be sorted. The Index method grabs the current culture, grabs the navigation elements (from the dynamic module), sorts if needed, and then serves them to the main-nav view listing.
GetMainNavModels is really where the logic is done for caching these navigation elements, but before we dive into that, let’s take a look at how this CacheManager is fetched. At the bottom of this controller I have a property for grabbing the global cache manager:
Sitefinity provides multiple options for grabbing cache managers in case another one is more appropriate:
Once we have a means of getting our cache manager, we can proceed with retrieving/placing data from/in the cache:
An empty listing of main navigation models is created for adding elements (this will either be set from the cache or placed into the cache depending on what’s in there currently) The current culture name is utilized for building out the cache key with the current data type name. If we can get data from the cache, then we’ll use it.
Otherwise, lock and check if we can get the items from the cache in case it’s been set since the last time we checked and locked. If there’s still no data then we’ll get all the live main nav items (dynamic content) and convert them into main nav models. With this clean listing of main nav models, we’ll place them into cache and return this listing back to the view.
With this implementation we’re able to keep the rich navigation in the cache for all pages instead of on an individual page’s cache. This method still relies on a user calling a round-trip to the database, but the number of times this needs to be done for the main navigation is much less. Page output caches are still necessary for all other content on the page, but we’ve removed at least one element that should speed up all initial page loads across the site.