Sitecore SXA:创建基于规则的代码片段呈现

时间阅读: 大约7 - 10分钟
用于: Sitecore开发人员,高级开发人员 & 领导
主要结论: 如何使用Sitecore规则引擎创建一个自定义呈现来动态显示代码段内容.

在最近的一个商务项目中,需要在产品详细信息页面上显示特定于产品的内容. 这可能是一个品牌提供的图像,额外的细节,或某种广告或特殊内容. 因为产品数据是动态显示的,所以我需要用一种动态的方式来处理它.

我首先关注的是个性化. 虽然这可能有效,但最好的做法是只使用它来显示基于客户行为的内容. 当把访问者规则和内容规则混在一起时,规则也会很快变得混乱. 然而,规则引擎是一个强大的工具,所以我决定使用一个新的定制呈现来满足需求.

创建基于规则的代码段

我决定使用代码片段作为起点. 我基于代码片段呈现来为内容作者提供可添加内容的灵活性. 它允许他们使用多个渲染来添加任何东西,从简单的图像渲染到详细的产品信息.

首先,我创建了Snippet呈现的一个克隆,并仅在数据源项上添加了一个额外的规则字段. 其思想是使用规则引擎根据所显示产品的一组条件选择代码段数据项. 前提相当直接, 我只需要根据规则引擎的结果更改数据源项.

GetXmlBasedLayoutDefinition管道

当呈现一个代码片段时,它的xml布局定义被注入到页面项布局定义中. 为此,将解析数据源项,并读取和注入其布局定义. 这发生在 Sitecore.XA.功能.复合材料.管道.GetXmlBasedLayoutDefinition.InjectCompositeComponents. 这里我重写了 ResolveCompositeDatasource 方法以基于规则字段而不是呈现的数据源字段解析数据.

var datasourceItem = Context.数据库.GetItem (datasourceId);
如果(datasourceItem.TemplateID = =模板.规则BasedSnippetSnippet.ID)
{
    var 规则sBasedDatasource = 规则sBasedSnippetRepository.Get规则BasedSnippetDataSource (datasourceItem contextItem);
    返回规则sBasedDatasource ?? datasourceItem;
}
其他的
{
    返回datasourceItem;
}

改变很简单, 如果数据源项是基于规则的代码片段,则从规则引擎获取该项,否则返回原始数据源项. 在下一节中,我将详细介绍规则引擎代码.

还需要考虑管道的另一个更改. 生成的布局定义xml将基于当前上下文项id存储在字典缓存中. 这需要调整,因为我需要返回相同页面的不同结果. 所以我重写了 Create复合材料XmlCacheKey 方法返回一个不同的缓存键,仅对基于规则的代码段追加url.

var pagePath = args.PageContext.请求Context.HttpContext.请求.路径;
如果(currentItem.Name = = " * " && renderingIds.Any(r => r == Renderings.规则BasedSnippet.ID))
{
    返回$”SXA:{常数.复合材料XmlPropertiesKey}: {siteItem.ID}:{上下文.数据库.名称}:{上下文.设备.ID}:{上下文.语言.名称}:{currentItem.ID}: {pagePath}”;
}
其他的
{
    返回$”SXA:{常数.复合材料XmlPropertiesKey}: {siteItem.ID}:{上下文.数据库.名称}:{上下文.设备.ID}:{上下文.语言.名称}:{currentItem.ID}";
}

解析数据源项

最后,我需要使用规则引擎解析数据源项. 让我们从下面的代码片段开始:

var commerceContextItem = siteContext.CurrentCatalogItem ?? contextItem;
var 规则s = RuleFactory.Parse规则(contextItem.数据库,XElement.解析(规则sBasedSnippetSnippetItem[模板.规则BasedSnippetSnippet.字段.Snippet规则]));
var 规则Context = new 规则Context ()
{
    项= commerceContextItem
};

如果(规则.规则.任何())
{
    Foreach (var 规则 in 规则s ..规则)
    {
        如果(规则.条件 != null)
        {
            var stack = new RuleStack();
            规则.条件.评估(规则Context堆栈);

            如果(规则Context.IsAborted)
            {
                继续;
            }
            如果(栈.数 != 0) && ((bool)堆栈.Pop ()))
            {
                规则.执行(规则Context);
                Var action = 规则.行动.FirstOrDefault ();
                var snippetId = action is SelectSnippet ? ((SelectSnippet)action)?.SnippetId:字符串.空的;
                返回 !字符串.IsNullOrEmpty (snippetId) ? contextItem.数据库.GetItem (ID.解析(snippetId)):空;
            }
        }
        其他的
        {
            规则.执行(规则Context);
        }
    }
}

返回null;

首先,我使用RuleFactory解析器解析规则字段xml. 然后, 因为我需要对产品项执行规则引擎,所以我从商业站点上下文中检索了当前目录项. 然后将其用作规则引擎的上下文项. 最后,我用返回最终结果的规则引擎遍历和评估每个规则.

SelectSnippet 是一个自定义 RuleAction 从解析的规则返回选定的代码段id. 的 SelectSnippetRuleContext 是否使用自定义宏设置代码段. 在这篇文章中,我不会详细介绍如何创建宏. 但是你可以在网上找到大量创建自定义宏的资源.

public class SelectSnippet : RuleAction where T : RuleContext
{
    public 字符串 SnippetId { get; set; }

    应用(T 规则Context)
    {
        select tsnippet规则context dataSourceRuleContext = 规则Context as SelectSnippetRuleContext;
        ID的结果;
        if (dataSourceRuleContext == null || . txt == null !ID.TryParse (SnippetId,结果)
        {
            返回;
        }
        dataSourceRuleContext.SnippetId =结果;
    }
}

结束

到目前为止,这个解决方案对我们的客户很有效. 目前还不清楚随着规则条件数量的增加,这种解决方案是否会带来性能问题. 到目前为止,十几条规则还没有给我们带来任何问题. 一个积极的方面是它与个性化相结合. 因此,它允许根据客户行为选择不同的规则集.

我希望这些信息对你有用. 如果你有任何问题,请随时留下评论.

友情链接: 1 2 3