Web.config and App.config file gotchas

If you try to use idiomatic .NET, and you have even modest configurability architecture requirements, you will almost certainly want to use the *.config system (App.config or Web.config). According to old hands at Win32 programming, this is quite a step forward from *.ini files or registry manipulation. Perhaps so.

However, the *.config regime is extraordinarily fragile and surprise-prone once you start trying to do more than just add name/value pairs to the <appSettings> section. The following are some gotchas that I hope you can avoid if you have to deal with this.

.EXE assembies get App.config, and Web DLLs get Web.config, but non-Web DLLs (e.g. tests) get App.config.

.EXE assemblies look for filename.exe.config, which is in App.config format.  Normally, DLLs do NOT get a config file; rather, they inherit / acquire whatever config is in place in their runtime environment.  But there are two important exceptions.  Web services / sites get built as DLLs.  Their execution environment (presumably IIS or the dev server) looks for Web.config and its format.  Test projects (of the MS type that Visual Studio 2010 makes by default) get built as DLLs, as well, but they get run by (mstest? vstudio?) an execution environment that looks for an App.config file.

So, to sum:

  • .EXE => App.config
  • .DLL Web project => Web.config, via its server runtime
  • .DLL Test project => App.config, via the test / IDE runtime
  • .DLL other => none, inherits runtime environment

Sections such as <appSettings> can be externalized into other files, but there are two subtlely different and incompatible ways to do so.

Specifically, you can add a “file” or “configSource” attribute to your appSettings section.  If you use “file,” that file will be read and will override default values that are set in that section in the .config main file.  If you use “configSource,” however, you must not set any values in your .config main file, and instead must entirely scope out that section (and that section alone, save for the XML declaration) in the file whose name you specify.

Frustratingly, “file” and “configSource” have different rules for what may be included (relative / absolute paths, parent directories, etc.).  Especially restrictive are the rules for Web.config, I believe, though I don’t have them straight.  Effectively what this means is that if you have several Web projects that require a shared configuration section, you cannot put your customSection.config in a parent directory and have your projects pull it in (thereby keeping a Single Point of Truth); rather, you have to propagate multiple copies out to all of the sub-Projects (ick).

For more on this: re: configSource, re: file from MSDN.

Web.config settings are mostly inherited from machine.config down through a hierarchy, but confusingly stop being inherited at the sub-directory level in IIS.

Sometimes, or at least most of the time by default, Web.config settings for a given directory are merged with those of parent directories, and are merged with machine-level config as well.  This can lead to somewhat unfortunate results if you have an app in a subdirectory of another app with divergent configruation requirements.  This fellow seems to have figured out how to resolve this.

Be alert, though, because not all settings *do* propagate properly.  First, a parent Web.config can indicate that its settings should not be inherited.  Second, collection settings are merged together, not replaced, by child specifications.  Third, some settings, just seem stubbornly not to propagate (see this MSDN article which suggests that “anonymousIdentification” does not propagate because it is a secret never-properly-set default magical element).  Finally, the above-quoted MSDN article raises the good point that Web.config only applies to ASP.NET stuff, and that there is an entirely different regime for static content and plain old ASP files.  So watch yourself, there, Tex.

Leave a Reply