Reputation: 1646
Adding output caching to all Sitecore MVC
view renderings on a layout is possible, however code in .cshtml
of the layout itself is always executed. Is there any way to apply OutputCache
to layout razor views? It would be huge waste if it wasn's possible
Upvotes: 2
Views: 2968
Reputation: 335
Sitecore applies caching on the MVC Renderings with the help of processors defined in the mvc.renderRendering pipeline.
SetCacheability
processor detects whether caching should be enabled based on the caching rendering parameters of the rendering and the site context.
GenerateCacheKey
processor generates the cache key based on the caching rendering parameters of the rendering.
RenderFromCache
processor responds with a cached output if it finds one for the given cache key.
Finally, there is AddRecordedHtmlToCache
that caches the output when a cacheable rendering is rendered.
How page level caching can be enabled (tested on Sitecore 8.2 Update 4)
Let's assume that the Sitecore items representing pages inherit from a template named Base page
Add to the base templates of Base page the Caching template {E8D2DD19-1347-4562-AE3F-310DC0B21A6C}
located at /sitecore/templates/System/Layout/Sections/Caching
.
Each Sitecore page item that inherits from Base page now has access to the same caching fields than the renderings.
The idea is to add a new processor before SetCacheability
.
This processor detects layout
rendering types.
If the associated Sitecore item has caching enabled, it will copy the caching definition to this rendering.
Code for this processor (it uses Glass Mapper but it is trivial to change):
public class SetPageCaching : RenderRenderingProcessor
{
public SetPageCaching() { }
ISitecoreContext GetSitecoreContext() => SitecoreContextFactory.Default?.GetSitecoreContext();
public override void Process(RenderRenderingArgs args)
{
if (IsPageRendering(args.Rendering) && args.Rendering?.Item != null)
{
var caching = GetSitecoreContext()?.Cast<ICaching>(args.Rendering.Item);
// the cast above always returns an item even if the item doesn't inherit the Caching template
// we check Cacheable property to verify if it has been mapped.
// Value of false for Cacheable property means that
// the item doesn't inherit the "Caching" template or Cacheable prop value is false
// we only do something for page items that are marked as cacheable
if (caching?.Cacheable ?? false)
{
UpdateRenderingCachingDefinition(caching, args.Rendering.Caching);
}
}
}
static bool IsPageRendering(Rendering rendering) => rendering?.RenderingType == RenderingTypes.Layout;
static void UpdateRenderingCachingDefinition(ICaching caching, RenderingCachingDefinition def)
{
if (caching == null || def == null) return;
def.Cacheable = caching.Cacheable;
def.VaryByData = caching.VaryByData;
def.VaryByDevice = caching.VaryByDevice;
def.VaryByLogin = caching.VaryByLogin;
def.VaryByParameters = caching.VaryByParam;
def.VaryByUser = caching.VaryByUser;
}
}
[SitecoreType(AutoMap = true, TemplateId = "{E8D2DD19-1347-4562-AE3F-310DC0B21A6C}")]
public interface ICaching
{
[SitecoreField(FieldId = "{3D08DB46-2267-41B0-BC52-BE69FD618633}")]
bool Cacheable { get; set; }
[SitecoreField(FieldId = "{F3E7E552-D7C8-469B-A150-69E4E14AB35C}")]
bool ClearOnIndexUpdate { get; set; }
[SitecoreField(FieldId = "{8B6D532B-6128-4486-A044-CA06D90948BA}")]
bool VaryByData { get; set; }
[SitecoreField(FieldId = "{C98CF969-BA71-42DA-833D-B3FC1368BA27}")]
bool VaryByDevice { get; set; }
[SitecoreField(FieldId = "{8D9232B0-613F-440B-A2FA-DCDD80FBD33E}")]
bool VaryByLogin { get; set; }
[SitecoreField(FieldId = "{3AD2506A-DC39-4B1E-959F-9D524ADDBF50}")]
bool VaryByParam { get; set; }
[SitecoreField(FieldId = "{0E54A8DC-72AD-4372-A7C7-BB4773FAD44D}")]
bool VaryByUser { get; set; }
}
Configuration to add this processor in the mvc pipeline (change MyAssembly.SetPageCaching, MyAssembly
with your own type):
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
<sitecore>
<pipelines>
<mvc.renderRendering>
<processor type="MyAssembly.SetPageCaching, MyAssembly" patch:before="processor[@type='Sitecore.Mvc.Pipelines.Response.RenderRendering.SetCacheability, Sitecore.Mvc']" />
</mvc.renderRendering>
</pipelines>
</sitecore>
</configuration>
Upvotes: 0
Reputation: 17000
You can only cache Renderings (View Renderings or Controller Renderings) in Sitecore MVC, for which caching options can be set in the Caching
section of the rendering definition item or in the Presentation Details when the control is added.
It is not possible to cache the Layouts (located under /sitecore/layout/Layouts
). The layouts are akin to View Master Pages, and therefore need to execute on every request in order to load the necessary controls.
If there are parts of the page you need to cache (and therefore not execute on every request) then dynamically bind it and set the the caching options (you can set this on the standard values of a base template). You can cache several controls at once by nesting them and then setting the caching on a control at a higher level, since the HTML for the entire set of controls is cached in a single entry.
Or if code needs to be present on every page then and you feel it needs to be cached then you can statically bind the renderings from the .cshtml and also set the caching options at the same time:
@Html.Sitecore().Rendering("{rendering-guid}", new { Cacheable = true })
You can find more information in this post about Specify datasource item of a statically binded rendering
Upvotes: 2
Reputation: 2047
Based on comments around the community applying OutputCache to Razor Views won't be added by Sitecore.
However you could create a custom Cache based on the OutputCache and extend it yourself to potentially include layout Razor views.
This blog outlines how you could create a new 'Vary by ...' HTML cache option. If you scroll down to the Custom Cache Key Generator section he outlines the resolution is to override the GenerateCacheKeyprocessor.
His article is relating about caching data from external source but will give you the right guidance.
http://www.lightmaker.com/news/sitecore/sitecore-mvc-custom-caching-vary-by-external-data/
Upvotes: 0