Tridion 组件链接在动态组件演示中未解析

Posted

技术标签:

【中文标题】Tridion 组件链接在动态组件演示中未解析【英文标题】:Tridion Component Link not resolving in Dynamic Component Presentation 【发布时间】:2012-05-18 22:34:49 【问题描述】:

我目前正在 Tridion 2009 SP1 中实现功能,用户可以使用过滤器来查询代理以获取匹配条件,然后将组件演示文稿返回到页面。 返回的每个项目都包含一个组件链接。

最初动态 CP 作为 html 片段存储在代理数据库中,但发现当以这种方式存储 CP 时,Tridion 会从内容中剥离组件链接并在 HTML 中留下空白区域。

然后我切换了设置,以便动态 CP 现在作为 ascx 控件存储在文件存储中。使用此设置时,<tridion:ComponentLink ... /> 成功存储在 ascx 文件中。

但是,当我将结果呈现到屏幕上时,组件链接没有被解析,我在结果源中留下了<tridion:ComponentLink ... />

目前,我使用GetComponentPresentation方法返回CP内容,然后将其添加到列表中,然后再绑定到Repeater进行显示。

总结代码如下:

ComponentPresentationFactory CPFactory = new ComponentPresentationFactory();
List<string> componentPresentations = new List<string>();

for (int i = 0; i < tbl.Rows.Count; i++)

    ComponentPresentation cp = CPFactory.GetComponentPresentation(
                                             tbl.Rows[i][0].ToString(), 
                                             strComponentTemplate.ToString());

    if (cp != null)
    
        componentPresentations.Add(cp.Content);
    

这个列表以通常的方式绑定到转发器:

rptOffer.DataSource = componentPresentations;
rptOffer.DataBind();

有谁知道我可以如何强制解析组件链接以及为什么GetComponentPresentationfunction 不为我执行此操作?

有什么我应该做的不同的事情,或者这在我实现它的方式上是不可能的吗?

我已确认tridion tagprefix 已在 web.config 中正确注册。

我对 Tridion 还很陌生,因此非常感谢任何帮助!

更新

我已尝试实施 Will 的建议,因为它似乎是最适合我的方案的解决方案,但是当我尝试将 Will 的建议与下面的代码一起使用时,我收到了一个(相当平淡的)错误:

ComponentPresentationAssembler cpa = new ComponentPresentationAssembler("tcm:35-62652-64");
string content = cpa.GetContent(tbl.Rows[i][0].ToString(), strComponentTemplate.ToString());

实际上有 2 个错误(看似)随机发生,但总是在 cpa.GetContent(...) 调用时发生。错误是:

Exception occurred during configuration callback
OR
com.tridion.dcp.ComponentPresentationFactory

我似乎无法弄清楚为什么在我运行代码时错误会发生变化。即使没有更改代码,错误也会发生变化。

有人知道我在这里缺少什么吗?我认为这将是与代理存储等的连接问题,但后来我记得当我使用 ComponentPresentationFactory 类时该部分正在工作。

如果有帮助,作为 ascx 存储在文件存储中的 DCP 包含以下 HTML:

<div class="content-list-item offer redesign noImage">
<h2><span>Mike Offer 01/06 - 10/06 &amp; 20/06 - 10/07</span> Exp May 20th</h2>
<div class="content-list-item-text">
    <p>Body Text</p> 
    <div class="input-btn burgundy">
        <tridion:ComponentLink runat="server" PageURI="tcm:0-0-0" ComponentURI="tcm:35-31685" TemplateURI="tcm:0-0-0" AddAnchor="false" LinkText="Button Text&lt;span class=&#34;rm&#34;&gt;: Button Text&lt;/span&gt;" LinkAttributes=" alt=&#34;Button Text&#34; target=&#34;_self&#34; " TextOnFail="true"/>    
    </div>
        <p>Sub Title</p>
</div>
<div class="offers-list">        
    <ul>
        <li>Offer ends: 20 May 2012</li>
        <li>Offer available at all hotels</li>
    </ul>
</div>                          
<div class="back-to-top">
    <a href="#content">Back to top</a>
</div>

更新 2

