Skip to content

Instantly share code, notes, and snippets.

@sotirisf
Last active September 9, 2020 18:42
Show Gist options
  • Select an option

  • Save sotirisf/f1e00b1e6e60ea619dcfa69dd4650ac9 to your computer and use it in GitHub Desktop.

Select an option

Save sotirisf/f1e00b1e6e60ea619dcfa69dd4650ac9 to your computer and use it in GitHub Desktop.
Umbraco Cached Nodes
using Umbraco.Core;
using Umbraco.Core.Composing;
namespace DotSee.Common
{
public class CachedNodesBuildersComposer : IUserComposer
{
public void Compose(Composition composition)
{
composition.Register<ICachedNodesBuilder, CachedNodesBuilder>(Lifetime.Request);
}
}
}
using DotSee.Common;
using System.Web.Mvc;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Web.PublishedModels;
namespace Site.Core
{
public static class CachedNodes
{
/*
The PageId parameter is optional and has meaning only when there is an AJAX request
(Where no AssignedContentItem exists).
When in an AJAX request, you MUST define the current page id for the CachedNodesBuilder to work.
*/
public static PageHome GetHomePage(int pageId = 0)
{
return GetNode<PageHome>(pageId);
}
public static ConfigGlobalSettings GetConfigNode(int pageId = 0)
{
return GetNode<ConfigGlobalSettings>(pageId);
}
public static ConfigScriptSettings GetScriptsNode(int pageId = 0)
{
return GetNode<ConfigScriptSettings>(pageId);
}
private static T GetNode<T>(int pageId) where T : class, IPublishedContent
{
return DependencyResolver.Current.GetService<ICachedNodesBuilder>().GetSingleCachedNode<T>(pageId);
}
}
}
using System.Collections.Generic;
using Umbraco.Core.Cache;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Web;
namespace DotSee.Common
{
public interface ICachedNodesBuilder
{
T GetSingleCachedNode<T>(int pageId = 0) where T : class, IPublishedContent;
IEnumerable<TChild> GetCachedNodeSet<TParent, TChild>(int pageId = 0) where TParent : class, IPublishedContent where TChild : class, IPublishedContent;
}
public class CachedNodesBuilder : ICachedNodesBuilder
{
private readonly IUmbracoContextFactory _context;
private readonly UmbracoHelper _c;
private readonly AppCaches _cache;
public CachedNodesBuilder(IUmbracoContextFactory context, UmbracoHelper c, AppCaches cache)
{
_context = context;
_c = c;
_cache = cache;
}
public T GetSingleCachedNode<T>(int pageId = 0) where T : class, IPublishedContent
{
//If you call this via an AJAX request WITHOUT a page ID, it'll throw an error
//("Can't return the IPublishedContent because the UmbracoHelper was not constructed with an IPublishedContent.")
//When using AJAX requests, you MUST pass a page id because there is no AssignedContentItem (this has a value only on normal
//front-end requests).
var pid = pageId != 0 ? pageId : _c.AssignedContentItem.Id;
T retVal = null;
using (var cnx = _context.EnsureUmbracoContext())
{
var currPage = cnx.UmbracoContext.Content.GetById(pid);
var cultureName = System.Threading.Thread.CurrentThread.CurrentUICulture.Name;
var rtc = _cache.RuntimeCache;
retVal = rtc
.GetCacheItem(CacheLiteralsCM.CachedNode + typeof(T).Name + currPage.AncestorOrSelf(1).Id.ToString() + cultureName,
() => currPage.AncestorOrSelf(1).DescendantOrSelf<T>(culture: cultureName));
}
return retVal;
}
public IEnumerable<TChild> GetCachedNodeSet<TParent, TChild>(int pageId = 0)
where TParent : class, IPublishedContent where TChild : class, IPublishedContent
{
var rtc = _cache.RuntimeCache;
var cultureName = System.Threading.Thread.CurrentThread.CurrentUICulture.Name;
//If you call this via an AJAX request WITHOUT a page ID, it'll throw an error
//("Can't return the IPublishedContent because the UmbracoHelper was not constructed with an IPublishedContent.")
//When using AJAX requests, you MUST pass a page id because there is no AssignedContentItem (this has a value only on normal
//front-end requests).
var pid = pageId != 0 ? pageId : _c.AssignedContentItem.Id;
IEnumerable<TChild> retVal = null;
using (var cnx = _context.EnsureUmbracoContext())
{
var currPage = cnx.UmbracoContext.Content.GetById(pid);
retVal = rtc
.GetCacheItem(CacheLiteralsCM.CachedNodes + typeof(TParent).Name + currPage.AncestorOrSelf(1).Id.ToString() + cultureName,
() => currPage.AncestorOrSelf(1).Descendant<TParent>(culture: cultureName).Children<TChild>(culture: cultureName));
}
return retVal;
}
}
}
namespace DotSee.Common
{
public static class CacheLiteralsCM
{
public static string CachedNodes => "cachednodesfor";
public static string CachedNode => "cachednodefor";
}
}
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
namespace DotSee.Common
{
public class SiteEventsCMComposer : IUserComposer
{
public void Compose(Composition composition)
{
composition.Components().Append<SubscribeToEventsCM>();
}
}
public class SubscribeToEventsCM : IComponent
{
private readonly IAppPolicyCache _cache;
public SubscribeToEventsCM(AppCaches cache)
{
_cache = cache.RuntimeCache;
}
public void Initialize()
{
ContentService.Published += ContentService_Published;
ContentService.Deleted += ContentService_Deleted;
ContentService.Copied += ContentService_Copied;
ContentService.Moved += ContentService_Moved;
ContentService.RolledBack += ContentService_RolledBack;
ContentService.Saved += ContentService_Saved;
ContentService.Publishing += ContentService_Publishing;
ContentService.Unpublished += ContentService_UnPublished;
ClearRuntimeCache();
}
public void Terminate()
{
}
private void ContentService_UnPublished(IContentService sender, PublishEventArgs<IContent> e)
{
ClearRuntimeCache();
}
private void ContentService_Publishing(IContentService sender, ContentPublishingEventArgs e)
{
ClearRuntimeCache();
}
private void ContentService_Saved(IContentService sender, ContentSavedEventArgs e)
{
ClearRuntimeCache();
}
private void ContentService_RolledBack(IContentService sender, RollbackEventArgs<IContent> e)
{
ClearRuntimeCache();
}
private void ContentService_Moved(IContentService sender, MoveEventArgs<IContent> e)
{
ClearRuntimeCache();
}
private void ContentService_Copied(IContentService sender, CopyEventArgs<IContent> e)
{
ClearRuntimeCache();
}
private void ContentService_Deleted(IContentService sender, DeleteEventArgs<IContent> e)
{
ClearRuntimeCache();
}
private void ContentService_Published(IContentService sender, PublishEventArgs<IContent> e)
{
ClearRuntimeCache();
}
private void ClearRuntimeCache()
{
_cache.ClearByKey(CacheLiteralsCM.CachedNodes);
_cache.ClearByKey(CacheLiteralsCM.CachedNode);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment