Invalidate Sitefinity Cache of Multiple Content Types

sitefinity | 2024-08-20

🚩 Problem Overview

Screenshot1

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.

Screenshot2

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.

📚 References