LibrarySites.Banner

Site Aware Link (Options) Provider for the Sitecore ASP.NET CMS

This blog post describes a solution that varies URL generation options based on attributes of the context site with the Sitecore ASP.NET web Content Management System (CMS) and Experience Platform (XP).

You can manage and deliver multiple logical sites with a single Sitecore instance. When generating links between items within a single managed site or within separate managed sites, Sitecore uses the link provider to generate URLs. Elements of in the Web.config file define properties of the link provider that affect its functionality.

You can implement a solution based on the following untested prototype of a link provider that allows attributes of the context site to override attributes of link provider configuration (and applies the Rendering.SiteResolving setting if appropriate).

namespace SitecoreJohn.Links
{
  using System;
 
  using Sitecore;
  using Sitecore.Configuration;
  using Sitecore.Links;
 
  public class SiteAwareLinkProvider : LinkProvider
  {
    public override UrlOptions GetDefaultUrlOptions()
    {
      var options = base.GetDefaultUrlOptions();
      options.SiteResolving = Settings.Rendering.SiteResolving;
      var site = Context.Site;
 
      if (site == null)
      {
        return options;
      }
 
      options.SiteResolving = MainUtil.GetBool(
        site.Properties["siteResolving"],
        options.SiteResolving);
      options.AddAspxExtension = MainUtil.GetBool(
        site.Properties["addAspxExtension"],
        options.AddAspxExtension);
      options.AlwaysIncludeServerUrl = MainUtil.GetBool(
        site.Properties["alwaysIncludeServerUrl"],
        options.AddAspxExtension);
      options.EncodeNames = MainUtil.GetBool(
        site.Properties["encodeNames"],
        options.EncodeNames);
      options.LowercaseUrls = MainUtil.GetBool(
        site.Properties["lowercaseUrls"],
        options.LowercaseUrls);
      options.UseDisplayName = MainUtil.GetBool(
        site.Properties["useDisplayName"],
        options.UseDisplayName);
      options.ShortenUrls = MainUtil.GetBool(
        site.Properties["shortenUrls"],
        options.ShortenUrls);
      LanguageEmbedding languageEmbedding = options.LanguageEmbedding;
      Enum.TryParse(
        site.Properties["languageEmbedding"],
        true /*ignoreCase*/,
        out languageEmbedding);
      options.LanguageEmbedding = languageEmbedding;
      LanguageLocation languageLocation = options.LanguageLocation;
      Enum.TryParse(
        site.Properties["languageLocation"],
        true /*ignoreCase*/,
        out languageLocation);
      options.LanguageLocation = languageLocation;
      return options;
    }
  }
}

You can use a Web.config include file such as the following to enable this link provider override:

<configuration xmlns:patch="https://www.sitecore.com/xmlconfig/">
  <sitecore>
    <linkManager>
      <patch:attribute name="defaultProvider">switcher</patch:attribute>
      <providers>
        <add name="sitecore">
          <patch:attribute name="name">switcher</patch:attribute>
          <patch:attribute name="type">SitecoreJohn.Links.SiteAwareLinkProvider</patch:attribute>
        </add>
      </providers>
    </linkManager>
    <siteManager>
      <patch:attribute name="defaultProvider">config</patch:attribute>
    </siteManager>
    <sites>
      <site name="website">
        <patch:attribute name="addAspxExtension">true</patch:attribute>
        <patch:attribute name="alwaysIncludeServerUrl">true</patch:attribute>
        <patch:attribute name="encodeNames">true</patch:attribute>
        <patch:attribute name="languageEmbedding">always</patch:attribute>
        <patch:attribute name="languageLocation">filePath</patch:attribute>
        <patch:attribute name="lowercaseUrls">true</patch:attribute>
        <patch:attribute name="shortenUrls">true</patch:attribute>
        <patch:attribute name="useDisplayName">false</patch:attribute>
      </site>
    </sites>
  </sitecore>
</configuration>

Now the /configuration/sitecore/sites/site elements in your Web.config file should support some new attributes:

  • addAspxExtension
  • alwaysIncludeServerUrl
  • encodeNames
  • languageEmbedding: always, never, or asNeeded
  • languageLocation: filePath or queryString
  • lowercaseUrls
  • shortenUrls
  • useDisplayName
  • siteResolving

Demonstration code:

@using Sitecore.Links
@using Sitecore.Sites
@model Sitecore.Mvc.Presentation.RenderingModel
 
<ul>
@foreach (Sitecore.Data.Items.Item item in Model.Item.Children)
{
  <li><a href="@LinkManager.GetItemUrl(item)">@LinkManager.GetItemUrl(item)</a>
 
  @using (new SiteContextSwitcher(SiteContext.GetSite("shell")))
  {
    <a href="@LinkManager.GetItemUrl(item)">@LinkManager.GetItemUrl(item)</a>
  }
  </li>
}
</ul>

Resources