感谢 Ryan,我发现我的 DCP (ASCX) 文件没有在 wwwroot 文件夹内的应用程序文件夹中发布,这解决了将 &lt;tridion:ComponentLink ... /&gt; 标记直接输出到源的问题。它现在正在呈现,但链接仍未解决。 &lt;a ... /&gt; 标签未输出。这就是汇编程序有望发挥作用的地方——一旦我可以让它工作。

我已经实现了更多的日志记录和检查,并获得了有关错误的更多信息,这表明我可能缺少 jar 文件或版本不正确:

Exception Details: Java.Lang.ClassNotFoundException: com.tridion.dcp.ComponentPresentationFactory

有趣的是,当我使用 ComponentPresentationFactory 类时,它可以工作(不解析内部链接),但是一旦我使用汇编程序,它就会抛出上述错误。

我还尝试按照 Alvin 的建议将页面添加到构造函数,但输出是相同的。

【问题讨论】:

嗨,迈克,欢迎来到 Tridion。你设法很好地隐藏了你的新鲜感。 :-) 您会发现 Tridion 社区的大多数成员都非常乐于助人。如果您还没有这样做,请提交我们关于 area51 的 Tridion 提案:area51.stackexchange.com/proposals/38335/… 问题出在 CPFactory - 请改用 CPAssembler,正如 Will 在他的回复中显示的那样 在 .getContent() 错误中,它是否与多个演示服务器和/或运行代码时实际未发布的组件演示有关? Alvin - 这是一个单一的演示服务器,所以这应该不是问题。在我将设置更改为在代理数据库中发布为 ascx 而不是 HTML 之后,我还重新发布了所有组件(其中大约 15 个),以确保不会导致问题。不幸的是,问题仍然存在...... 您是否确定您的 ASCX 文件已发布在您的 Web 应用程序文件夹中?您可以在 cd_broker_conf.xml 文件中进行设置。 【参考方案1】:

您正在将动态组件表示的内容作为字符串加载,而不是像用户控件那样执行字符串。

要解决您的问题,您可以使用 2 个解决方案之一:

1) 在cp.Content 上使用正则表达式通过 Tridion API 处理链接。

2) 将您的动态内容作为用户控件发布到文件系统,并将此控件加载到您的页面/用户控件上,从而执行它

using (var cpf = new ComponentPresentationFactory(publicationId))

    var cp = cpf.GetComponentPresentation(componentId, componentTemplateId);
    fileLocation = cp.FileLocation;


if (!String.IsNullOrEmpty(fileLocation))

    var crtl = this.LoadControl(MapPathReverse(fileLocation));
    phldControls.Controls.Add(crtl);

【讨论】:

-1 因为 Tridion 对使用 ComponentPresentationAssembler 执行此操作提供了开箱即用的支持 谢谢多米尼克。我不知道 ComponentPresentationAssembler。你每天都能学到新东西。【参考方案2】:

Mark 的回答已经涵盖了您的 Tridion 版本最重要的部分:您必须将 ASCX 文件发布到磁盘,以便 ASP.NET 执行 tridion:CompontentLink 控件。。 p>

Tridion 2011 引入了 REL 作为替代解决方案。使用 REL 时,您只需再次发布 HTML 片段,tcdl:ComponentLink 将按原样存储到数据库中(因此在部署时不会转换为 tridion:ComponentLink)。然后,当您检索内容(通过ComponentPresentationTransformer 或通过新的 Content Delivery OData Web 服务)时,tcdl:ComponentLink(和其他 tcdl:* 标记)将被解析,您将获得所需的结果。

【讨论】:

【参考方案3】:

为了执行 DCP,而不仅仅是获取发布的内容,您需要使用 ComponentPresentationAssembler 类,而不是 ComponentPresentationFactory 类。

下面是一个简单的例子:

ComponentPresentationAssembler cpa = 
   new ComponentPresentationAssembler("tcm:69-6212-64",this.Page);
Response.Write(cpa.GetContent("tcm:69-2882", "tcm:69-6339-32"));

请注意,如果您要发布大量(即数百个)组件演示文稿(并且经常发布它们),使用 ascx 不是一个好主意 - 您可能会遇到一些性能问题,因为 ASP.NET 批量重新编译包含它们全部,或触发应用程序重新启动。

