Magic Mirror, on the wall who has the largest web.config of them all?
Sitecore 8 has a default Web.config file that weighs in at a whopping 244 KB and is just north of 4,000 lines. This presents a number of challenges right out of the gate. This is problematic since the default maximum size for a Web config is only 250 KB. Now, some will chime in and remind us that this is simply a reg key that can be adjusted. However, that should be the absolute last resort for handling a Web config that exceeds the default limit.
Config file management should be one of the first things you think about when architecting your Sitecore solution. Config files can literally make or break your application, particularly when it's time to release it in the wild.
Patch configs are Sitecores answer to modifying or extending the default Sitecore config. Patch configs are loaded into memory at run time by Sitecore. This can cause some confusion, particularly when handing your application off to a release team that isn't familiar with how patch configs work. However, properly managed patch configs can be the difference between a relatively painless Sitecore upgrade, or being stuck in file diff hell.
Organizing Patch Configs
I typically organize my patch configs with the following directory structure.
+-- App_Config | +-- Include | | +-- *My_Application* | | +-- Pipelines | | +-- initialize | | NameSpace.Pipelines.Initialize.Example.config | | +-- httpRequestBegin | | +-- httpRequestEnd | +-- Hooks | +-- Events | | +-- itemAdded | | RunWild.Sc.Events.ItemAdded.AddChildItemRules.config | | +-- itemSaved | | +-- publish | | +-- Handlers | | +-- Rules | | +-- ZZZ
Single Purpose Patch Files
Another convention I like to follow is having only one modification per patch file and naming that file as descriptively as possible. The benefit of this is that you can simply glance through your directory structure and have a pretty good idea of which patch configs are present. This makes troubleshooting a breeze and also helps reduce the possibility of applying the same patch in multiple files.
As a rule of thumb any modifications that need to be made inside of the
Only valid for AppSettings Node <appSettings file="/App_Config/appSettings.config"> Connection String Example <connectionStrings configSource="App_Config\ConnectionStrings.config" />
If your solutions makes use of Nuget, it is important to be aware of the changes made to your base web config during the installation of a Nuget package. For example, the Sitecore Ship module modifies several nodes in the web config and also adds a configuration node of it's own. I would typically only want to deploy those changes to my CM environments, deploying them to CDs creates a scenario where you could accidentally expose an implementation detail on your live website. Changes such as these are subtle and easy to miss, especially if they aren't caught immediately. There is a downside to pulling them out of the base web config however, if you chose to upgrade the Nuget package or uninstall it, you also have to remember to clean up any related config references.
One strategy you could employ to make managing this easier is to use the configSource attribute in the web config. Then create a directory under the App_Config directory with the name of the Nuget package. For each modification that the Nuget package made to the base web config create a corresponding config file. When you create your transforms the transforms will insert/remove/replace the config element with the configSource attribute. You will end up with something that looks like the following:
Transform: <packageInstallation configSource="App_Config\Include\SitecoreShip\Ship.PackageInstall.config"/ xdt:Transform="Insert"> Ship.PackageInstall.config: <packageInstallation enabled="true" allowRemote="false" allowPackageStreaming="false" recordInstallationHistory="false"/>
The advantage of this is now I can do a search in my transforms or web config for SitecoreShip and reliably get every reference in the solution without having to add comments or white space to my config files. This makes diffing configs easier. Also, it ensures that during removal I remove ALL modifications made by the Nuget package install. If I were to delete the contents of the entire SitecoreShip directory the application will throw an error at run time. This makes sure that settings that were changed that otherwise wouldn't throw a run time error are also removed.
I prefer to keep my build configurations to a minimum. This can be difficult if you aren't using tools to provision development environments or enforcing strict standards relating to host names, directory structures/locations etc. A common convention that I have seen is having unique build configurations for each developer on a project. This can quickly get out of control over the life time of a project and become a headache to manage. Newer versions of TDS can help with some of these issues with the introduction of .user files that aren't checked into version control. However, tools such as vagrant to manage environment provisioning make having a single dev configuration a non issue.
Example VS Build Configurations:
Config Transforms VS File Replacement
Outside of the web config I personally prefer file replacement over config transforms when working with homogeneous environments. Currently Visual Studio doesn't support previewing / transforming files other than the web config and app config, there are VS extensions such as SlowCheetah which will add this functionality and the VS product team has indicated that this feature is on their road map. However, at the time this article was written the creator of SlowCheetah has put the project into maintenance mode. Additionally, config transforms add another layer of risk for syntax errors and duplication. File replacement on the other hand is straight forward and explicit.
However, there are instances where you may want to chose transforms over file replacement. One of those may be in situations where you have a large number of small variations in your configurations between environments / dev machines. In this case transforms can be more manageable than file replacement. However, if possible I would look at ways that you could reduce variances between your environments and developer machines.
Below is an example directory structure. Most of the configuration files will exist under the Common directory. From there configs are organized by their role. For example, if we have a patch config that needs to be applied to all Sitecore servers regardless of their role it would live under CM-CD. If a patch config only applied to CD servers, such as removing the Master db, it would live under the CD directory. In the environment specific folders you typically end up with only connection strings and non Sitecore related application configuration files that apply to specific environments or server roles.
+--Environments |--+ Common | +-- CM | | +-- App_Config | | +-- Include | | +-- My_Application | +-- CD | | +-- App_Config | | +-- Include | | +-- My_Application | +-- CM-CD | | +-- App_Config | | +-- Include | | +-- My_Application |--+ Dev | +-- CM | | +-- App_Config | | +-- Include | | +-- My_Application | +-- CD | | +-- App_Config | | +-- Include | | +-- My_Application | +-- CM-CD | | +-- App_Config | | +-- Include | | +-- My_Application |--+ QA |--+ UAT |--+ PROD |--+ DR
One thing to watch out for is what happens to a patch config file after it has been deleted or moved in your project. If your build process doesn't have a mechanism to cleanse your webroot during a build you can end up with some subtle irregularities. Another benefit of doing file replacement is that one of your file replacement steps can be to copy a vanilla version of Sitecore into your web root. In conjunction with a clean that deletes the contents of your web root, you can avoid this problem completely.