Microsoft Office SharePoint Server (MOSS) 2007 provides architecture for designing and developing scalable solutions. Two of these concepts are Site Collections for separating information and Variations for delivering multilingual solution. While working with both concepts – especially in Web Content Management (WCM) solutions I have found out that there is no easy way to create Site Collection or Variation relative links.
SPSite.ServerRelativeUrl != /
Per definition SharePoint allows you to create multiple Site Collection within one Web Application. In most cases you will have one root Site Collection, which URL will be equal to the URL of the Web Application. Then you are allowed to create other Site Collections on the given Managed Path. Looking at the URL’s only the root Site Collection will have a / server relative URL. Other Site Collections will look more like: /sites/yoursitecollection.
While working with WCM solutions you might find yourself in a situation when you want to reuse the look & feel across multiple Site Collections. Unfortunately you will run into troubles if the Master Page or one of the Page Layouts contains a link to a contact page or a disclaimer: SharePoint doesn’t provide any mechanism to get this done!
Variations as the Root Site
MOSS 2007 introduced the concept of Variations: a mechanism which allows you to publish multilingual content. During the configuration of Variations, you provide the Variation Root (the starting point from which the content will be translated) and you create a number of Variations (language versions). Each Variation will end up in a separate tree, like /en/, /nl/, etc.
By creating Variations Hierarchies you indirectly move the root one level down. Your home page is now not the / anymore but /en/ or /nl/. Of course you can still navigate to / but based on your browser settings you will automatically get redirected to the Variation that SharePoint thinks fits your preferences the best.
Now imagine that your Master Page contains a link to the contact page. Because you are a good Internet citizen you have provided a translation for both English and Dutch. But what about the link? How to let SharePoint know that what you want to do is to link to the contact page of the current variation?
A better way of creating relative URLs in SharePoint 2007
As I have already mentioned: SharePoint doesn’t provide a standard mechanism to create either Site, Site Collection or Variation relative URL’s in an intuitive way. You could of course do it by creating a custom control, but then again imagine doing that for each and every link.
Looking on how to solve this challenged I have decided to extend the standard HtmlAnchor class available with ASP.NET. Eventually I have came up with the following control:
So how does it work?
Imtech.SharePoint.A under the hood
To get it all done I have created a new Href property. Because there is no way to override the one provided with the HtmlAnchor class I had to create a new one which would hide the base.Href property. Normally that would be a bad idea since the underlying class wouldn’t “see” our Href property but the base instead. Luckily for us, all attributes of an HtmlAnchor are being stored in a collection.
Each time there is a URL provided to the control through the Href attribute, it’s being scanned for three tokens: ~SiteCollection/, ~Site/ and ~Variation/. They are being replaced with respectively: server relative URL of the Site Collection (SPSite.ServerRelativeUrl), server relative URL of the current Site (SPWeb.ServerRelativeUrl) and the server relative URL of the current variation.
Because there is no straight-forward way of getting the URL of the current Variation I have included the GetVariationUrl method:
What it does is: it loops through all available Variations and by comparing the Variation URL to the URL of the current Site determines which Variation is the user currently using.
So how can I use it?
Imtech.SharePoint.A is just an ordinary custom control. In order to use it in your Master Pages and Page Layouts, you have to add it to your project, build the assembly, and reference it using the Register directive (assuming your assembly is called Imtech.SharePoint and you haven’t changed the namespace):
Then you can start using the control:
You can even use image links if you want to:
Download: Imtech.SharePoint.A.cs (2KB)