Multisite configuration management with an Enterprise Accelerator

One major consideration you have to make when building an enterprise layer is the flexibility of the component library itself. The components and functions provided by your enterprise layer have to be created in a tenant-agnostic way. This means that they should not understand the tenant layer (aka project layer in Helix terms) or which website may be using them. They simply exist to serve the tenants.

One easy trick that I’ve been using across many of my projects is allowing for the generic Enterprise components to allow for a configuration fallback.

Configuration Fallback

Let me explain. The idea is simple. At the enterprise layer, I want to provide a default configuration value that may be stored in a configuration file. Let’s assume this configuration value is for an API Key for the FooBar service:

 

<sitecore>
  <settings>
    <setting name="FooBar.ApiKey" value="XYZ" />
  </settings>
</sitecore>

Given that we’ve set this up, we can write code like this to extract it:

var setting = Sitecore.Configuration.Settings.GetSetting("FooBar.ApiKey");
// setting is "XYZ"

So, assuming that I’m making a generic component that uses this API Key, how can I handle this configuration setting being a different value per-tenant?

The solution is Configuration Fallback.

To pull this off, it’s quite simple. I will introduce configuration that looks like this:

 

<sitecore>
  <settings>
    <setting name="AcmeCo.Alpha.FooBar.ApiKey" value="ABC" patch:source="Project.Alpha.config" />
    <setting name="AcmeCo.Gamma.FooBar.ApiKey" value="123" patch:source="Project.Gamma.config" />
    <setting name="AcmeCo.Enterprise.FooBar.ApiKey" value="XYZ" patch:Source="Foundation.FooBar.config" />
  </settings>
</sitecore>

Notice that the Alpha and Gamma sites have introduced a custom setting, while the Enterprise layer provides a default setting from Foundation.FooBar.config. All settings files are named intelligently to help with quick debugging when glancing at /sitecore/admin/showconfig.aspx.

To implement the configuration fallback, I introduce a service that all layers can utilize:

 

namespace Enterprise.Configuration.Services
{
    public interface IConfigurationManager
    {
        string GetSetting(string settingName);
    }
 
    public class ConfigurationManager : IConfigurationManager
    {
        public string GetSetting(string settingName)
        {
            var organization = "AcmeCo"; // replace with your convention as necessary
 
            var siteName = Sitecore.Context.Site?.Name;
 
            if (siteName != null)
            {
                var localSetting = Sitecore.Configuration.Settings.GetSetting($"{organization}.{siteName}.{settingName}");
                if (localSetting != null)
                    return localSetting;
            }
 
            var enterpriseSetting = Sitecore.Configuration.Settings.GetSetting($"{organization}.Enterprise.{settingName}");
            if (enterpriseSetting != null)
                return enterpriseSetting;
 
            return Sitecore.Configuration.Settings.GetSetting(settingName);
        }
    }
}

Which results in this:

var configManager = new ConfigurationManager(); // we'll cover injecting dependencies next
 
// Assuming that Sitecore.Context.Site is Alpha:
var setting = configManager.GetSetting("FooBar.ApiKey"); // resolves to "ABC"
 
// Assuming that Sitecore.Context.Site is Gamma:
var setting = configManager.GetSetting("FooBar.ApiKey"); // resolves to "123"
 
// For any site that doesn't explicitly call out this config value:
var setting = configManager.GetSetting("FooBar.ApiKey"); // resolves to "XYZ" as the 'enterprise default'

In doing this, I’ve now created a foundational element that all components can use. Remember: your Enterprise components should not have any logic directly related to a tenant website. Instead, you can utilize configuration injection techniques to resolve dependencies and settings at runtime!

Bonus

You can also attach settings to your site definition and fallback to this if you choose.

For instance, assuming that my site definition looks like this:

 

<sitecore>
  <sites>
    <site name="Alpha" ... FooBar.ApiKey="ABC" />
  </sites>
</sitecore>

I can then extract this configuration via this code:

var setting = Sitecore.Context.Site.Properties["FooBar.ApiKey"];

Happy coding!

Dylan McCurry

I am a certified Sitecore developer with a passion for the web. I hopped into the .NET space 5 years ago to work on enterprise-class applications and never looked back. I love building things—everything from from Legos to software that solves real problems. I have a strong foundation of backend skills, with sweet spots like security, portal solutions and APIs. Early on, before I had the benefit of SCORE, I made a lot of mistakes with Sitecore but learned a lot in the course of the struggle. I would like to support other developers by contributing my perspective on doing things “the Sitecore way,” rather than fighting the framework. Did I mention I love video games?

More posts from Dylan McCurry >

Add a Comment

Your email address will not be published. Required fields are marked *

Or request call back