Time to burst another popular misconception.
SharePoint 2010 comes with a new server tag to help you set a Favourite Icon (FavIcon) for pages in your site. This is the <SharePoint:SPShortCutIcon> tag. The SPShortCutIcon tag lets you specify an IconUrl property. If we don’t mind hard coding our IconUrls, we can set it to something like:
<SharePoint:SPShortCutIcon IconUrl=”/Site Assets/favicon.ico” runat=”server” />
However, if you have many sites in a hierarchy, or many site collections, you might not want to have this hard coded.
SharePoint helps us out here with a handy thing called the SPUrlExpressionBuilder class. We can use the special server-side tag $SPUrl to format up Url strings that are relative to the current site or site collection.
If I wanted to use this technique with a related part of the page, the Site Logo Image <SharePoint:SiteLogoImage>, I could embed the following code into my master page:
<SharePoint:SiteLogoImage LogoImageUrl=”<% $SPUrl:~sitecollection/SiteAssets/icon.png%>” runat=”server”/>
It would be nice to use the same technique with FavIcons. Indeed, there are are a lot of blog sites that suggest this is possible. I’ve tried this out, and I have no idea how it could work.
The reason the above code works is that SPSiteLogoImage.LogoImageUrl is a System.String type. $SPUrl statements return a System.String. No problem there.
However, SPShortCutIcon.IconUrl seems to have broken this pattern, and is actually a System.Uri. Any attempt to use $SPUrl to format a relative Url results in a casting error from System.String to System.Uri.
Good news is, there is a workaround. It’s not pretty, but we can use $SPUrl to set the System.String value of the Text property on an asp:Literal control.
We then need to sandwich that in between two more asp:Literals to render a complete client-side <link rel=”shortcut icon” …/> tag.
<asp:literal runat=”server” Text=”<link rel=’shortcut icon’ href='” /><asp:literal runat=”server” Text=”<% $SPUrl:~sitecollection/Site%20Assets/favicon.ico %>” /><asp:literal runat=”server” Text=”‘ type=’image/vnd.microsoft.icon’ />” />
I told you it wasn’t pretty, but at least we didn’t have to write any custom controls of our own. Here’s the HTML it outputs:
<link rel=’shortcut icon’ href=’/Site%20Assets/favicon.ico’ type=’image/vnd.microsoft.icon’ />
If anyone has a more elegant (read: less kludgy) solution to the problem, please post a comment!
Post Script:
Here’s a nicer solution from one of our readers: (Many thanks, Adam!)
<link rel=’shortcut icon’ href=’<% $SPUrl:~SiteCollection/Style Library/Images/favicon.ico %>’ />