将它们作为 (X)HTML 片段发布到数据库并按照 Mark 提到的那样对链接进行后期处理会更安全。

正如 Frank 在 2011 SP1 中提到的,您可以使用 REL 为您执行此后期处理。更多信息请见this article

【讨论】:

好东西会。我看到您还没有加入我们的提案以获得 Tridion 特定的 StackExchange 区域。请点击此链接并考虑:area51.stackexchange.com/proposals/38335/… 感谢@Will 提供的信息。我已经尝试过了,但是当我尝试检索 DCP 时出现错误。我已将我的错误详细信息添加到帖子中。有什么想法吗? 啊,经典的 CP Assembler vs Factory 解释(来自 REL 的新优点),太好了! @MikePercival--我怀疑错误的不同之处在于您在第一个示例中捕获了空 CP。如果您删除检查,您是否会在同一组组件 ID 上得到相同的错误? @AlvinR​​eyes 我在代码中输入了很多日志,但失败肯定来自 cpa.GetContent() 调用。我在所有点检查空值,但在代码错误之前没有找到任何空值。我在原始帖子中添加了更多关于我的发现的细节。 @Mike - 要让 CP 汇编器工作,您需要 bin/conf/cd_wai_conf.xml 和 bin/lib/cd_wai.jar(请参阅我在问题下的评论) - 这可能是这里的问题 【参考方案4】:

如前所述,为了解决您的问题,您需要使用ComponentPresentationAssembler 类,而不是ComponentPresentationFactory 类,但您需要确保在Tridion.ContentDelivery.WAI 命名空间内使用ComponentPresentationAssembler 类:

Tridion.ContentDelivery.WAI.ComponentPresentationAssembler presentationAssembler = new Tridion.ContentDelivery.WAI.ComponentPresentationAssembler("tcm:5-44410-64",this.Page);
Response.Write(presentationAssembler.GetContent("tcm:5-62700", "tcm:5-62627-32"));

您还需要确保:

您的 ASCX 文件已发布到文件系统 这是在 &lt;Bindings&gt; 部分内的 cd_broker_conf.xml 文件中设置的,例如&lt;Binding Name="ASPComponentPresentation" Class="com.tridion.broker.componentpresentations.FSASCXComponentPresentationHome"/&gt;

您的 ASCX 文件在您的 .Net Web 应用程序中发布。 这是在 &lt;Publications&gt; 部分内的 cd_broker_conf.xml 文件中设置的,例如

<Publication Id="5" DocumentRoot="C:/Inetpub/wwwroot/website1" DataRoot="C:/Inetpub/wwwroot/website1/dcp">
    <Dcp>
        <Asp Location="C:/Inetpub/wwwroot/website1/dcp"/>
    </Dcp>
</Publication>

请注意,您在上面看到的位置区分大小写

【讨论】:

Cheers Ryan,我已将 Will 的答案标记为已接受的答案,因为他使用 ComponentPresentationAssembler 是正确的,但列出所需的事项以确保一切都在里面真的很方便这个工作的地方。干杯! 其实,再看一遍,我认为你的回答实际上是我设法解决这个问题的原因。事实证明,我收到的有关 ClassNotFoundException 的错误(请参阅更新 2)是由于我为 ComponentPresentationAssembler 使用了错误的命名空间。更改为 Tridion.ContentDelivery.WAI 命名空间解决了这个问题,让我可以让代码完全正常工作。很抱歉在标记正确答案时遗漏了这一重要部分。 除非我弄错了,否则您必须确保您拥有使用 WAI 功能的许可证。请注意...我不希望任何人实现此功能,然后发现他们没有必要的 Tridion 许可证!

以上是关于Tridion 组件链接在动态组件演示中未解析的主要内容,如果未能解决你的问题,请参考以下文章

在 Tridion 2011 中部署 PDF 的最简单方法

Tridion Taxonomy 查询示例的任何好的来源

Vue动态添加和删除组件的实现,子组件和父组件的传值实例演示

Vue组件滚动加载懒加载功能的实现,无限滚动加载组件实例演示

Tridion 2011 Sp1 允许将组件的修订版本发布到暂存目标

ASCX 用户控制 SDL Tridion 2011