Skip to main content

Custom Caching with Sitecore

Custom Caching with Sitecore

Caching has been always black box and full of surprise, if we define caching strategy in our application it will do surprise with the performance and if not then will create mess.

Let's first understand Caching A cache is a temporary storage area. Caching works best with data that change infrequently. Caching makes a copy of data that can be returned much faster than from the original source.

What we have in Sitecore for cacheing Sitecore internally uses various caches to Store data, Render presentation logic In-memory information in order to improve performance and response time.These are caches that inherit from Sitecore.Caching.CustomCache class .

Let's talk about how we can implement custom caching in SItecore Custom Caching component provides capability to cache application specific items. e.g., Site configuration, Custom View Model etc. We can have following caching implementations which are injected at runtime based on the configuration.

  • In Memory cache [Default]
  • Redis cache
  • Mem cache
We need to define corresponding provider in services section as code snippet

  <sitecore><services> 
    <register zsitecore.caching="" lifetime="Singleton"
      servicetype="Sitecore.Core.Interfaces.Caching.ICacheManager,Sitecore.Core.InterfacesimplementationType="  zsitecore.caching.inmemorycacheprovider=""></register></services></sitecore> 

Package Details 1.Create a new package source to refer Sitecore Nuget packages. 3. Browse and install the packages. Package Contents

  • 1. Base Package
  • 2. MemCache Package
  • 3. Redis package

In Memory Caching: InMemory cache uses MemoryCache (System.Runtime.Caching) to store commonly used expensive data on server side.

  • The cache stored in the memory of web server.
  • In memory cache can store simple types and any objects.
  • In memory cache life ends with application pool life.
  • Using Cache duration we can configure when cache will expiry.
  • To make the In-memory cache to work,
  • 1. Specify the “InMemoryCacheProvider” assembly identifier in services section
  • 
    <services>
      <registerservicetype
        implementationtype="Sitecore.Caching.InMemoryCacheProvider,Sitecore.Foundation.Interfaces lifetime="
        itecore.core.interfaces.caching.icachemanager=""
        itecore.foundation.interfaces.caching=""
        singleton="">
      </registerservicetype></services>
    
  • 2. Set the Time out in the file config file
<!--In Memory Settings-->
<setting name="DefaultCacheExpirationTimeinMinutes" value="30">
Caching.Redis Redis Cache is distributed cache, just pass a key-value pair to store data and use the same key to retrieve its associated values. The services can be hosted externally, So that even the running web server goes done, it will not affect the Redis caching Server. It stores the simple type and serialized object in string format. Host the Redis Setup as Services and start the service. To make the Redis cache to work:
  • 1. Specify the “Redis” provider in Sitecore Settings
  •  <services>
       <registerservicetype
          implementationtype="Sitecore.Caching.Redis.RedisCacheProvider,Sitecore.Found lifetime="
          sitecore.core.interfaces.caching.icachemanager=""
          sitecore.foundation.interface.caching=""
          singleton="">
        </registerservicetype></services>
    
  • 2.Set up the Host name, port number, Cache time, secured and password to run the redis cache and password can be set in redis.config file in service.

 <!--Redis Caching Settings-->
  <setting name="RedisHost" value="127.0.0.1">
    <setting name="RedisPort" value="6379">
      <setting name="RedisCacheTimeout" value="10">
        <setting name="RedisIsSecured" value="false">
          <setting name="RedisAccountKey" value="foobared">
Caching.Memcached Mem Cache is also a distributed memory object caching system. Mem cache is running as separate service, so all the web servers can point to same location for caching. Host the Services and start the service. To make the MemCache to work,
  • 1.Specify the configuration node and memcache section.
  • 
                <configsections>
                  <sectiongroup name="enyim.com">
                   <section
                      name="memcached" type="Enyim.Caching.Configuration.MemcachedClientSection, 		  Enyim.Caching"></section></sectiongroup>
                </configsections><enyim .com=""><memcached protocol="Binary"><servers>
                      <add address="127.0.0.1" port="11211"></add></servers> </memcached>
                </enyim>
                
  • 2. Specify the “Memcached” provider in Sitecore Settings
  •          <services>
                  <register Sitecore.foun="" lifetime="Singleton"
                    servicetype="Sitecore.Core.Interfaces.Caching.ICacheManager,Sitecore.Foundat implementationType="
                    sitecore.caching.memcached.memcachemanager="" <
                  </register></services>
                  
  • 3. Set up the time out for mem cache.
          <!--Memcache Settings-->
           <setting name="CacheDurationInHours" value="10">
