Kentico 12 MVC Caching

Geo Neeliyara asked on October 23, 2020 13:52

Hi,

I created a menu controller with cache. I have the outputcachedependency set to PrimaryMenu and it is working fine. But I want to include Secondary Menu to the outputcachedependency

Is that possible to add Primany Menu and its children to Cachedependency. do you have any examples for this?

Regards, Geo

Recent Answers


Sean Wright answered on October 31, 2020 18:08

Geo,

Can you provide some sample code to show how you are setting your Output Cache Dependencies?

The official docs show how to set a cache dependency for output cache.

You can set as many cache dependencies as you want for a given Page.

The docs also have the cache dependency string patterns that Xperience uses. You can generate these programatically in your code if you need dynamic dependency values.

0 votesVote for this answer Mark as a Correct answer

Geo Neeliyara answered on November 1, 2020 21:12

Hi Sean,

I build the cache service based on MedioClinic website.

please see the code for cacheservice.cs

using System;
using System.Web;
using Business.Services.Context;
using CMS.Helpers;

namespace Business.Services.Cache
{
    public class CacheService : ICacheService
    {
        public ISiteContextService SiteContextService { get; }

        // Injects a service which holds the site name and current culture code name
        public CacheService(ISiteContextService siteContextService)
        {
            SiteContextService = siteContextService;
        }

        // Returns a dummy cache key for pages ("nodes") in the content tree
        // "nodes|<site name>|<generated class name>|< type of cached data >"
        // which is touched when pages are modified
        public string GetNodesCacheDependencyKey(string className, CacheDependencyType dependencyType)
        {
            return $"nodes|{SiteContextService.SiteName}|{className}|{dependencyType}".ToLowerInvariant();
        }

        // Returns a dummy cache key for a page ("node") in the content tree identified by its "NodeGuid"
        // "nodeguid|<site name>| <given node in the content tree>"
        // which is touched when the page is modified
        public string GetNodeCacheDependencyKey(Guid nodeGuid)
        {
            return $"nodeguid|{SiteContextService.SiteName}|{nodeGuid}".ToLowerInvariant();
        }

        public void SetOutputCacheDependency(Guid nodeGuid)
        {
            var dependencyCacheKey = GetNodeCacheDependencyKey(nodeGuid);

            // Ensures that the dummy key cache item exists
            CacheHelper.EnsureDummyKey(dependencyCacheKey);

            // Sets cache dependency to clear the cache when there is any change to node with given GUID in Kentico
            HttpContext.Current.Response.AddCacheItemDependency(dependencyCacheKey);
        }

        public void SetOutputCacheDependency(string className)
        {
            var dependencyCacheKey = GetNodesCacheDependencyKey(className, CacheDependencyType.All);
            CacheHelper.EnsureDummyKey(dependencyCacheKey);
            HttpContext.Current.Response.AddCacheItemDependency(dependencyCacheKey);
        }

        public void SetOutputCacheDependencyByAliasPath(string aliasPath)
        {
            var dependencyCacheKey = $"nodes|{SiteContextService.SiteName}|{aliasPath}|childnodes".ToLowerInvariant();
            CacheHelper.EnsureDummyKey(dependencyCacheKey);
            HttpContext.Current.Response.AddCacheItemDependency(dependencyCacheKey);
        }

        public TData Cache<TData>(Func<TData> dataLoadMethod, int cacheForMinutes, string cacheName, string cacheDependencyKey) 
        {
            var cacheSettings = new CacheSettings(cacheForMinutes, cacheName, SiteContextService.SiteName, SiteContextService.CurrentSiteCulture)
            {
                GetCacheDependency = () => CacheHelper.GetCacheDependency(cacheDependencyKey.ToLowerInvariant())
            };

            return CacheHelper.Cache(dataLoadMethod, cacheSettings);
        }
    }
}

I have the menu controller as per below

using System;
using System.Linq;
using System.Web.Mvc;
using System.Web.UI;
using Business.Repository.Menu;
using Business.Services.Cache;
using CMS.DocumentEngine.Types.ITM;

namespace ITM.Controllers
{
    public class MenuController : Controller
    {
        private readonly ICacheService _cacheService;
        private readonly IMenuRepository _menuRepository;

        public MenuController(IMenuRepository menuRepository, ICacheService cacheService)
        {
            _menuRepository = menuRepository ?? throw new ArgumentNullException(nameof(menuRepository));
            _cacheService = cacheService ?? throw new ArgumentNullException(nameof(cacheService));
        }

        [OutputCache(Duration = 600, VaryByParam = "none")]
        public ActionResult Index()
        {
            var model = _menuRepository.GetMenuItems().ToList();
            //_cacheService.SetOutputCacheDependency(PrimaryMenu.CLASS_NAME);
            _cacheService.SetOutputCacheDependencyByAliasPath("/Menu");
            return PartialView("~/Views/Menu/Index.cshtml", model);
        }

    }
}

Please see the below for menu section on admin site. I just want to make sure outputcache works if i make any changes on primary and sub section.

site

-- Menu

----Primary Menu1

------Sub Menu 1

------Sub Menu 2

----Primary Menu2

------Sub Menu 1

------Sub Menu 2

If you have any queries, please let me know.

0 votesVote for this answer Mark as a Correct answer

   Please, sign in to be able to submit a new answer.