This article describes how Sitecore handles internal and external links, how you can resolve the correct URL to an item, and what you should know about links when building multisite and multilanguage websites.
To render a corrent URL you use the LinkManager:
public string GetUrl(Sitecore.Data.Items.Item item) { return Sitecore.Links.LinkManager.GetItemUrl(item); }
If the Sitecore Item you are linking to is a Media Item, you cannot use the LinkManager as this will return the Url to the Sitecore item, not the actual media. Instead use the MediaManager:
public string GetUrl(Sitecore.Data.Items.Item item) { return Sitecore.Resources.Media.MediaManager.GetMediaUrl(item); }
If you have a Linkfield (which can link to Internal items, Media Items, external pages, anchors, email and javascript) you can use a function like this to automatically get the correct URL:
Sitecore.Data.Fields.LinkField lf = Sitecore.Context.Item.Fields["Link"]; switch (lf.LinkType.ToLower()) { case "internal": // Use LinkMananger for internal links, if link is not empty return lf.TargetItem != null ? Sitecore.Links.LinkManager.GetItemUrl(lf.TargetItem) : string.Empty; case "media": // Use MediaManager for media links, if link is not empty return lf.TargetItem != null ? Sitecore.Resources.Media.MediaManager.GetMediaUrl(lf.TargetItem) : string.Empty; case "external": // Just return external links return lf.Url; case "anchor": // Prefix anchor link with # if link if not empty return !string.IsNullOrEmpty(lf.Anchor) ? "#" + lf.Anchor : string.Empty; case "mailto": // Just return mailto link return lf.Url; case "javascript": // Just return javascript return lf.Url; default: // Just please the compiler, this // condition will never be met return lf.Url; }
WHAT ELSE IS THERE TO KNOW?
Well, all internal links in Sitecore starts as a GUID. The GUID represents the internal item you link to. By using GUIDs internally, Sitecore allows you to move pages without worrying about links being invalid.
It is first when you render the page that the GUID is converted into a valid URL. Links in Rich Text Fields does it automatically (actually they use the ExpandLinks processor in the renderField pipeline), Link fields and lookup fields need help from you.
CAN I CONTROL HOW THE URL LOOKS?
Yes you can. You control the URLs with the linkManager settings in web.config:
<linkManager defaultProvider="sitecore"> <providers> <clear /> <add name="sitecore" type="Sitecore.Links.LinkProvider, Sitecore.Kernel" addAspxExtension="true" alwaysIncludeServerUrl="false" encodeNames="true" languageEmbedding="asNeeded" languageLocation="filePath" shortenUrls="true" useDisplayName="false" /> </providers> </linkManager>
Read the comments in the web.config on how to use the attributes. You can also replace the LinkProvider completely.
HOW ABOUT LINKS IN MULTISITE SOLUTIONS?
Multisite solutions are solutions where the same Sitecore installation contains more than one website, each site with its own unique domain name.
When creating multisite websites, you must remember to:
- Set the Rendering.SiteResolving setting in web.config to true.
- Set the targetHostName property to a unique domain for each website in the sites section in web.config.
This allows Sitecore to identify each site and add the correct domain name to links between sites.
BUT FOR NO APPARENT REASON Sitecore has chosen to render links made in the Rich Text Editor and links rendered by the LinkManager differently. Links in the Rich Text Editor use the Rendering.SiteResolving setting, while the LinkManager does not.
So you have to set it when using the LinkManager, using UrlOptions():
Sitecore.Links.UrlOptions urlOptions = new Sitecore.Links.UrlOptions(); urlOptions.SiteResolving = true; Sitecore.Links.LinkManager.GetItemUrl(someSitecoreItem, urlOptions)
A clever developer will might do as Paul is doing in this blog post and modify the LinkProvider so the option is always set.
Sitecore have also made a free LinkProvider that does the same and more. You can get it here:
http://trac.sitecore.net/LinkProvider#
HOW ABOUT NESTED MULTISITES?
When nesting sites (a new site begins below the URL of an existing site) it becomes more tricky. Forunately Sitecore allows us to replace their LinkProvider, as my colleague Uli has done here: http://reasoncodeexample.com/2012/08/09/sitecore-cross-site-links/
HOW ABOUT MULTILANGUAGE SOLUTIONS?
Multilanguage solutions are solutions where the same site exist in several language versions, each language having a unique URL.
From Sitecore 6.4, Update 6, Sitecore introcuced to more settings called Rendering.SiteResolvingMatchCurrentSite and Rendering.SiteResolvingMatchCurrentLanguage. These settings allow URL’s to guestimate the correct domain and langauge and create the correct URL accordingly.
Read more about it here: http://briancaos.wordpress.com/2012/03/29/sitecore-cross-site-and-cross-language-links-resolved-in-6-4-1-release-120113/
Unfortunately, these settings are also only supported by the Rich Text Editor, not by the LinkManager.
MORE TO READ:
- Sitecore Cross Site Links by Uli Weltersbach
- Manipulating Sitecore Links by John West
- Custom LinkProvider by Sitecore Trac
- Using cross site links by Paul Martin
