Flush Partial HTML on Dictionary changes

Created: 27 Sep 2021, last update: 4 Oct 2021

Flush Partial HTML on Dictionary changes (Sitecore 10.1+)

If you use Partial Html Cache and Sitecore Dictionary items the Cache will not flush on changes. Also depend on your code other items changes are also not part of the out of the box flush option.

Adding automatically a relation to the used dictionary items requires some complex logic that is not easy or might be time consuming to execute. If you want to flush the partial html cache when there are dependencies changed that are not part of the options. The only thing you can do is publish the data sources or (the whole website) or use the cache admin tool, but that do only one server, no remoting no other Sitecore servers.

For flushing Html cache on Dictionary change I have 3 solutions or actually workaround: note: There are multiple ways to use the Dictionary but this is about when using Sitecore Items in master/web database and editors can change the value.

1) Use normal Html Cache
Use normal Html Cache for renderings that are depending on Dictionary items, you can perfectly use the Html caching side by side to Partial Html caching

2) Add the dictionary fields to Related Items
Create a “Related Items for Cache Flush” Field on your datasource template, use standard values to specified the dependencies. Optionally gives the Field “Field Read” deny permissions so you don’t bother the editor with this technical field. Now you can use the Related Items flush on the rendering to flush your Rendering on some specific dictionary items.

3) Full clear cache on dictionary change
Create a processor in the item:save event that do a clear on the cache when a dictionary item is saved. Flush the entire cache or specify which renderings you want to clear, auto detect which rendering are using the dictionary is complex to write. So specify or just flush the whole cache. This goes against the idea of the partial HTML cache, but it is useful to be able to completely empty the cache if you need to. Usually the dictionary is not modified much and extra permissions are needed for this.

using Sitecore.Abstractions;
using Sitecore.Diagnostics;
using Sitecore.Data.Items;
using System;

using Sitecore.Data.Events;
using Sitecore.Events;
using Sitecore.Web;
using System.Collections.Generic;
using System.Linq;

namespace DictionaryFlushPartialCache
{
    
    public class Clear
    {
        private readonly BaseSiteContextFactory _siteContextFactory;

        public Clear(BaseSiteContextFactory siteContextFactory)
        {
          Assert.ArgumentNotNull((object) siteContextFactory, nameof (siteContextFactory));
          this._siteContextFactory = siteContextFactory;
        }

        public void OnItemEvent(object sender, EventArgs args)
        {
            Assert.ArgumentNotNull((object)args, nameof(args));
            Item item = ExtractItem(args);
            if (item != null && item.Paths.FullPath.StartsWith(@"/sitecore/system/Dictionary"))
            {
                Flush();
            }
        }

        private static Item ExtractItem(EventArgs args)
        {
            Assert.ArgumentNotNull((object)args, nameof(args));
            switch (args)
            {
                case ItemSavedRemoteEventArgs savedRemoteEventArgs:
                    return savedRemoteEventArgs.Item;
                case SitecoreEventArgs sitecoreEventArgs:
                    return (Item)Sitecore.Events.Event.ExtractParameter(args, 0);
            }
            return (Item)null;
        }

        private void Flush()
        {
            var sites = GetSitesWithPartialHtml();
            foreach (SiteInfo site in sites)
            {
                var partialcache = Sitecore.Caching.CacheManager.FindCacheByName(site.Name + "[partial html]");
                if (partialcache != null)
                {
                    partialcache.Clear();
                }
            }
        }

        private IEnumerable GetSitesWithPartialHtml()
        {
            return this._siteContextFactory.GetSites().Where(x => x.CacheHtml && x.EnablePartialHtmlCaheClear);
        }
    }
}
<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <initialize>
        <processor type="RadioPollResult.Eventing.Event, RadioPollResult"/>
      </initialize>
    </pipelines>
    <events>
      <event name="item:saved">
        <handler type="DictionaryFlushPartialCache.Clear, DictionaryFlushPartialCache" method="OnItemEvent" resolve="true" />
      </event>
      <event name="item:savedremote">
        <handler type="DictionaryFlushPartialCache.Clear, DictionaryFlushPartialCache" method="OnItemEvent" resolve="true" />
      </event>
    </events>
  </sitecore>
</configuration>

Note:
3 things you can do to Flush Partial HTML on Dictionary changes, choose the solution that best suits your project. The solutions are generic and also apply to other dependencies that are outside of the available content dependencies options. It is also possible even quite simple if you can easily pick up the depencies to make options yourself. See Sitecore 10.1 Build a Home Item Content dependencies option for Partial Html Cache