Site Specific Link Manager (Part 2) – Sitecore 8.2 Dependency Injection Support

I previously blogged about a Switching Link Provider for Sitecore, allowing you use a different LinkProvider for different sites.

There were a number of changes in Sitecore 8.2 to LinkManager/Provider as a result of the Dependency Injection changes, unfortunately one of them being the Providers collection being marked [Obsolete]. The code in the old post should still work, but you’ll get that annoying warning.

The previous code worked by creating a Link Provider which acted as a switcher that in turn called a different Provider. This was a hack because we could not switch out the Link Manager itself. Well the DI changes in Sitecore 8.2 allow us to do that instead and provide our own implementation of LinkManager instead.

Slightly annoyingly, the code could have been super simple if we were able to inherit the Sitecore.Links.DefaultLinkManager and just override the internal LinkProvider Provider… But notice it’s marked internal so we are left having to essentially copy/paste all the other properties (╯°□°)╯︵ ┻━┻

Anyway, we can replace the LinkManager with our own implementation, which checks if a linkProvider property is set on the context site node. If not, then the defaultProvider that is set on the “ node is used. There is no need for an additional switching provider to set fallbacks.

<?xml version="1.0"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
<sitecore>
<services>
<configurator type="Sitecore.Custom.Providers.ServicesConfigurator, Sitecore.Custom" />
</services>
</sitecore>
</configuration>

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Sitecore.Abstractions;
using Sitecore.DependencyInjection;
namespace Sitecore.Custom.Providers
{
public class ServicesConfigurator : IServicesConfigurator
{
public void Configure(IServiceCollection serviceCollection)
{
var service = new ServiceDescriptor(typeof(BaseLinkManager), typeof(SwitchingLinkManager), ServiceLifetime.Singleton);
serviceCollection.Replace(service);
}
}
}

using System;
using System.Web;
using Sitecore.Abstractions;
using Sitecore.Configuration;
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Links;
using Sitecore.Sites;
using Sitecore.Web;
namespace Sitecore.Custom.Providers
{
public class SwitchingLinkManager : BaseLinkManager
{
private readonly ProviderHelper<LinkProvider, LinkProviderCollection> providerHelper;
public SwitchingLinkManager(ProviderHelper<LinkProvider, LinkProviderCollection> providerHelper)
{
this.providerHelper = providerHelper;
}
protected virtual LinkProvider Provider
{
get
{
var siteLinkProvider = (Sitecore.Context.Site != null)
? Sitecore.Context.Site.Properties["linkProvider"] : String.Empty;
if (String.IsNullOrEmpty(siteLinkProvider))
return this.providerHelper.Provider;
return this.providerHelper.Providers[siteLinkProvider]
?? this.providerHelper.Provider;
}
}
/* below is copy/paste from Sitecore.Links.DefaultLinkManager cos Provider is marked internal :'( */
public override bool AddAspxExtension => this.Provider.AddAspxExtension;
public override bool AlwaysIncludeServerUrl => this.Provider.AlwaysIncludeServerUrl;
public override LanguageEmbedding LanguageEmbedding => this.Provider.LanguageEmbedding;
public override LanguageLocation LanguageLocation => this.Provider.LanguageLocation;
public override bool LowercaseUrls => this.Provider.LowercaseUrls;
public override bool ShortenUrls => this.Provider.ShortenUrls;
public override bool UseDisplayName => this.Provider.UseDisplayName;
public override string ExpandDynamicLinks(string text)
{
Assert.ArgumentNotNull(text, nameof(text));
return this.ExpandDynamicLinks(text, false);
}
public override string ExpandDynamicLinks(string text, bool resolveSites)
{
Assert.ArgumentNotNull(text, nameof(text));
return Assert.ResultNotNull<string>(this.Provider.ExpandDynamicLinks(text, resolveSites));
}
public override UrlOptions GetDefaultUrlOptions()
{
return Assert.ResultNotNull<UrlOptions>(this.Provider.GetDefaultUrlOptions());
}
public override string GetDynamicUrl(Item item)
{
return this.GetDynamicUrl(item, LinkUrlOptions.Empty);
}
public override string GetDynamicUrl(Item item, LinkUrlOptions options)
{
return this.Provider.GetDynamicUrl(item, options);
}
public override string GetItemUrl(Item item)
{
return this.Provider.GetItemUrl(item, this.GetDefaultUrlOptions());
}
public override string GetItemUrl(Item item, UrlOptions options)
{
return this.Provider.GetItemUrl(item, options);
}
public override bool IsDynamicLink(string linkText)
{
return this.Provider.IsDynamicLink(linkText);
}
public override DynamicLink ParseDynamicLink(string linkText)
{
return this.Provider.ParseDynamicLink(linkText);
}
public override RequestUrl ParseRequestUrl(HttpRequest request)
{
return this.Provider.ParseRequestUrl(request);
}
public override SiteInfo ResolveTargetSite(Item item)
{
Assert.ArgumentNotNull(item, nameof(item));
return this.Provider.ResolveTargetSite(item);
}
public override SiteContext GetPreviewSiteContext(Item item)
{
Assert.ArgumentNotNull(item, nameof(item));
return this.Provider.GetPreviewSiteContext(item);
}
}
}

<?xml version="1.0"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
<sitecore>
<linkManager defaultProvider="default-provider">
<providers>
<add name="custom-provider" type="Sitecore.Links.LinkProvider, Sitecore.Kernel"
addAspxExtension="true"
alwaysIncludeServerUrl="true"
encodeNames="true"
languageEmbedding="never"
languageLocation="filePath"
lowercaseUrls="true"
shortenUrls="true"
useDisplayName="false"/>
<add name="alternate-provider" type="MySite.Custom.Links.AlternateProvider, MySite.Custom" … />
<add name="default-provider" type="MySite.Custom.Links.DefaultProvider, MySite.Custom" … />
</providers>
</linkManager>
<sites>
<site name="website"
set:linkProvider="custom-provider" />
<site name="my-custom-site"
inherits="website"
linkProvider="alternate-provider" />
</sites>
</sitecore>
</configuration>

DI FTW. Enjoy.

Leave a Reply

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

WordPress.com Logo

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

Google photo

You are commenting using your Google 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 )

Connecting to %s