Invalidate Sitefinity Cache of Multiple Content Types
sitefinity | 2024-08-20
🚩 Problem Overview
In our Sitefinity project, we are working with two interconnected content types:
- Content_Type_A: Receives data updates through an open API pushed from an external source.
- Content_Type_B: References Content_Type_A for its business logic and content display.
Both content types are served through separate pages, each with Page Output Caching enabled for performance.
❗ Issue Identified
When a data update is pushed to Content_Type_A via the API:
- The page directly displaying Content_Type_A (blue line) correctly reflects the updated information after cache invalidation.
- However, the page displaying Content_Type_B (red line), which depends on Content_Type_A, does not automatically refresh and continues to show outdated content.
This inconsistent cache behavior can result in confusing user experiences and stale data being shown on key pages.
💡 The Solution
Sitefinity provides a built-in mechanism to programmatically trigger cache invalidation for specific pages or content types when needed.
To address the problem:
- We subscribed to the update event of Content_Type_A.
- Upon detecting an update, we manually triggered cache invalidation for the related pages.
This ensures that both pages — those displaying Content_Type_A directly and those referencing it through Content_Type_B — are updated consistently when the underlying data changes.
🔗 The Solution Code Snippets:
public void Update()
{
if (Content_Type_A_Updated)
{
NotifyCache(TypeResolutionService.ResolveType("Content_Type_B"));
}
}
private static void NotifyCache(Type type)
{
CacheDependency.Notify(GetCacheDependencyKeys(type, type.FullName));
}
private static List<CacheDependencyKey> GetCacheDependencyKeys(Type type, string key)
{
var cacheDependencyKeys = new List<CacheDependencyKey>();
var manager = DynamicModuleManager.GetManager(string.Empty);
string applicationName = manager != null && manager.Provider != null ? manager.Provider.ApplicationName : string.Empty;
cacheDependencyKeys.AddRange(OutputCacheDependencyHelper.GetPublishedContentCacheDependencyKeys(type, applicationName));
var itemIds = manager.GetDataItems(type).Where(x => x.Status == ContentLifecycleStatus.Live && x.Visible).Select(x => x.Id).ToList();
foreach (var itemId in itemIds)
{
cacheDependencyKeys.AddRange(OutputCacheDependencyHelper.GetPublishedContentCacheDependencyKeys(type, itemId));
}
cacheDependencyKeys.Add(new CacheDependencyKey { Key = key, Type = type });
return cacheDependencyKeys;
}
📌 Potential Enhancements
The current solution invalidates the affected cache manually.
To further optimize:
- Implement logic to intelligently locate and invalidate only the specific pages where Content_Type_B depends on the updated Content_Type_A items.
- Reduce unnecessary cache invalidations to maintain optimal site performance.
This enhancement would allow for more targeted and efficient cache management, balancing performance with real-time data accuracy.