Unique global settings object in Sitecore

Most Sitecore solutions have a settings item defined somewhere in the database. They also have settings defined in configuration files (application settings), and although they’re two different types of settings, I never found it necessary to keep them separate. On the contrary, I find applications are much more maintainable if the two were defined together.

My content and client admins would not and could not define settings on their own, so there is no chance of overriding a setting’s value. But I’m getting ahead of myself, as this phrase might not make a lot of sense without seeing some code first, so here it is.

The main idea is to create a class model of my settings item. When the settings item defines CurrencyPrefix and CurrencySuffix, the class model would look like this.

    public class WebsiteSettingsManager
    {
        private Item _WebsiteSettings;
        protected Item WebsiteSettings
        {
            get
            {
                if (_WebsiteSettings == null)
                    _WebsiteSettings = GetItem("/sitecore/content/management/sitesettings");
                return _WebsiteSettings;
            }
        }
        protected virtual Item GetItem(string id)
        {
            Item item = null;
            if (Sitecore.Context.Item != null && Sitecore.Context.Item.Database != null)
                item = Sitecore.Context.Item.Database.GetItem(id);

            if (item == null)
                item = Sitecore.Context.Database.GetItem(id);
            return item;
        }
        protected virtual string GetSetting(string settingName, string defaultValue)
        {
            string value = GetItemSetting(settingName);
            return value;
        }
        protected virtual string GetItemSetting(string settingName)
        {
            if (WebsiteSettings != null)
            {
                Field field = WebsiteSettings.Fields[settingName];
                if (field != null)
                {
                    return field.Value;
                }
            }
            return null;
        }

        //Single-Line Text
        private string _CurrencyPrefix = null;
        public string CurrencyPrefix
        {
            get
            {
                if (_CurrencyPrefix == null)
                    _CurrencyPrefix = GetSetting("CurrencyPrefix", "$");
                return _CurrencyPrefix;
            }
        }
        //Single-Line Text
        private string _CurrencySuffix = null;
        public string CurrencySuffix
        {
            get
            {
                if (_CurrencySuffix == null)
                    _CurrencySuffix = GetSetting("CurrencySuffix", "");
                return _CurrencySuffix;
            }
        }
    }

Defined as it is, I don’t have to pass in a string representing the Setting’s name to a method or indexer, or define string constants for my setting names. Even better, I can define default values for these settings.

The same goes for application settings.

        protected virtual string GetSetting(string settingName, string defaultValue)
        {
            string value = GetItemSetting(settingName);

            if (value == null)
                value = GetApplicationSetting(settingName, defaultValue);

            return value;
        }
        public static string GetApplicationSetting(string settingName, string defaultValue)
        {
            return Sitecore.Configuration.Settings.GetSetting(settingName, defaultValue);
        }

When I now request a setting somewhere in the code it will first be searched for in the database, and then in application settings if not found in the database. Finally, when a setting is missing the default value is returned. One interesting result is that I can override application settings, by modifying the settings item in the database. This will help when I don’t have access to the hosting environment but need to change configuration file settings.

I usually define the website’s logo as a field on the database settings item, or any endpoint as a General Link, so I wrap that ability in here as well.

        private string GetXmlFieldAttribute(XmlField field, string attribute)
        {
            if (field == null)
                return string.Empty;
            return field.GetAttribute(attribute);
        }
        protected virtual string GetGeneralLinkUrl(XmlField field)
        {
            return GetXmlFieldAttribute(field, "url");
        }

        protected virtual string GetImageSrc(XmlField field)
        {
            return GetXmlFieldAttribute(field, "src");
        }
        protected virtual string GetItemSetting(string settingName)
        {
            if (WebsiteSettings != null)
            {
                Field field = WebsiteSettings.Fields[settingName];
                if (field != null)
                {
                    switch (field.TypeKey)
                    {
                        case "image":
                            return GetImageSrc(field);
                        case "general link":
                            return GetGeneralLinkUrl(field);
                        default:
                            return field.Value;
                    }
                }
            }
            return null;
        }

Finally, I like to map fields to types. A checkbox field setting should return a boolean. An Integer field, an int, and so on and so forth.

        protected virtual bool GetSetting(string settingName, bool defaultValue)
        {
            string value = GetItemSetting(settingName);

            if (value == null)
                value = Sitecore.Configuration.Settings.GetSetting(settingName, "");

            if (value == "1")
                return true;
            else
                return false;
        }

        //Checkbox
        private bool? _AutoLogout = null;
        public bool AutoLogout
        {
            get
            {
                if (_AutoLogout == null)
                    _AutoLogout = GetSetting("AutoLogout", false);
                return _AutoLogout.ToBoolean();
            }
        }

That’s the gist, how I like to set it up. I also like to bind it to the request and expose it to xslt files , to make it so that settings are only read once.

To access properties in xslt I use their getter method. With CurrencySuffix for instance, I would use get_CurrencySuffix().

Untested, non-production code.

Leave a Reply