Sitecore.Links.LinkManager and the context

A new feature in Sitecore 6 is the LinkManager. Previously, in Sitecore 5, in order to get a friendly url (an URL with the .aspx extension) you would write the following:

Item item;
string path = item.Paths.GetFriendlyUrl(false);

In Sitecore 6, the GetFriendlyUrl() is deprecated. Instead we are encouraged to use the Sitecore.Links.LinkManager. The same piece of code would look like this:

Item item;
string path = Sitecore.Links.LinkManager.GetItemUrl(item);

The LinkManager provides us with a lot of features that the GetFriendlyUrl() did not. But it also introduces some pitfalls. The LinkManager runs in a context that is not necessarily the same as the Item you are getting the link from, nor the context you wish to run in. Let me explain. Imagine you write a Sitecore shell extension that returns the path to an item. The Item is grabbed from the web database:

Sitecore.Data.Database database = Sitecore.Data.Database.GetDatabase("web");
Sitecore.Data.Items.Item item = database.GetItem("/sitecore/content/home");
string path = item.Paths.FullPath;

The path to the item is “/sitecore/content/home”.

Now, lets get the item’s URL:

string path = Sitecore.Links.LinkManager.GetItemUrl(item)

This returns the item URL for the current Site as defined in the LinkManager.GetDefaultUrlOptions().Site. If my code runs in the modules_shell site, the url is /en/sitecore modules/shell.aspx. Is this really the url of my item? Yes, seen from the modules_shell site it is, but not as seen from the website site.

So my Item used the website site, but my LinkManager uses the modules_shell site. The URL i wanted is the one from the website site, but the URL i requested is from the modules_shell site.

What can I do about this? The URL is constructed by prefixing the current site’s virtual path (which for the modules_shell site is /sitecore modules/shell) to the actual path. The easy solution would be to remove the virtual path from the URL:

string virtualFolder = LinkManager.GetDefaultUrlOptions().Site.VirtualFolder.TrimEnd('/');
Response.Write(LinkManager.GetItemUrl(item).Replace(virtualFolder, ""));

This produces the URL /en.aspx, which is correct for my website site, since this site has no virtual path.

Another, and probably better, solution would be to change the context before getting the link:

string oldSiteName = Sitecore.Context.GetSiteName();

This produces the URL “/”, which is correct for the home page of my website.

UPDATED: More on the same topic:

About briancaos

Developer at Pentia A/S since 2003. Have developed Web Applications using Sitecore Since Sitecore 4.1.
This entry was posted in Sitecore 6 and tagged , , , . Bookmark the permalink.

6 Responses to Sitecore.Links.LinkManager and the context

  1. Pingback: Working with multiple sites in Sitecore « Brian Pedersen’s Sitecore and .NET Blog

  2. Pingback: Working with multiple sites in Sitecore |

  3. Great article! We used your suggestions in a custom PublishItem processor to send links to recently-published items to a mirror site.

    An alternate approach to the “change the context before getting the link” idea that we used is to provide the desired site context directly to GetItemUrl() via UrlOptions:

    string link = LinkManager.GetItemUrl(item, new UrlOptions
    Site = Sitecore.Sites.SiteContext.GetSite(“website”)

  4. Gareth Watt says:

    I raised a sitecore support issue relating to this (version 6.5). They did not recommend changing the site context with Sitecore.Context.SetActiveSite(), but instead passing the site explicitly into LinkManager.GetItemUrl() with UrlOptions as Pheonix suggests. I found this to work better.

  5. Pascal says:

    Another option in my opinion is to use the UrlOptions with the Property ResolveSite to true. This way you don’t have to set a specific site, but the one in which the item is used.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s