Thursday, January 17, 2013

Sitecore Solution Custom Configuration

No matter how many times I look at a Sitecore web.config  I inevitably find something I’ve never seen before, or had forgotten about, or never really understood. There’s such an abundance of settings, pipelines, hooks, events --- all kinds of ways to modify and extend the application.

Good solution architecture should follow that same approach. As much as is practical, functional components should expose custom configuration settings, which allow the solution to be tweaked and extended without the need to deploy code. This includes such thing as connection strings, service URLs and communication parameters, pick list options, content locations, task behaviors, UI factors … anything that code or users need to make decisions about how the application should work.
There are four key places where configuration options can be created and managed:
  1. Web.config
  2. Config files in the /App_Config/Include folder
  3. Sitecore content items (typically in a global “MetaData” or “Settings” node)
  4. Static code classes, exposed as enums, constants, properties or methods
There are other, more obscure methods as well. For example, an application initialization event could create application-scoped objects, or even modify the running config. Cool as all that may be, these techniques are only useful in unusual circumstances, and can complicate analysis and troubleshooting.

There is no single right way for configuration management in a solution; rather, any given configuration setting should be managed in the location that makes the most sense for that function.

Using web.config

It is best to avoid using web.config to store custom application settings. Generally speaking, only Sitecore platform specific configuration should be handled here. Settings embedded within web.config can be a nightmare when deploying and reconciling across environments.
All configuration within the Sitecore section of the web config can be extended and modified within .config files (below). Rather than placing settings in web.config, it is better to group related configuration items within .config files, making management, deployment and troubleshooting much easier.

Content owners cannot make changes to web.config, and developers might not be able to easily make changes here is some landscapes.

Web.config should be used only for very stable, solution-wide settings, and that, rarely (.config files can accomplish the same thing and are more manageable). Ideally, only Sitecore platform specific configuration – things that are part of the Sitecore release --- should be managed in web.config.

Using .config files

Sitecore allows any number of .config files to be created in the  /App_Config/Include folder. These config files require a specific XML structure, and are reconciled with web.config when Sitecore initializes, to create a “running config”. This running config represents what the web.config file would look like if all configuration were managed in one file.

Remember that Sitecore reconciles all of the .config files against web.config at application initialization. It is possible for two config files to modify the same configuration item, and it is difficult to predict what order the .config files will be applied.  Sitecore provides a utility at /sitecore/admin/showconfig.aspx to view the running config, which can be very helpful when troubleshooting.

Well organized .config files are a very powerful way to handle configuration, as related configuration item can be aggregated into a single file. Configuration for settings, pipeline processors, events, etc  can be added to the “running config” here, which has the same effect as modifying web.config, but in a more manageable way. Modifying existing web config entries in external .config files allows the solution to have ‘default” behavior defined in web.config while making server, landscape or application specific changes to be made in separate file in separate environments.

This is the ideal place to manage config in the following circumstances:
  1. The configuration modifies or extends an existing setting, event or pipeline in web.config.
  2. This configuration might need to have different values in different environments.
  3. The configuration related to a module or package that needs to be distributable.
  4. Only developers or administrators should be allowed to change the configuration.

Settings in these files should follow the Sitecore setting syntax.

<configuration xmlns:patch="">
            <!—Items to fetch per connection -->
            <setting name="MyDataConsumer.ItemsToFetchPerConnection" value="10" />

Note the naming convention for the name of the setting node. Using the dotted notation (MySettingGroup.MySettingItem) creates a pseudo-namespace that prevents name collisions. Remember that all settings in config files are merged together into a single running config when Sitecore initializes. Every setting needs to have a unique name when the configs are merged.

 It is a good practice to create an associated class that exposes these settings through properties or static methods.

public static int ItemsToFetchPerConnection
              return Sitecore.Configuration.Settings.GetIntSetting(
                     MyDataConsumer.ItemsToFetchPerConnection", 0);

Not only can .config files extend Sitecore configuration, but they can even change Sitecore configuration by using a patch attribute.  John West’s blog post, “All About web.config Include Files with the Sitecore ASP.NET CMS” discusses config patching, and includes links to more in-depth reading.

In most cases, developers can create and deploy config files, at least within the developer and QA environments. Of course, content authors generally can’t touch config files.

Using content items

It is common practice to have a global settings section of the content tree, usually (not below) the home node. This node is usually called something like “MetaData” or “Settings”.

This is a great place to manage configuration in these circumstances:
  1. The setting is always the same across all landscapes and environments.
  2. Content authors, editors or power users should be able to manage the setting.
  3. The setting relates to interface elements, like the items to be included in a pick list in a data template or rendering parameter template.

Settings stored here are very easy to manage, but there is also some risk. Whenever a setting can affect the stability of the application, there should be tighter control over who can change it. Using security can help protect these settings while allowing them to be managed in the Sitecore UI, but moving them to .config or static classes protects them from UI users altogether.

Rather than creating a template that contains all of the fields needed for a particular “set” of settings, I generally create a several generic “settings” templates, and use them to create items in grouped folders under a “settings” item at the root of the content tree. Some useful templates include: General (text), Link (for references to content items), WebService (with fields for the URL and credential info), and File (for media library file items).

Settings managed in content cannot have different values for CM and CD (unless you use two different items).

The nature of the setting also comes into play. When the setting represents a list of allowable values in a pick list in the content UI, this is really the only place to manage it (because the items in these lists are defined as data sources for the field). The danger is that these values often govern the behavior of code, and unexpected values can cause the code to throw errors. Again, security can help prevent unintended changes to these settings.

Using static classes

Settings in static classes (constants, properties or enums) is the best scenario from a performance perspective, but is also the least manageable method. Changes to these settings can only be accomplished with a code deployment.

This is a good approach for things that should only be changed when code is changing anyway, or only affect code. Static code configuration should also be considered when performance is a concern. For example, there are cases where a known predictable content item must be referenced frequently in code. Storing the GUID of this item in a static class makes the code much more efficient when accessing the item. If the GUID is unlikely to ever change, this is an excellent approach. Note that Sitecore exposes the Sitecore.FieldIDs and Sitecore.ItemIDs classes where the GUIDS of well-known items are stored.

In fact, this is a good way to “bootstrap” settings that are managed in the Sitecore content tree. Create a property in code with the GUID of the folder that contains the settings. This avoids hard-coding the location of the settings, and allows the settings to be accessed even if the location of the settings folder changes.

Settings location guidelines


Config file
Content item
Static class
Types (what does this setting affect?)
Part of the Sitecore platform
Related to code
Related to infrastructure
Related to content
Roles (who manages this setting?)
System administrator
Site architect
Business owner
Environments (CM vs CD)
Same on all environments
Different in each environment
Volatility (how often does it change?)
Risk (impact of a mistake)
Changes affect entire application
Changes affect part of the application
Changes affect availability of data
Changes are cosmetic or content only

More reading...

No comments:

Post a Comment