As described in part one of my post, we at Pentia have for some time had a bad feeling about the XSLT extensions concept introduced by Microsoft in the XsltTransform class and implemented further in Sitecore. We feel that XSLT’s belong in the UI tier (in a traditional n-tier architecture) and XSLT extensions has a tendency to introduce a mix of UI and business layer functionality and limited by the type restrictions in XSLT.
All developers (in their right minds) knows that asp.net codebehind files should contain UI layer functionality, not business logic, and that one c# codebehind file is bound to one asp.net file. What we want to achieve, is to have the same link between codebehind files in ASP.NET and XSLTs, therefore in our internal projects at Pentia, we have introduced the concept of XSLT codehind files.
So how does that work, you might ask?
Basically, we’ve developed a module which is included in all our projects (through our build environment), which automatically links XSLT extension classes to XSLT files through a common namespace. The module consists of an overridden Sitecore.Web.UI.WebControls.XslFile class, which overrides the AddExtensionObjects function:
public class XslCodebehindFile : Sitecore.Web.UI.WebControls.XslFile
{
protected override void AddExtensionObjects(XsltArgumentList list, Item item)
{
//...
}
}
The AddExtensionObjects function dynamically determines which .NET class is the codebehind file for the current XSLT and adds it to the XsltArgumentList with a specific namespace (in our case http://www.pentia.net/codebehind). The class to add is determined via a custom .NET Attribute class which decorates the codebehind class (see the example below).
Furthermore the module implements an overridden Sitecore.Web.UI.XslControlRenderingType class:
public class XslCodebehindControlRenderingType : XslControlRenderingType
{
public override Control GetControl(NameValueCollection parameters, bool assert)
{
// Returns the XslCodebehindFile class instead of the XslFile class
// ...
}
}
This class is used by the Sitecore renderings engine to return the .NET class which implements a Sitecore rendering type. The class is hooked into Sitecore through the web.config (done automatically though our build environment):
<configuration>
<!-- ... -->
<sitecore>
<!-- ... -->
<renderingControls>
<!-- ... -->
<control template="xsl rendering"
type="PT.XslCodebehind.XslCodebehindControlRenderingType, PT.XslCodebehind"
propertyMap="Path=path" />
<!-- ... -->
So how does the developer actually use it?
The developer starts by writing his XSLT file, e.g. /xsl/newslist.xslt. Most often it turns out that XSLT files does not even require codebehind or that the required functionality is implemented in the Sitecore XSLT extensions, but in the rare cases where advanced functionality is required (e.g. paging in the list of news) the developer creates a c# class file named newslist.xslt.cs (to keep the naming conventions defined by Microsoft). The class in the file is decorated with the XslCodebehind attribute which points to the fully qualified XSLT file:
[XslCodebehind("/xsl/NewsArchive.xslt")]
public class NewsArchive
{
//All functions in this class can be called in NewsArchive.xslt
public Int32 GetCurrentPageIndex(XPathNodeIterator archive)
{
//...
}
public Int32 GetPreviousPageIndex(XPathNodeIterator archive)
{
//...
}
public Int32 GetNextPageIndex(XPathNodeIterator archive)
{
//...
}
}
This class is then automatically linked into the XSLT file at runtime and can be called though the http://www.pentia.net/codebehind namespace:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:sc="http://www.sitecore.net/sc"
xmlns:codebehind="http://www.pentia.net/codebehind"
exclude-result-prefixes="sc codebehind">
<!-- ... -->
<xsl:template match="*" mode="main">
<!-- ... -->
<a href="?p={codebehind:GetNextPageIndex(.)}">
<!-- ... -->
</a>
<!-- ... -->
</xsl:template>
</xsl:stylesheet>
Easy-peasy – no meddling about in web.config and a much tighter coupling between XSLT files and their .NET functions.
The XSLT codebehind functionality took me about half a day to code and include into all our projects. It has made it practically easier for developers to link functionality to XSLT files and conceptually easier to understand the placement of the XSLT functionality in the UI layer.
Like this:
Like Loading...