[VERY URGENT] - Sitefinity Cache Configuration - Front- & Back-End Development - Front- & Back-End Development - Progress Community
 Front- & Back-End Development

[VERY URGENT] - Sitefinity Cache Configuration

  • [VERY URGENT] - Sitefinity Cache Configuration
  • Hi,

    We have performance problems on our website (4.3.1885) in all of our environments. It may be partly be due to our cache configuration on Sitefinity, so we are in need of some explanations.

    In backend "Administration > Settings > Advanced > System > Output Cache Settings > Output Cache Profiles" we create our own caching like this :
    <outputCacheSettings>
       <profiles>
             <add enabled="True" duration="2700" slidingExpiration="False" maxSize="500" name="Insite Caching" />
       </profiles>
    </outputCacheSettings>

    But it seems that cache doesn't last 45 minutes, it expires before that. On top of that, it seems to be client specific: the page cache generated by one person doesn't benefit other persons, everyone generates their own page cache. On a given computer, the cache is not even shared between different browsers. Yet, from what we understand, this cache shouldn't be a client cache. Maybe we are misunderstanding something?
    Under "Output Cache Settings", there is "Output Cache Profiles" and "Client Cache Profiles". We expected the "Ouput Cache Profiles" to be server caches. Are they not?

    We also see differences between browsers: we need two page accesses on IE8 to generate the page cache, but only one on Firefox.

    In the configuration settings at the same place, we can reconfigure CacheManagers, but we don't know what to do and if it could help. Is this worth exploring this? If so, what could we do?

    Thanks in advance for your reactivity, as this problem is critical for us right now.

    Regards,
    Nicolas
  • Hi,

    Could a Sitefinity admin answer this question, or post a link to the documentation explaining everything we want to know about the cache?

    Thanks.
  • Hello,

    In general Sitefinity implements two types of caching - OutputCache through its Output cache settings and DataCache through its OpenAccess implementation. While the data cache is turned on my default and cannot be controlled directly by Sitefinity, OutputCache is available for fine tuning by user requirements.

    In backend "Administration > Settings > Advanced > System > Output Cache Settings > Output Cache Profiles" we create our own caching like this :
    <outputCacheSettings>
       <profiles>
             <add enabled="True" duration="2700" slidingExpiration="False" maxSize="500" name="Insite Caching" />
       </profiles>
    </outputCacheSettings>

    But it seems that cache doesn't last 45 minutes, it expires before that.
    Can you please make sure that this is the Default Output Cache Profile set for the entire site?

    On top of that, it seems to be client specific: the page cache generated by one person doesn't benefit other persons, everyone generates their own page cache. On a given computer, the cache is not even shared between different browsers.

    By default Sitefinity sets the output cache to vary by user agents. This is done so, because different browsers have different capabilities, and sometimes you will need to put browser specific HTML and CSS to resolve frontend issues. If you do not have such issues in your project you can manually set the caching headers by inhering from the RouteHandler which serves Sitefinity pages. Bellow are the steps that you need to do:

    1) Create a class which inherits from PageRouteHandler, and override the InitOutputCache method. This will give you control over the caching headers:
    using Telerik.Microsoft.Practices.Unity;
    using Telerik.Sitefinity.Abstractions;
    using Telerik.Sitefinity.Web;
      
      
    namespace SitefinityWebApp
        public class CustomPageRouteHandler: PageRouteHandler
        
            protected override void InitOutputCache(System.Web.Routing.RequestContext requestContext, PageSiteNode siteNode)
            
                base.InitOutputCache(requestContext, siteNode);
                var cache = requestContext.HttpContext.Response.Cache;
                 cache.VaryByHeaders.UserAgent = true;
            
      
            public static void RegisterType()
            
                ObjectFactory.Container.RegisterType<PageRouteHandler, CustomPageRouteHandler>();
            
        

    2) Create a Global Application class (Global.asax). There you will call the RegisterType method of the custom route handler to substitute the built in one with the custom one:
    protected void Application_Start(object sender, EventArgs e)
        Bootstrapper.Initialized += new EventHandler<Telerik.Sitefinity.Data.ExecutedEventArgs>(Bootstrapper_Initialized);
      
    void Bootstrapper_Initialized(object sender, Telerik.Sitefinity.Data.ExecutedEventArgs e)
        if (e.CommandName == "RegisterRoutes")
        
            CustomPageRouteHandler.RegisterType();
        

    3) Compile your project and run it

    IN addition, please check out the tips for optimizing performance: Tips for optimizing performance. We recommend that you verify that you have enabled caching throughout the site as well as make sure you have a machinekey set in the web.config and enabled static content expiration:
    staticContent>
      <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="14.00:00:00" />
    </staticContent>
    <urlCompression doDynamicCompression="true" doStaticCompression="true" dynamicCompressionBeforeCache="true" />

    if any problems persist  I'd recommend you contact us through the support ticketing system in order to benefit from the guaranteed response time we're offering there.

    Greetings,
    Boyan Barnev
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  • Hi,
    Thanks for your answer. We are testing your solution.

    I have a question about it, when we set clienCache MaxAge in web.config it's an  override of OutputCache original MaxAge value ?

    Regards,
    Nicolas
  • Hi,

    Thanks for your answer, Boyan, much appreciated.

    It's surprising that a user agent-based cache is the default, and that there is no simple flag to revert to a classic cache. By the way, as you know, many things can make the user agent vary (whether .NET 4.0 is installed, etc...), and in our company, IE8 users do not all have the same UA.

    Anyway, we do not serve browser-specific content. Does Sitefinity do it, with its components (like, say, the standard navigation menu), or does it serve the same HTML to everyone?

    Thanks.
  • Hi,

    Follow-up: we created a class derived from PageRouteHandler, as advised, in order to control the way caching works. However, we're encountering an unexpected problem: pages set to "No Caching" are now cached. I guess that in the code sample you showed, we were supposed to add a check for whether the page cache is enabled or not.

    Edit: our method now looks like this:

    protected override void InitOutputCache(System.Web.Routing.RequestContext requestContext, PageSiteNode siteNode)
        base.InitOutputCache(requestContext, siteNode);
     
        var config = Config.Get<SystemConfig>();
        if (config.CacheSettings.EnableOutputCache)
        
            var cacheProfile = siteNode.OutputCacheProfile;
            if (cacheProfile.IsNullOrEmpty())
            
                cacheProfile = config.CacheSettings.DefaultProfile;
            
     
            OutputCacheProfileElement profile;
            if (!config.CacheSettings.Profiles.TryGetValue(cacheProfile, out profile))
            
                throw new ArgumentException("Invalid output cache profile specified: \"0\".".Arrange(cacheProfile));
            
     
            if (profile.Enabled)
            
                var cache = requestContext.HttpContext.Response.Cache;
                cache.VaryByHeaders.UserAgent = false;
                cache.SetMaxAge(new TimeSpan(0, 0, 172800));
            
        
  • Hello Thomas,

    Can you please try adding an else clause where you'll set explicitly the Cacheability to None. Like this:
    var config = Config.Get<SystemConfig>();
                if (config.CacheSettings.EnableOutputCache)
                
                    var cacheProfile = siteNode.OutputCacheProfile;
                    if (cacheProfile.IsNullOrEmpty())
                    
                        cacheProfile = config.CacheSettings.DefaultProfile;
                    
     
                    OutputCacheProfileElement profile;
                    if (!config.CacheSettings.Profiles.TryGetValue(cacheProfile, out profile))
                    
                        throw new ArgumentException("Invalid output cache profile specified: \"0\".".Arrange(cacheProfile));
                    
     
                    if (profile.Enabled)
                    
                        var cache = requestContext.HttpContext.Response.Cache;
                        cache.VaryByHeaders.UserAgent = false;
                        cache.SetMaxAge(new TimeSpan(0, 0, 172800));
                    
                           
                else
                    requestContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);


    Greetings,
    Boyan Barnev
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  • Hi Boyan,

    Thanks for the info.
    By the way, our updated method already worked for our case. I guess your update helps if we disable the cache for the whole site, as opposed to disabling the cache for certain pages, so we'll add this bit of code.

    I was wondering whether we should also add the same no cache instruction in a else for the profile.Enabled. That is to say:

    if (profile.Enabled)
        var cache = requestContext.HttpContext.Response.Cache;
        cache.VaryByHeaders.UserAgent = false;
        cache.SetMaxAge(new TimeSpan(0, 0, 172800));
    else
        requestContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);

    What do you think?
  • Hello,

    Yes that should do, or you could just say:
    if (config.CacheSettings.EnableOutputCache)
               
                   .
                   .
                   .
     
                   if (!profile.Enabled)
                       return;
     
                 .
                 .
                 .
     
                   //if output cache is enabled set flag to add cache dependencies
                   requestContext.HttpContext.Items[PageRouteHandler.AddCacheDependencies] = true;
               
               else
                   requestContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);


    Greetings,
    Boyan Barnev
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  • Hi Boyan,

    So I don't need to call Cache.SetCacheability(HttpCacheability.NoCache); explicitly there? Okay.
    I added the AddCacheDependencies instruction, although I'm not sure what it does exactly, and I can't find any documentation for it.

    This is our method now:

    protected override void InitOutputCache(System.Web.Routing.RequestContext requestContext, PageSiteNode siteNode)
        base.InitOutputCache(requestContext, siteNode);
     
        var config = Config.Get<SystemConfig>();
        if (!config.CacheSettings.EnableOutputCache)
        
            requestContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        
        else
        
            var cacheProfile = siteNode.OutputCacheProfile;
            if (cacheProfile.IsNullOrEmpty())
            
                cacheProfile = config.CacheSettings.DefaultProfile;
            
     
            OutputCacheProfileElement profile;
            if (!config.CacheSettings.Profiles.TryGetValue(cacheProfile, out profile))
            
                throw new ArgumentException("Invalid output cache profile specified: \"0\".".Arrange(cacheProfile));
            
     
            if (profile.Enabled)
            
                var cache = requestContext.HttpContext.Response.Cache;
                cache.VaryByHeaders.UserAgent = false;
                cache.SetMaxAge(new TimeSpan(0, 0, 172800));
                requestContext.HttpContext.Items[PageRouteHandler.AddCacheDependencies] = true;
            
        
  • Hello,

    By default we add dependency on a page site node cache key, so when page site node is invalidated (e.g. Publish) the output cache key of the page should be refreshed.

    All the best,
    Boyan Barnev
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  • Hi Boyan,

    I just noticed something else that I do not understand: pages set no "No Caching" are still cached (whether we override the InitOutputCache method or not). If I modify the content of a page set to No Caching, I cannot see the changes on other servers where the site is deployed. I can only see the changes on the server from which the modification has been done (until the site is restarted on the other servers). Although I haven't configured load balancing, so other servers aren't informed the page has been modified, shouldn't I see the changes on the page considering both the data and page caches are disabled?

    I also want to add that we have not changed the "No Caching" profile settings at all, it's the default, unaltered one.
  • We are seeing the same issue: with two separate SF 4.3 instances that share a database, content changes made on one instance are not visible on the other. This is even with global output caching disabled, data caching set to "False", and page-level cache set to "No Caching".

    What are we missing? Why does Sitefinity not bypass the cache if the page is set to no caching?

    This is a very urgent issue for us.

    Regards,
    John Gassman
  • John, did you ever find a solution for this? Running into the same problem for us.