Site Collection-Safe CQWP XSL Links

A common complaint about styling the ContentByQueryWebPart is that the XslLink properties, used to reference custom XSL files that can be deployed via features (the best practice), don’t support site collection-relative links. This means that one would need to provide a separate .webpart file for each site collection that doesn’t live at the server root. Other common workarounds are to “get creative” with relative URLs or add the Web Part with code and assign a server-relative URL. Fortunately, it’s relatively easy to extend CQWP to adjust any server-relative URL to accommodate non-root site collections:

public class SiteSafeContentByQueryWebPart : ContentByQueryWebPart
{
    protected override void OnLoad(EventArgs e)
    {
        MainXslLink = MakeServerRelativeUrl(MainXslLink);
        HeaderXslLink = MakeServerRelativeUrl(HeaderXslLink);
        ItemXslLink = MakeServerRelativeUrl(ItemXslLink);
    }

    private string MakeServerRelativeUrl(string url)
    {
        if (string.IsNullOrEmpty(url) || url[0] != '/')
            return url;

        var u = SPUtility.SiteRelativeUrlPrefix + url.TrimStart('/');
        return SPUtility.GetServerRelativeUrlFromPrefixedUrl(u);
    }
}

There are already several examples online of how to deploy and use an extended CQWP, so I won’t bother to repeat the process here. As long as the XslLink starts with “/”, it will be translated for the current site collection:

<properties>
  <property name="Title" type="string">SiteSafeContentByQueryWebPart</property>
  <property name="MainXslLink" type="string">/Style Library/CustomContentQueryMain.xsl</property>
  <property name="HeaderXslLink" type="string">/Style Library/CustomHeader.xsl</property>
  <property name="ItemXslLink" type="string">/Style Library/CustomItemStyle.xsl</property>
</properties>

If there’s demand for a barebones SCSCQWP, I can post one, but I would rather see some of the more advanced versions just integrate this code.

Advertisements