Tridion Dynamic Linking API requires a PageURI value to be used when resolving dynamic links. This TCMURI is used when calculating the the proximity of a potential target URL relative to the current Page (where the link appears on).
The Issue
Tridion Dynamic Linking API requires a PageURI value to be used when resolving dynamic links. This TCMURI is used when calculating the the proximity of a potential target URL relative to the current Page (where the link appears on).
For links within a static Component Presentation, this is no problem, as the PageURI can be taken from the context of the Page the current static Component Presentation appears on. So at publish time, when the Linking tag or control is generated, the PageURI is available and can be used.
However, for Dynamic Component Presentations (DCPs), it is not possible to determine the PageURI where this DCP will be on during publishing. By their nature, a DCP is a piece of content that can appear on any Page; therefore, there is a need to find the context PageURI and pass it to the DCP such that the Link tag/control can use it.
The following prerequisites must be in place:
- DCP language is scripted (e.g. Java, ASCX, ...)
- Tridion generates tags/controls for dynamic Linking
The Solution
The general idea is to have the PageURI available in the Page that displays the DCP (typically there would be a page level variable that during publishing is populated with the value of the PageURI). This PageURI value is then placed into the current request (as an attribute for example), such that when the ComponentPresentationAssembler forwards the request to the DCP, the PageURI value is available in the forwarded request. The DCP contains code that reads the PageURI from the request and uses it in the call to Link API.
Java
The Java solution uses JSTL (Java Standard Tag Library) and Unified Expression Language (EL), so the following 2 JARs need be available in the server's classpath (i.e. typically WEB-INF/lib/ folder):
- jstl.jar
- standard.jar
In the Page Template put the following code:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <c:set var="PageURI" value="[%= Page.Id %]" scope="request"/> [% For Each objCP In Page.ComponentPresentations WriteOut objCP.Content & vbCrLf Next %]
When published, the Page would look similar to this:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <c:set var="PageURI" value="tcm:37-986-64" scope="request"/> <tridion:ComponentPresentation runat="server" PageURI="tcm:37-986-64" ComponentURI="tcm:37-972" TemplateURI="tcm:37-970-32"/>
In the DCP output the following code that generates the dynamic Component link:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <tridion:ComponentLink pageURI="${PageURI}" templateURI="tcm:0-0-0" componentURI="tcm:37-972" textOnFail="true" linkText="Amy Winehouse cancels gig (Public)"/>
.NET
In the Page Template put the following code:
<% Context.Items.Add("PageURI", "[%= Page.Id %]"); %> [% For Each objCP In Page.ComponentPresentations WriteOut objCP.Content & vbCrLf Next %]
When published, the Page would look similar to this:
<% Context.Items.Add("PageURI", "tcm:68-2185-64"); %> <tridion:ComponentPresentation runat="server" PageURI="tcm:68-2185-64" ComponentURI="tcm:68-2171" TemplateURI="tcm:68-2177-32"/>
In the DCP output the following code that generates the dynamic Component link:
<tridion:ComponentLink runat="server" PageURI='<%$ Code: Context.Items["PageURI"]%>' TemplateURI="tcm:0-0-0" ComponentURI="tcm:68-2170" LinkText="Amy Winehouse cancels gig (Public)" TextOnFail="true"/>
This code above uses a .net 2.0 feature called Expression Builder. This makes the following construct available to be executed within .net: <%$ Code: some_expression %>. Even more, such an Expression Builder can be used within the attribute of a control.
In order for the Code Expression Builder to work, the Code namespace needs to be declared in web.config:
<configuration> <system.web> <compilation debug="true"> <expressionBuilders> <add expressionPrefix="Code" type="Tridion.Extensions.ContentDelivery.Utility.CodeExpressionBuilder"/> </expressionBuilders> </compilation> ...
where the class Tridion.Extensions.ContentDelivery.Utility.CodeExpressionBuilder belongs to DLL Tridion.Extensions.ContentDelivery.Utility.dll.