Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stop EPiServer clearing output cache on publish

This isn't a question I've seen around, usually it's 'EPiServer isn't clearing the output cache'. I'm trying to achieve the opposite. Each time a page is published the entire cache is dropped and as the client publishes several times a day, this is frustrating.

I'm using the [ContentOutputCache] attribute and tried to implement a httpCacheVaryByCustom rule with an accompanying scheduled task in EPiServer to invalidate the cache when we decide to i.e. bundle updates together and invalidate at a predetermined time.

I've tested this rule and it works using:

public override string GetVaryByCustomString(HttpContext context, string custom)

I was under the impression that by using this type of caching rule it would stop EPiServer dumping my cache whenever something is published / media uploaded.

It doesn't though is there a way to stop this from happening?

I've had success by using the standard [OutputCache] with the same custom string rule the only problem with this is that editors will always see a cached version of the page they are editing.

The application settings I have in my web.config for EPiServer are:

<applicationSettings globalErrorHandling="Off" operationCompatibility="DynamicProperties" uiSafeHtmlTags="b,i,u,br,em,strong,p,a,img,ol,ul,li" disableVersionDeletion="false" 
                     httpCacheability="Public" uiEditorCssPaths="~/assets/css/styles.css, ~/assets/css/editor.css" urlRebaseKind="ToRootRelative" 
                     pageUseBrowserLanguagePreferences="false" uiShowGlobalizationUserInterface="false" subscriptionHandler="EPiServer.Personalization.SubscriptionMail,EPiServer" 
                     uiMaxVersions="20" pageValidateTemplate="false" utilUrl="~/util/" 
                     uiUrl="~/EPiServer/CMS/" httpCacheExpiration="01:00:00"  httpCacheVaryByCustom="invalidateSiteCache" />
like image 203
Daniel Pickford Avatar asked May 11 '16 17:05

Daniel Pickford


1 Answers

A custom GetVaryByCustomString function will determine when the cache is invalidated, but any request for content that is using the ContentOutputCache is checked against a master cache key Episerver.DataFactoryCache.Version. This version number is incremented any time content is published, updated etc, and the cache is invalidated if the version number is changed.

To understand what you need to do, I recommend using a decompiler (e.g. DotPeek) and looking at the ContentOutputCacheAttribute and OutputCacheHandler classes in the Episerver dll.

You will need to:

  1. Derive a new handler from EPiServer.Web.OutputCacheHandler
  2. Create an alternative method to ValidateOutputCache(...) that still calls OutputCacheHandler.UseOutputCache(...) but ignores the cache version number
  3. Derive a new attribute from ContentOutputCacheAttribute
  4. Override the method OnResultExecuting(ResultExecutingContext filterContext) using the same logic as the current method (this is where a decompiler is useful), but that adds a callback to your new validate method instead of the current one. Unfortunately we can't inject the new handler because the validate method is passed statically.

e.g.

public override void OnResultExecuting(ResultExecutingContext filterContext)
{        
    // Rest of method
    filterContext.HttpContext.Response.Cache.AddValidationCallback(new HttpCacheValidateHandler(CustomOutputCacheHandler.CustomValidateOutputCache), (object) tuple);
}
  1. Use the new attribute in place of [ContentOutputCache]
like image 183
Electric Sheep Avatar answered Sep 21 '22 12:09

Electric Sheep