How to Use
  • 1.Define appropriate cache setting in configuration.
  • 2.Use CacheManager class methods to Add/Get/Remove Items from Cache.
  string key= "site_metadata"; 
              var metadata= CacheManager.Get(key); if(null==metadata) { metadata = FUNCTIONTOGETMETADATA();
                CacheManager.Add(key,metadata); } 
or you can use GetOrSet method
 var points = CacheManager.GetOrSet($"MapPoints_{itemId}", ()=> 
                { var item = SC.Context.Database.GetItem(new
                SC.Data.ID(itemId)); 
                return this.mapPointRepository.GetAll(item); }); 
Do' and Don't
  • 1.Make sure all cacheable objects are serializable.
  • 2.Sitecore Items are not serializable, so you won’t be able to cache them using Redis / Memcache. However in-memory cache can cache them.
  • 3.Redis cache uses JsonSerilezer to serialize item to string and cache it.
  • 4.Ensure cachekey should be very specific. Since Sitecore supports multiple site and languages. Ideally key should be like "sitename_language_keyname"
  • 5.Make sure to clear cache when Sitecore item is published. Already a processor is added to take care of this.
  • 6.Request specific data should not be cached using this module. Extension We can have different type of caching requirement for different type of application. Sitecore Caching module can provide different implementation of caching i.e. InMemory,Redis and Memcache, beyond this we can implement other caching providers.

Custom Cache Manager: We can implement custom Cache manager. Cache Manager follows DI pattern, so it can be extended to support any CacheProvider of choice.

  • 1.Implement Sitecore.Core.Interfaces.Caching.ICacheManager in your Provider namespace MyAssembly.Cache{ public class MyCustomProvider : ICacheMaanger{ ... } }
  • 2. Specify your provider in appsetting
   <<sitecore>
                  <services>
                    <register
                      lifetime="Singleton"
                      myassembly.cache.mycustomprovider=""
                      servicetype="Sitecore.Core.Interfaces.Caching.ICacheManager,Sitecore.Core.I implementationType="
                      yassembly="">>
                    </register></services>
                </sitecore>
                
Use Multiple Caching Providers By Default the CacheManager uses DI to find out current caching provider from configuration. In case we need multiple providers we can instantiate the specific provider. Other Caching considerations for Sitecore application

HtmlCache: We have HtmlCache is the top level cache, sometimes call the web cache. This Cache caches the actual HTML generated from renderings or sublayouts. It is used to store the rendered Html from renderings and sublayouts. Unfortunately most of the solutions we’ve seen don’t use HTML caching at all and on top of that run with default data cache sizes, which can cause performance issues due to frequent cache clearing and fails to utilize server memory properly. Sitecore does not limit cache size growth and ignores any maximum cache sizes specified in the web.config file. Enabling this setting can improve the application’s performance in 64-bit environments by allowing Sitecore to take full advantage of the available memory. After setting this value to true, monitor the system at regular intervals, as this configuration can cause Sitecore to consume too much memory and cause Out Of Memory errors. It is only recommended to set the setting to true in 64-bit environments. When use this cache, make sure to select appropriate vary by parameters

