About a week ago I published my Extensions Manager, a Tridion 2011 extension that allows extensions’ creators define customizations for their users in a few lines of code. The customizations are exposed as fields to the users in a graphical interface that is easy to use and also takes care of the persistence of the values the users enter.
In my previous post I focused on the functional side of the Manager, the different features it has and the visual interaction.
In this post I’d like to focus on the programmatic side – how should an extension creator use it.
Since Tridion 2011 has been released with its shiny new GUI framework everyone and their sister have either been creating or thinking about creating extensions. I myself have been heavily involved in creating some.
Traditionally, extensions for the most part are islands of functionality; code is typically hardly ever reused. This is something I’d like to improve. With the advancement of the Tridion framework and by following OO practices, it’s possible to create reusable code, frameworks and more, the sky it the limit really.
A few weeks ago I thought about customizing GUI extensions. As extensions mature it will make sense to allow Tridion users, whether administrators or business, the ability to make changes to extensions’ behavior, to turn functionalities on and off and more, without having to change the underlying code. This led to… *drumroll* … The Extensions Manager.
The new 2011 Tridion GUI framework is a major overhaul to the way extensions have been previously developed. The framework now is far more robust and well designed. Building new and exciting extensions has never been easier. However, configuring your extension may not be the easiest thing in the world to do…
The following tutorial steps show how to configure an extension for the Tridion 2011 GUI from start to finish.
The example configuration and code is based on my extension: The Item XML Display.
While I have been planning to publish many more posts already this year, time seems more slippery than expected and I just can’t find it and hold it down for the necessary amount of… well, time.
So nothing fancy with this post, I just wanted to publish the extensions I created before, for the Tridion 2011 CTP(Item Xml Display and List Quick Helper) with the update to make them work on the already released Tridion 2011 (GA).
About a month ago I happily shared a GUI extension I’ve built for Tridion 2009 called the Item XML Display extension.
This extension lets a user (typically a developer) view the entire XML structure of a Tridion item from within the GUI without the need to open a new IE window or having a remote session to the CM server.
If you’re one of those already using this extension and have been dreading the moment Tridion 2011 will come out and you will be left without being able to quickly view items’ XML, fear not! I got you covered:
Continuing my recent trend of Tridion GUI extensions,
- Using jQuery for Tridion GUI Extensions.
- Integrating Tridion with Gravatar.
- The Read-Only Fields Tridion GUI Extension.
I give you the “Item XML Display” extension:
Lately I’ve worked on a Gravatar library for .NET which I released in July. I have also recently had the chance to work on Tridion GUI extensions for a customer.
This got me thinking; wouldn’t it be cool to integrate the two? Almost immediately I thought; yes, it will be cool!
So I’ve set to work on a nice GUI extension that will bring Gravatar to Tridion users and give the GUI a bit of a social touch make it feel more personalized by displaying a personalized photo for each user.
And so the integration is really 3 different extensions that can be each used individually or together.
Current User Photo
The first integration shows the Gravatar photo for the current user logged on to the Content Manager Explorer:
A relatively unknown feature of the Tridion CMS product is the GUI extensibility framework.
This is actually a fantastic feature which allows us to create and supplement the user interface with just about any type of addition we can think of.
It is pretty unknown because of the lack of documentation but with a little bit of investigation work it is possible to find all sorts of treasures we can use to extend the current GUI.
Here’s one example that is already available on the SDLTridionWorld website’s Community eXtensions section: “Republish from publish queue”, this nifty extension gives users the ability to republish items directly from the queue instead of the normal way of locating the item within the folder or structuregroup hierarchy.
The extension framework is quite robust (not without limitations of course) and allows us to add toolbar items, context menu options, tree nodes or simply run scripts that can do just about anything.
In this article I’m focusing on the latter, adding a scripted extension to do different tasks.
jQuery’s CSS selectors and methods for DOM manipulation are exactly the tools to help us create Tridion GUI extensions quickly and with relative ease.
The way the extension framework is built allows us to create a jQuery extension that can be reused by other extensions.
- .NET XSLT Extension Objects
- Creating an Extension Object
- Using Extension Objects – The Old Way
- Using Extension Objects – The New Way
- XSLT Page Template
- Source Code
In the previous article I’ve discussed the fundamentals of setting up the XSLT Mediator, configuring it and then showed how to create a simple compound component template which is making use of an XSLT TBB.
In this article I would like to concentrate mainly on extension objects; a little bit on what they are and how to make use of these in conjunction with the mediator.
.NET XSLT Extension Objects
The .NET Framework allows us to extend the style sheets we build by creating Extension Objects, these can be simple classes that contain helper or utility methods.
Some functionality is either extremely difficult or impossible to implement in pure XSLT code, for example we may want to retrieve a list of items from Tridion, doing this in just XSLT will be complicated and unmanageable to say the least.
The extension feature allows writing the logic for this kind of functionality in .NET managed code, we may even already written this code for a different part of our implementation and we simply want to reuse it.
If this concept is still unclear I am sure it will become more so further in the article, I will also add some links to other resources on the web that cover this area more thoroughly.
Creating an Extension Object
We’ll begin by creating a simple class with some useful methods that we can reuse in multiple templates:
public class SimpleXsltHelper
private TemplatingLogger m_Logger = null;
private Engine m_Engine = null;
public SimpleXsltHelper(Engine engine)
m_Engine = engine;
m_Logger = TemplatingLogger.GetLogger(this.GetType());
/// Returns the result of rendering the provided component and compomnent tempalte in a xml document
///component = the TCM URI of the component
///componentTemplate = the TCM URI of the component template
public XmlDocument RenderComponentPresentation(string component, string componentTemplate)
StringBuilder sb = new StringBuilder();
using (XmlWriter xWriter = XmlWriter.Create(sb))
TcmUri compURI = new TcmUri(component);
TcmUri ctURI = new TcmUri(componentTemplate);
XmlDocument resultDoc = new XmlDocument();
/// Used to publish a binary to the presentation server
/// compURI = the TCM URI of the multimedia component to publish
/// Returns the publish path of the binary
public string PublishBinary(string compURI)
Component comp = m_Engine.GetObject(compURI) as Component;
string publishPath = comp.Id;
if (comp.BinaryContent != null)
Binary pubBinary = m_Engine.PublishingContext.RenderedItem.AddBinary(comp);
m_Logger.Debug("PublishBinary: published Binary: " + comp.Id + " to url: " + pubBinary.Url);
publishPath = pubBinary.Url;
m_Logger.Warning("PublishBinary: " + comp.Id + " is not a multimedia coomponent");
Here’s an explanation of the code:
The constructor of the class accepts a single parameter, an instance of the Engine (Tridion.ContentManager.Templating.Engine) class.
RenderComponentPresentation(string component, string componentTemplate) – this method accepts the TCM URI of a component and the TCM URI of a component template, renders the two and returns the resulting content in an xml document.
PublishBinary(string compURI) – this method accepts the TCM URI of a multimedia component and using the AddBinary method makes sure the binary is published to presentation server. The method returns the relative path of the published binary file.
The reason for creating this class is to be able to call the methods defined in it from an XSLT TBB, the next couple of sections demonstrate ways of accomplishing this.
Using Extension Objects – The Old Way
When I released the XSLT Mediator there was only one way for adding extension objects. To add an object to the transformation we had to create the class in the Mediator’s assembly project and inject the line of code for adding the object into the mediator’s class.
I’ve later improved this a bit by making the method in charge of adding extension objects Virtual so a developer can create their own mediator inheriting from the Tridion.Extensions.Mediators.XsltMediator and overriding that method.
So a project with a custom extension object will look something like this:
In the image above you can see the helper class (which we’ll use as an extension object) and the custom mediator inheriting from the XsltMediator.
The code for our custom mediator will look like this:
public class MyCustomMediator : XsltMediator
protected override void AddExtensionObjects(XsltArgumentList arglist)
SimpleXsltHelper helper = new SimpleXsltHelper(this.Engine);
The code is very straightforward, We override the virtual method AddExtensionObjects which accepts a single parameter of type System.Xml.Xsl.XsltArgumentList.
To the arglist parameter we can add our extension objects using its method AddExtensionObject(string, object).
The method expects two parameters, the first, a String, which should contain a unique namespace within the transformation. This can be just about any string of characters you decide to use as long as its unique.
The second parameter is the actual extension object which is an instance of the SimpleXsltHelper class we created earlier.
The last line of code to mention is
This makes sure that the helper extension object which is bundled with the mediator is also available in the transformation. If you don’t plan on using this helper object you can simply omit that line of code from your implementation.
To be able to start using our new extension object there is one last step which is needed. In the previous article I’ve showed how to configure the basic mediator in the Tridion configuration file.
First build the project and overwrite the existing Mediator DLL file with the new build.
Since now we have a new custom implementation of the mediator we need to configure this new class name instead.
So in the Tridion.ContentManager.config file change the type attribute of the XSLT mediator from: Tridion.Extensions.Mediators.XsltMediator to XSLTMediator.Tutorials.MyCustomMediator
(the namespace and class name will obviously be different in real implementations).
Make sure you restart all the necessary services as explained in the first article.
Now we can go ahead and use the new methods we created in our XSLT templates.
We will go on and extend the XSLT template used in the previous article:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:image="http://www.tridion.com/ContentManager/5.0/DefaultMultimediaSchema" exclude-result-prefixes="msxsl simple customHelper">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
Publish Date: <xsl:value-of select="simple:pubDate"/>
First thing to notice is the declaration of the helper class namespace at the top:
xmlns:customHelper=”http://www.tridion.com/customhelper”. The important part is the namespace itself, it should be exactly the same as the one used in the Mediator’s code.
The prefix we assign this namespace can be anything we decide on as long as its unique within the context of our template.
The second part to notice is the call to our PublishBinary() method, using the prefix defined previously we can call any public method defined in the extension object’s class (As long as we use valid parameter data types). Since this method returns the publish path of the binary being published in our example we can use the returned value to set the ‘src’ attribute of the ‘img’ HTML element.
Notice that this time when we execute the compound template there is no need for the default finish actions, the image is published by the XSLT Template and the extension object.
Hopefully this simple example shows how extension objects can be used to augment XSLT templates in such a way that provides a very robust and manageable model.
Using Extension Objects – The New Way
As can be seen from previous sections its quite simple to create XSLT templates for compound templates and even add custom logic in the form of extension objects.
One thing bothered me about this process and that is that this type of templating model basically forces managing code in two locations, two projects: one is the templates projects which is uploaded into Tridion using the assembly upload tool and the second is the Mediator project which during a project and/or implementation is updated with extension objects and helper methods.
These two projects have to be maintained separately even though they both contain functionality which is ultimately used for one purpose – templates.
Because of this issue I came up with a new and in my view better way of creating and maintaining extension objects. This way allows you to create the class(es) in the same project you develop your templates.
The Mediator then loads the extension object(s) from Tridion in a similar manner to how Tridion loads .NET templates.
Using this new way you no longer need to keep updating the Mediator project, you can simply use the provided mediator as is.
To create extension objects in the Templates project you need a few things, if you are using the base project (available on world) you’ll have an easier time because everything you need is provided there.
First, any class which is meant to be used as an EO (Extension Object) should implement an interface, this is an interface you can create yourself or you can use the one in the base project, IXsltHelper. it doesn’t really matter which interface it is actually as we will see in a minute.
The second thing needed is to decorate any class used as an EO with an attribute class, TridionXSLTHelperNSAttribute. This attribute is used to define the namespace the EO will be assigned with when inserted into the argument list.
If you’re not using the base project or using an old version of it, simply download the new project from SDLTridionWorld and copy the TridionXSLTHelperNSAttribute class file to your project.
Your project should have similar elements to this example:
Since we already created a sample extension object we can reuse it by adding it to our templates project.
We will need to modify it a bit to conform to our new style:
public class SimpleXsltHelper : IXSLTHelper
private TemplatingLogger m_Logger = null;
private Engine m_Engine = null;
Notice that now the SimpleXsltHelper is implementing our IXSLTHelper interface and has the TridionXSLTHelperNS attribute. The value we pass the attribute is the same namespace we used earlier so that means there is no need to change the XSLT at all.
The mediator will take care of the rest, but to make sure it does we need to add a few configuration parameters to the Tridion.ContentManagaer.config file in this fashion:
<mediator matchMIMEType="text/xml" type="Tridion.Extensions.Mediators.XsltMediator" assemblyPath="C:\Program Files\Tridion\bin\Tridion.Extensions.Mediators.dll">
<parameter name="loadFromTridion" value="true"/>
<parameter name="interfaceName" value="IXSLTHelper"/>
<parameter name="templateID" value="tcm:42-15958-2048"/>
Let’s go over the parameters:
loadFromTridion: True or False telling the mediator whether to look for extension objects in Tridion.
interfaceName: The Mediator loads the assembly for Tridion and will look for classes that implement an interface with this name.
templateID: The TCM URI of the template building block containing the templates assembly.
As always make sure to restart all the necessary services after making the configuration changes.
From now on you can create and modify your extension objects as if they were any other .NET template you were working on. Updating the code in Tridion requires the same process as do normal templates and there are no extra steps needed.
It also means you have only one project containing all your templating functionality code which I think is a massive improvement.
Running our compound CT again gives us the exact same result as before:
XSLT Page Template
Up until now we have been working on a compound component template that was using a XSLT TBB but it wasn’t doing much more than what could be accomplished with normal XSLT CT.
Here is an example of a simple XSLT page template:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
<xsl:output method="html" indent="yes" omit-xml-declaration="yes"/>
<xsl:variable name="cp" select="customHelper:RenderComponentPresentation(tcm:Component/@xlink:href, tcm:ComponentTemplate/@xlink:href)"/>
As with the Component Template created in the first part of this tutorial, you will need to create a XSLT TBB and paste the above code into the source pane, then create a new compound page template in the Template Builder and add the new XSLT TBB to the list of selected templates.
Save and close the new PT and create a new page based on this page template.
Now we can preview our XSLT page template successfully:
Very easily we created a new page template in XSLT, to render the component presentations on the page we use a method we added to the extension object which returns the resulting content and layout in an XML document that is stored in a variable from which we can copy it onto the page.
In this article I focused mainly on creating extension objects and using them from XSLT templates.
I showed two ways of including extension objects in the transformation of templates, both are valid but the second is much more convenient in terms of deploying and managing the functionality of extension objects..
I’ve even added a simple example of a XSLT page template which is where the benefit of using the XSLT Mediator is really obvious since Tridion doesn’t support this type of template natively.
The XSLT Mediator comes with an extension object which is added to the transformation by default. The namespace for this object is: “http://www.sdltridion.com/ps/XSLTHelper”
This default object comes with some useful methods:
getFormatedDate – Generic XSLT helper function to format date strings using standard format strings.
getListItems – Generic XSLT helper function to retrieve items from within an OrganizationalItem
GetMultimediaInfo – Returns xml with information about the MM component such as the mime type or extension
Can be downloaded here.