3

Sitecore 7.2 cache issue - we have a page that has a document list component on it.

The page is hit and shows the document list with abc title, the document in the media library gets updated to 123 title and published. The abc title will still appear on the page until a shift-refresh is done.

We have added meta tags to the layout to try and force (cache-control no-cache etc) but in the chrome dev tools the Status of the request in the Network tab is 304 instead of 200 - after the user does a shift-refresh the status is 200 and the updated doc title is displayed.

Any ideas on how to make Sitecore recognize that a component on the page has been changed and it should be a 200 instead of a 304 or worse case force a 200 status everytime?

2
  • I had an issue one related to ajax calls and back button. I fixed it by adding this to the layout @{ Response.Cache.SetCacheability(HttpCacheability.NoCache); // HTTP 1.1. Response.Cache.AppendCacheExtension("no-store, must-revalidate"); Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0. Response.AppendHeader("Expires", "0"); // Proxies. }
    – josedbaez
    Nov 3 '16 at 14:24
  • that worked - I will keep Richard's answer in mind when I want it to be more 'best practice' like - but for now I am just going to do the all-or-nothing approach because it is an intranet with limited traffic.
    – Colema18
    Nov 3 '16 at 15:03
3

You can disable browser caching by changing this setting in Sitecore to true:

<setting name="DisableBrowserCaching" value="true" />

BUT that really is not a good move to make, disabling the browser caching on clients will cause a higher load on your servers when most of the time, you don't need to do that.

What you need to do is work out your caching strategy and how long you want things like images to live in the clients browser cache. I normally use a sliding scale based on the age of the content/media item.

One thing to keep in mind, once the browser cache has been set, there is nothing you can do about it from the server!! The user will have to manually clear the browser cache to force an update.

A simple option would be to use the current context item to set the cache headers. Adding this processor to the renderLayout pipeline will do that:

public class BrowserCaching : RenderLayoutProcessor
{
    /// <summary>
    /// Set browser caching headers.
    /// 
    /// </summary>
    /// <param name="args">The arguments.</param>
    public override void Process(RenderLayoutArgs args)
    {
        Assert.ArgumentNotNull(args, "args");
        Profiler.StartOperation("Update browser caching headers.");
        var page = Context.Page;
        if (page?.Page == null)
        {
            return;
        }

        SetCacheHeaders(page.Page);
        if (Context.Item != null)
        {
            SetUpdateHeaders(Context.Item, page.Page);
        }
        Profiler.EndOperation();
    }

    /// <summary>
    /// Set caching related headers
    /// 
    /// </summary>
    /// <param name="page">The page.</param>
    private static void SetCacheHeaders(Page page)
    {
        if (Context.Site == null && !Settings.DisableBrowserCaching || Context.Site != null && !Context.Site.DisableBrowserCaching)
        {
            // TODO: Build a sliding scale here based on the age of the Context.Item

            page.Response.Cache.SetMaxAge(new TimeSpan(0, 0, 30));
            return;
        }
        Tracer.Info("Adding Http headers to disable caching.");
        page.Response.Cache.SetNoStore();
        page.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    }

    /// <summary>
    /// Set time-of-last-update headers
    /// 
    /// </summary>
    /// <param name="item">The item.</param><param name="page">The page.</param>
    private static void SetUpdateHeaders(Item item, Page page)
    {
        var date = item.Statistics.Updated;
        if (date > DateTime.Now)
        {
            date = DateTime.Now;
        }
        Tracer.Info("Adding Http header to indicate last modification.", "Date: " + date + ".");
        page.Response.Cache.SetLastModified(date);
    }
}

This code sets the max-age of the response and also sets the last modified date. Browsers should be able to use that to know when to expire the cached copy of the data. As for the sliding scale, you will need to work out what is best for your implementation. As a baseline, I keep young items, so 2-3 hours old or less at around 60 seconds max-age, and then grow that. If a media item is more than a week old, I'm setting the max age in days rather than seconds.

Obviously this example only does the current context item, so pages that have lots of Datasources may need to calculate it from the datasource and for media items you will need to add this to the media request pipelines.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.