CDN Cache: CDN cache is the cache which helps to serve anything from web page assets (CSS, java-script and media library items) to the page itself to the end users browser. All CDN provides PULL and PUSH mechanism to cache the data, PULL will allow edge server to pull the data from application server as per defined TTL and PUSH is the mechanism where we define when do we need to cache the item. The most important asset which needs more attention is your media item and for that we an have configuration to get the item from CDN network:


                <settings>
                  <setting name="MediaResponse.Cacheability">
                    <patch:attribute name="value">public</patch:attribute>
                  </setting>
                  <setting name="Media.AlwaysIncludeServerUrl">
                    <patch:attribute name="value">false</patch:attribute>
                  </setting>
                  <setting name="Media.MediaLinkServerUrl">
                    <patch:attribute name="value">https://SOMENAME.azureedge.net/</patch:attribute>
                  </setting>
                </settings>
                
We will require custom implementation for versioning and CDN path for media item and add the CDN Media provider in patch config

                <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
                  <sitecore>
                    <medialibrary>
                      <mediaprovider>
                        <patch:attribute name="type">YOURSOLUTIONNAMESPACE.Business.SC.Providers.CDNMediaProvider,
                          YOURSOLUTIONNAMESPACE.Busine
                        </patch:attribute></mediaprovider>
                    </medialibrary>
                 </sitecore>
                </configuration>
                
There are some Sitecore modules available for some of the CDN,we can leverage them also.

We can cache the glassmapper model Let's first do Configurations to enable GlassMapper of Foundation.GlassMapper Second step is to configure first Base Classes and Repository to Get glass object
How to use

  • 1. Add Reference to "Sitecore.Foundation.Glassmapper"
  • 2. It's good to create an Interface of your model implementing IGlassBase
  • 
                    [SitecoreType(AutoMap = true)]
                    public interface IMetaKeyword : IGlassBase
                    {
                    [SitecoreField("Keyword")]
                    string Keyword { get; set; }
    }
  • 3. Use DependencyInjection to inject IGlassRepository to your class.
  • 
                    readonly IGlassRepository repository;
                    public MetadataRepository(IGlassRepository repository)
                    {
                    this.repository = repository;
                    }
  • 4. Use repository method to get GlassModel from the Item

                MetaViewModel metaDataModel = new MetaViewModel();
                var metaDataItem = repository.GetCurrentItem();
                metaDataModel.MetaDataItem = metaDataItem;
                return metaDataItem;
Caching GlassModels Glass Mapper v4 comes with caching enabled to imporve the performance. We have implemented a custom Caching component with uses Foundation.Caching to cache glass models.

                public static IDependencyResolver CreateResolver()
                {
                var config = new Glass.Mapper.Sc.Config();
                var dependencyResolver = new DependencyResolver(config);
                dependencyResolver.CacheManager = () => new Extensions.Caching.CustomCacheManager();
                return dependencyResolver;
                }
To make a GlassModel cachable, make sure to do the followings
  • 1. Use Concrete Class Types instead of Interface types. (Interface type will work for inmemory cache but it might fail for redis caching)
  • instead of
     [SitecoreType(AutoMap = true)]
                      public interface IMetaKeyword : IGlassBase
                      {
                      [SitecoreField("Keyword")]
                      string Keyword { get; set; }
                      }
    use
     [SitecoreType(AutoMap = true)]
                      public class MetaKeyword : GlassBase
                      {
                      [SitecoreField("Keyword")]
                      public string Keyword { get; set; }
                      }
  • 2. Set the Cachable to true
  • [SitecoreType(AutoMap = true,Cachable=true)]
                      public class MetaKeyword : GlassBase
                      {
                      [SitecoreField("Keyword")]
                      public string Keyword { get; set; }
                      }
  • 3. Or we can user the [CachableSitecoreType] attribute
Glass Model Caching in Redis Using above configurations glassmodel can be cached in any caching providers. Caching Foundation component comes with On-Premise Redis Cache. Steps to enable redis Cache
  • 1. Install foundation component "Sitecore.Foundation.Caching.Redis".
  • 2. Install-Package Sitecore.Foundation.Caching.Redis
  • 3. Configure the redis cache provider in cache configuration.
 
                 <setting name="RedisHost" value="127.0.0.1"/>
                  <setting name="RedisPort" value="6379"/>
                 <setting name="RedisCacheTimeout" value="10"/>
                  <setting name="RedisIsSecured" value="false"/>
                  <setting name="RedisAccountKey" value="foobared"/>
                  
