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(); Sitecore.Context.SetActiveSite("website"); Response.Write(LinkManager.GetItemUrl(item)); Sitecore.Context.SetActiveSite(oldSiteName);
This produces the URL “/”, which is correct for the home page of my website.
UPDATED: More on the same topic: https://briancaos.wordpress.com/2012/08/24/sitecore-links-with-linkmanager-and-mediamanager/