Sitecore saxa:创建一个基于规则的代码片段呈现

时间阅读: 大约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 =参数.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规则中的规则.规则)
    {
        如果(规则.条件 != null)
        {
            var stack = new RuleStack();
            规则.条件.评估(规则Context堆栈);

            如果(规则Context.IsAborted)
            {
                继续;
            }
            如果(栈.数 != 0) && ((bool)堆栈.Pop ()))
            {
                规则.执行(规则Context);
                Var动作=规则.行动.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)
    {
        dataSourceRuleContext = 规则Context作为SelectSnippetRuleContext;
        ID的结果;
        如果dataSourceRuleContext == null || !ID.TryParse (SnippetId,结果)
        {
            返回;
        }
        dataSourceRuleContext.SnippetId =结果;
    }
}

结束

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

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