Foundation Caching component doesnot support Azure Redis Caching. We need to create custom caching to support that.
Extension We can implement the interface ICacheManager to use any custom caching implementation. Or Extend the Foundation.Caching component to provide custom caching.
Do's and Dont's
Cacheble attribute need to be specified in all models. In following example Metakeyword will not be cached even if its derievd from a cachable parent.
[SitecoreType(AutoMap = true,Cachable=true)]
                  public class GlassBase
                  {
                  [SitecoreField("Title")]
                  public string Title { get; set; }
                  }
                  [SitecoreType(AutoMap = true)]
                  public class MetaKeyword : GlassBase
                  {
                  [SitecoreField("Keyword")]
                  public string Keyword { get; set; }
                  }
When implementing a caching you should follow the following rules for you Glass models:
  • Ensure that all properties are serializable.
  • Turn off lazy loading, by default later versions of Glass will disable lazy load when a model is marked as cachable.
  • Don't create models that have large object graphs, since this will require a lot of data to be pulled from Sitecore and also a lot of data to be serialized which may affect performance.
  • When lazy loading is disable Glass will perform a depth check to try and limit the size of the object graph that gets created. This is limited to a depth of 8 at the moment, e.g myModel.Level2.Level3.Level4.Level5.Level6.Level7.Level8.
  • Certain custom datamappers may mean it isn't possible to cache a model.

Comments

Popular posts from this blog

Sitecore Site Creation: A Comparison of SXA and Headless SXA

  Objective: Are you thinking about using Sitecore for your website development? If so, you might be wondering whether to use Sitecore Experience Accelerator (SXA) or Headless SXA. In this post, we'll examine the differences between these two methods and help you determine which one is best for your project. Its totally depend on the business context and load model. To design your site using SXA: Sitecore SXA brings Sitecore in competition with other easy to use CMS with enterprise capability. SXA empowers teams to collaborate effectively, streamline website creation, and maintain brand consistency. Its flexibility and scalability make it an excellent choice for enterprise CMS solutions. Few of SXA core enterprise CMS capabilities are: Parallel Work Streams Responsive Grid Layouts Reusable Renderings and Components Themes for Brand Consistency Page Designs for Consistency and Flexibility Customizing Renderings with Variants   But what about Headless SXA? This approach is in hi...

Quickest way to setup Sitecore 10.1 Vanilla instance

Sitecore 10.1 Vanilla installation on Developer machine   Step 1. Install Visual studio 2019 Step 2. Install SQL server 2019 (Developer edition) Step 3. Copy all the setup files and tools at shared location with full rights   Step 4. Browse “Sitecore 10.1.1 rev. 005862 (Setup XP0 Developer Workstation rev. 1.2.3-r6)” folder and run setup.exe in admin mode Step 5. You should be able to see SIA installation screen, click on Start button to start installation Step 6. SIA complete the entire process in 3 parts, first part installed all required Sitecore 10.1 prerequisites. Step 7. Once Prerequisites are installed restart the development machine and open setup.exe again in admin mode (refer step #4). Once SIA will be started then don’t click on Install button again for “Prerequisites”, just click on Skip. Step 8. As I said in Step #6 that Sitecore does installation in three parts, so this is second parts where you will have to pass require parameter to setup sol...

Other aspects of HTML5

There is great feature embedded with HTML5 that is multimedia support without any plugin at end user.The best part of this tag is that it support wide range of quality audio/video format. The tags which we use for audio and video are: <audio> <video> The code snippet for same: <audio id=“audio” controls preload="auto" autobuffer>   <source src="source1.mp3" />   <source src=" source2.ogg" /> </audio> <video id=“video” poster=”poster.jpg" src=”source.mp4" width="2" height="1" x-webkit-airplay="allow” autoplay controls> </video> HTML5 is enriched with other input type tag which is having great ability to enrich the mobile interface,this input type tag along with Jquery UI plugin give them very strong presence on mobile where end user get very lucrative look and feel. <input type="number" pattern="[0-9]*" /> <input type=...