【问题标题】:How to cache .cshtml layout in Sitecore MVC?如何在 Sitecore MVC 中缓存 .cshtml 布局?
【发布时间】:2015-04-19 12:25:20
【问题描述】:

可以为布局上的所有Sitecore MVC 视图渲染添加输出缓存,但是始终执行布局本身的.cshtml 中的代码。有什么方法可以将OutputCache 应用于布局剃刀视图?如果可能的话,那将是巨大的浪费

【问题讨论】:

  • 您的视图渲染是从 Sitecore 外部使用的,还是实际添加为 Sitecore 中“布局”部分的渲染(然后您通过演示详细信息/页面编辑器添加)?
  • 作为渲染添加的那些被缓存得很好,我们不能缓存的是布局渲染(.chstml 的路径在布局项的“数据”部分设置)。

标签: asp.net-mvc sitecore outputcache sitecore-mvc


【解决方案1】:

您只能在 Sitecore MVC 中缓存渲染(视图渲染或控制器渲染),可以在渲染定义项的Caching 部分或添加控件时在 Presentation Details 中设置缓存选项。

无法缓存布局(位于/sitecore/layout/Layouts 下)。布局类似于查看母版页,因此需要在每个请求上执行以加载必要的控件。

如果您需要缓存页面的某些部分(因此不会在每个请求上执行),然后动态绑定它并设置缓存选项(您可以在基本模板的标准值上进行设置)。您可以通过嵌套多个控件来一次缓存多个控件,然后在更高级别的控件上设置缓存,因为整个控件集的 HTML 都缓存在单个条目中。

或者,如果代码需要出现在每个页面上,并且您觉得需要对其进行缓存,那么您可以静态绑定 .cshtml 中的渲染并同时设置缓存选项:

@Html.Sitecore().Rendering("{rendering-guid}", new { Cacheable = true })

你可以在这篇文章中找到更多关于Specify datasource item of a statically binded rendering的信息

【讨论】:

  • “无法缓存布局(位于 /sitecore/layout/Layouts 下)。”这不是真的,缓存配置参考说它可以使用 aspx 布局:“要指示 Web 客户端缓存整个页面,请将 DisableBrowserCaching 设置为 false,并在布局和子布局中使用 ASP.NET OutputCache 指令”。很明显,这是 Razor 视图的遗漏。 Sitecore 决定是否应该缓存布局是没有意义的 - 这取决于具体情况,在大多数情况下,评估每个请求的整个布局完全是浪费 CPU 时间。
  • 公平地说,我不知道那个设置。但是我从来没有遇到过缓存整个页面的用例,主要是因为我所做的一切都有一些动态内容的元素。该设置在 Webforms 场景中更没有意义,其中通常使用代码隐藏将事件绑定在一起。就像我说的那样,将所有控件封装在一个渲染中(其中可能包含一个占位符来放置所有控件),并且您可以有效地将整个页面缓存在 Sitecore HTML 缓存中。
  • 感谢您的回复。我同意这通常不会成功,但我们正在努力变得更聪明,并且我们正在通过单独的 ajax 调用下载所有个性化部分(用户头像、状态等)。因此,我们能够非常积极地缓存最重的元素(具有整个布局的主页)(即使在浏览器中使用 max-age 10 分钟),并且只需下载带有个性化信息的小 json,性能要高得多。它在纯 MVC 中工作得非常好,性能非常高。我非常推荐这种方法,不幸的是,如果没有对缓存的完全控制,我们就无法做到。
  • 可能是整个父占位符周围的 Sitecore HTML 缓存和使用适当值设置您自己的 HTTP 标头的组合。查看renderLayout 中的Sitecore.Pipelines.RenderLayout.BrowserCaching 处理器,然后在此之后添加您自己的处理器。可能不如纯 MVC 快,但希望更好。
  • 实际上,我认为 DisableBrowserCaching 甚至没有考虑到 MVC,上面的管道没有被击中,因为它是用于 WebForms 的,而且在 MVC 中似乎没有等价物:(你可能需要连接到mvc.requestEnd 管道来设置您自己的标头或在 IIS 中设置它们
【解决方案2】:

基于社区中的 cmets 将 OutputCache 应用于 Razor 视图不会被 Sitecore 添加。

但是,您可以基于 OutputCache 创建自定义缓存并自行扩展它以可能包含布局 Razor 视图。

本博客概述了如何创建新的“按...变化”HTML 缓存选项。如果您向下滚动到 Custom Cache Key Generator 部分,他概述了解决方案是覆盖 GenerateCacheKeyprocessor。

他的文章是关于从外部来源缓存数据的,但会给你正确的指导。

http://www.lightmaker.com/news/sitecore/sitecore-mvc-custom-caching-vary-by-external-data/

【讨论】:

  • 如果剃刀视图是 sitecore MVC 中视图渲染的一部分,那么它们已经可以缓存,对吧?它可以在演示详细信息上设置(因此在剃刀文件本身之外)。所以问题在于布局文件本身没有这样的设置。
【解决方案3】:

Sitecore 在 mvc.renderRendering 管道中定义的处理器的帮助下对 MVC 渲染应用缓存。

SetCacheability处理器根据渲染的缓存渲染参数和站点上下文检测是否应该启用缓存。

GenerateCacheKey处理器根据渲染的缓存渲染参数生成缓存key。

RenderFromCache 处理器如果找到给定缓存键的缓存输出,则会以缓存输出进行响应。

最后,AddRecordedHtmlToCache 在渲染可缓存渲染时缓存输出。

如何启用页面级缓存(在 Sitecore 8.2 Update 4 上测试)

假设代表页面的 Sitecore 项目继承自名为 Base page

的模板

将位于/sitecore/templates/System/Layout/Sections/Caching缓存 模板{E8D2DD19-1347-4562-AE3F-310DC0B21A6C} 添加到基本页面的基本模板。

基本页面继承的每个 Sitecore 页面项目现在都可以访问与渲染相同的缓存字段。

这个想法是在SetCacheability 之前添加一个新处理器。 此处理器检测layout 渲染类型。 如果关联的 Sitecore 项目启用了缓存,它会将缓存定义复制到此渲染中。

此处理器的代码(它使用 Glass Mapper,但更改起来很简单):

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; }
}

在 mvc 管道中添加此处理器的配置(将 MyAssembly.SetPageCaching, MyAssembly 更改为您自己的类型):

<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>

【讨论】:

    猜你喜欢
    • 2011-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多