Skip to content

Instantly share code, notes, and snippets.

@dawoe
Created November 7, 2017 08:20
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save dawoe/f8d649c09f4f6341ea9630acbab44cf0 to your computer and use it in GitHub Desktop.
Save dawoe/f8d649c09f4f6341ea9630acbab44cf0 to your computer and use it in GitHub Desktop.
Donut Cache examples from Umbraco UK Festival talk "The need for speed"
public class DefaultController : RenderMvcController
{
[UmbracoDonutOutputCache(CacheProfile = "LongPageCache",
Options = OutputCacheOptions.NoCacheLookupForPosts &
OutputCacheOptions.ReplaceDonutsInChildActions, Order = 100)]
public override ActionResult Index(RenderModel model)
{
return base.Index(model);
}
}
public class Global : UmbracoApplication
{
public override string GetVaryByCustomString(HttpContext context, string custom)
{
var result = base.GetVaryByCustomString(context, custom);
if (string.IsNullOrEmpty(custom))
{
return result;
}
if (UmbracoContext.Current.IsFrontEndUmbracoRequest)
{
var keys = custom.Split(new[] { ";" }).ToList();
if (keys.Contains("url"))
{
result += $"pageid={UmbracoContext.Current.PageId};";
result += $"url={context.Request.Url}";
}
}
return result;
}
}
public class UmbracoDonutOutputCacheAttribute : DonutOutputCacheAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// overrides donut output cache attribute to not cache when in umbraco preview mode or Doctype grid editor preview
this.Duration = -1;
var previewMode = UmbracoContext.Current.InPreviewMode;
if (!previewMode)
{
if (UmbracoContext.Current.HttpContext.Request.QueryString["dtgePreview"] == "1")
{
previewMode = true;
}
}
if (previewMode)
{
this.Duration = 0;
}
base.OnActionExecuting(filterContext);
}
}
public class UmbracoStartup : ApplicationEventHandler
{
protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication,
ApplicationContext applicationContext)
{
DefaultRenderMvcControllerResolver.Current.
SetDefaultControllerType(typeof(DefaultController));
PageCacheRefresher.CacheUpdated += this.PageCacheRefresherCacheUpdated;
}
private void PageCacheRefresherCacheUpdated(PageCacheRefresher sender, CacheRefresherEventArgs e)
{
switch (e.MessageType)
{
case MessageType.RefreshById:
case MessageType.RemoveById:
var contentId = (int)e.MessageObject;
var doctype = string.Empty;
var item = UmbracoContext.Current.ContentCache.GetById(contentId);
if (item != null)
{
doctype = item.DocumentTypeAlias;
}
this.ClearPageOutputCache(contentId, doctype);
break;
case MessageType.RefreshByInstance:
case MessageType.RemoveByInstance:
var content = e.MessageObject as IContent;
if (content == null)
{
return;
}
this.ClearPageOutputCache(content.Id, content.ContentType.Alias);
break;
}
}
private void ClearPageOutputCache(int contentId, string doctype)
{
var enumerableCache = OutputCache.Instance as IEnumerable<KeyValuePair<string, object>>;
if (enumerableCache == null)
{
return;
}
// get all output cache keys that contain current page id
var keysToDelete = enumerableCache
.Where(x => !string.IsNullOrEmpty(x.Key) && x.Key.Contains($"pageid={contentId};"))
.Select(x => x.Key);
// remove all caches for current page
foreach (var key in keysToDelete)
{
OutputCache.Instance.Remove(key);
}
var manager = new OutputCacheManager();
manager.RemoveItems("MasterSurface","Footer");
if(doctype == "NewsDetail")
{
// clear cache of all news related actions
manager.RemoveItems("NewsSurface");
}
}
}
<system.web>
<caching>
<outputCache enableOutputCache="true" />
<outputCacheSettings>
<outputCacheProfiles>
<add name="LongGlobalCache" duration="86400" />
<add name="LongPageCache" duration="86400" varyByCustom="url" />
<add name="LongUserPageCache" duration="86400" varyByCustom="url;user" />
<add name="NoCache" duration="0" />
</outputCacheProfiles>
</outputCacheSettings>
</caching>
</system.web>
@JasonElkin
Copy link

JasonElkin commented Oct 10, 2019

varyByCustom="url;user" can cause cause problems when parsing cache keys as ; is the default delimiter for any other MVC routes that will also be stored in the key.

This will create a key that looks like this: url;user=pageid=1;url=/your-url;somethingelse=somethingelse; etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment