![]() | 时间阅读: 大约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 =结果;
}
}
结束
这个解决方案到目前为止对我们的客户工作得很好. 目前还不清楚,随着规则条件数量的增加,这种解决方案是否会带来任何性能问题. 到目前为止,它还没有给我们带来任何问题,只有十几条规则. 一个积极的方面是它与个性化相结合. 因此,它允许根据客户行为选择不同的规则集.
我希望这些信息对你有用. 如果你有任何问题,请随时留下评论.