-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #36 from marcemarc/feature/UmbracoCacheTagHelper
Add some sort of implementation of a Preview/Debug aware CacheTagHelper
- Loading branch information
Showing
6 changed files
with
234 additions
and
0 deletions.
There are no files selected for viewing
22 changes: 22 additions & 0 deletions
22
Our.Umbraco.TagHelpers/Composing/CacheTagHelperComposer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Our.Umbraco.TagHelpers.Notifications; | ||
using Our.Umbraco.TagHelpers.Services; | ||
using Umbraco.Cms.Core.Composing; | ||
using Umbraco.Cms.Core.DependencyInjection; | ||
using Umbraco.Cms.Core.Notifications; | ||
|
||
namespace Our.Umbraco.TagHelpers.Composing | ||
{ | ||
public class CacheTagHelperComposer : IComposer | ||
{ | ||
// handle refreshing of content/media/dictionary cache notification to clear the cache key used for the CacheTagHelper | ||
public void Compose(IUmbracoBuilder builder) | ||
{ | ||
builder.Services.AddSingleton<IUmbracoTagHelperCacheKeys, UmbracoTagHelperCacheKeys>(); | ||
|
||
builder.AddNotificationHandler<ContentCacheRefresherNotification, CacheTagRefresherNotifications>(); | ||
builder.AddNotificationHandler<MediaCacheRefresherNotification, CacheTagRefresherNotifications>(); | ||
builder.AddNotificationHandler<DictionaryCacheRefresherNotification, CacheTagRefresherNotifications>(); | ||
} | ||
} | ||
} |
55 changes: 55 additions & 0 deletions
55
Our.Umbraco.TagHelpers/Notifications/CacheRefresherNotifications.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
using Microsoft.AspNetCore.Mvc.TagHelpers; | ||
using Microsoft.Extensions.Caching.Memory; | ||
using Our.Umbraco.TagHelpers.Services; | ||
using Umbraco.Cms.Core.Events; | ||
using Umbraco.Cms.Core.Notifications; | ||
|
||
namespace Our.Umbraco.TagHelpers.Notifications | ||
{ | ||
/// <summary> | ||
/// For Use with the Our Cache TagHelper | ||
/// We handle the published cache updating notification for content, media and dictionary | ||
/// And then use our dictionary collection of tracked tag helper caches, created in the tag cache helper | ||
/// loop through each one and clear the tag helpers cache | ||
/// </summary> | ||
public class CacheTagRefresherNotifications : | ||
INotificationHandler<ContentCacheRefresherNotification>, | ||
INotificationHandler<DictionaryCacheRefresherNotification>, | ||
INotificationHandler<MediaCacheRefresherNotification> | ||
{ | ||
|
||
private IMemoryCache _memoryCache; | ||
|
||
private IUmbracoTagHelperCacheKeys _cacheKeys; | ||
|
||
public CacheTagRefresherNotifications(CacheTagHelperMemoryCacheFactory cacheFactory, IUmbracoTagHelperCacheKeys cacheKeys) | ||
{ | ||
_memoryCache = cacheFactory.Cache; | ||
_cacheKeys = cacheKeys; | ||
} | ||
|
||
public void Handle(ContentCacheRefresherNotification notification) => ClearUmbracoTagHelperCache(); | ||
|
||
public void Handle(DictionaryCacheRefresherNotification notification) => ClearUmbracoTagHelperCache(); | ||
|
||
public void Handle(MediaCacheRefresherNotification notification) => ClearUmbracoTagHelperCache(); | ||
|
||
private void ClearUmbracoTagHelperCache() | ||
{ | ||
// Loop over items in dictionary | ||
foreach (var item in _cacheKeys.CacheKeys) | ||
{ | ||
// The value stores the CacheTagKey object | ||
// Looking at src code from MS TagHelper that use this object itself as the key | ||
|
||
// Remove item from IMemoryCache | ||
_memoryCache.Remove(item.Value); | ||
} | ||
|
||
// Once all items cleared from IMemoryCache that we are tracking | ||
// Clear the dictionary out | ||
// It will fill back up once an <our-cache> TagHelper is called/used on a page | ||
_cacheKeys.CacheKeys.Clear(); | ||
} | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
Our.Umbraco.TagHelpers/Services/IUmbracoTagHelperCacheKeys.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
using Microsoft.AspNetCore.Mvc.TagHelpers.Cache; | ||
using System.Collections.Generic; | ||
|
||
namespace Our.Umbraco.TagHelpers.Services | ||
{ | ||
public interface IUmbracoTagHelperCacheKeys | ||
{ | ||
Dictionary<string, CacheTagKey> CacheKeys { get; } | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
Our.Umbraco.TagHelpers/Services/UmbracoTagHelperCacheKeys.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
using Microsoft.AspNetCore.Mvc.TagHelpers.Cache; | ||
using System.Collections.Generic; | ||
|
||
namespace Our.Umbraco.TagHelpers.Services | ||
{ | ||
/// <summary> | ||
/// used to retain a list of hashed cache tag helper keys that have been created using the our cache tag helper | ||
/// and which need to be cleared when a publish notification takes place. | ||
/// </summary> | ||
public class UmbracoTagHelperCacheKeys : IUmbracoTagHelperCacheKeys | ||
{ | ||
public Dictionary<string,CacheTagKey> CacheKeys { get; } = new Dictionary<string,CacheTagKey>(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
using Microsoft.AspNetCore.Mvc.TagHelpers; | ||
using Microsoft.AspNetCore.Mvc.TagHelpers.Cache; | ||
using Microsoft.AspNetCore.Razor.TagHelpers; | ||
using Our.Umbraco.TagHelpers.Services; | ||
using System.Text.Encodings.Web; | ||
using System.Threading.Tasks; | ||
using Umbraco.Cms.Core; | ||
using Umbraco.Cms.Core.Web; | ||
|
||
namespace Our.Umbraco.TagHelpers | ||
{ | ||
/// <summary> | ||
/// A wrapper around .net core CacheTagHelper, that is Umbraco Aware - so won't cache in Preview or Debug Mode | ||
/// And will automatically clear it's when anything is published (optional) | ||
/// </summary> | ||
[HtmlTargetElement("our-cache")] | ||
public class UmbracoCacheTagHelper : CacheTagHelper | ||
{ | ||
private readonly IUmbracoContextFactory _umbracoContextFactory; | ||
private readonly IUmbracoTagHelperCacheKeys _cacheKeys; | ||
|
||
/// <summary> | ||
/// Whether to update the cache key when any content, media, dictionary item is published in Umbraco. | ||
/// </summary> | ||
public bool UpdateCacheOnPublish { get; set; } = true; | ||
|
||
public UmbracoCacheTagHelper(CacheTagHelperMemoryCacheFactory factory, | ||
HtmlEncoder htmlEncoder, | ||
IUmbracoContextFactory umbracoContextFactory, | ||
IUmbracoTagHelperCacheKeys cacheKeys) | ||
: base(factory, htmlEncoder) | ||
{ | ||
_umbracoContextFactory = umbracoContextFactory; | ||
_cacheKeys = cacheKeys; | ||
} | ||
|
||
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) | ||
{ | ||
using (UmbracoContextReference umbracoContextReference = _umbracoContextFactory.EnsureUmbracoContext()) | ||
{ | ||
var umbracoContext = umbracoContextReference.UmbracoContext; | ||
|
||
// we don't want to enable the cache tag helper if Umbraco is in Preview, or in Debug mode | ||
if (umbracoContext.InPreviewMode || umbracoContext.IsDebug) | ||
{ | ||
// Set the enabled flag to false & let base class | ||
// of the cache tag helper do the disabling of the cache | ||
this.Enabled = false; | ||
} | ||
else | ||
{ | ||
// Now whenever anything is published in Umbraco 'the old Umbraco Cache Helper convention' was to clear out all the view memory caches | ||
// we want to do the same by default for this tag helper | ||
// we can't track by convention as dot net tag helper cache key is hashed - but we can generte the hash key here, and add it to a dictionary | ||
// which we can loop through when the Umbraco cache is updated to clear the tag helper cache. | ||
// you can opt out of this by setting update-cache-on-publish="false" in the individual tag helper | ||
if (UpdateCacheOnPublish) | ||
{ | ||
// The base TagHelper would generate it's own CacheTagKey to create a unique hash | ||
// but if we call it here 'too' it will fortunately be the same hash. | ||
// so we can keep track of it & put into some dictionary or collection | ||
// and clear all items out in that collection with our notifications on publish | ||
var cacheKey = new CacheTagKey(this, context); | ||
var key = cacheKey.GenerateKey(); | ||
var hashedKey = cacheKey.GenerateHashedKey(); | ||
_cacheKeys.CacheKeys.TryAdd(key, cacheKey); | ||
} | ||
} | ||
|
||
await base.ProcessAsync(context, output); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters