I've been using the .NET
config files lately, and its been rather frustrating lately because of the confusion that arises when running a bunch of different ways to access the same code.
In my scenario, I have a class library called
DBAccess.
dll and I call it in the following ways:
1. From a web site using the ASP.NET built in web server launched from VS 2005.
2. From a web site running in
IIS.
3. From a forms application
4. By running
TestDriven.NET using a
seperate test assembly.
5. From a windows service.
In all these cases, I'm expecting to get configuration values through the main configuration file for connection string so that it can be used by Microsoft Enterprise Library.
With so many options, .NET doesn't make it easy for you because of the differences in naming conventions on the default configuration file, e.g. in the case of a web app it expects a web.
config, a forms app expects an app.
config and if you run the
NUnit application it wants the assembly
config file, e.g. DBAccess.dll.config. Maintaining all these configuration files is a nightmare!
So in sorting through this, I came up with a few basic strategies to combat this configuration file overload:
- If you add an App.Config file to your class library project, it will automatically translate this into Assembly.Dll.Config for you.
- For NUnit, it expects a config file that is rooted to your test assembly. It does not read any dependent assemblies config files, app.config, web.config, etc. even if its the same directory of your assembly. Alternatively, you can add configuration information directly into the app.config file of the NUnit executable (either the GUI or the Console) but this isn't a very portable approach.
- If you have an App.Config file and an assembly config file, .NET will always read the App.Config file. It does not by design read your assembly specific config files. There is some code floating around that can do this for you if you want to have more distributed configuration mechanisms that are attached to assemblies instead of executables. This is one way to mitigate the problem of re-using an assembly across multiple projects where some are web projects and some are forms projects.
- Another great alternative is to use proper build files instead of the default studio builds. Either MSBuild or NANT will allow you the flexibility to store a single configuration file and rename it and then deploy it to the appropriate destination. The tricky part would be that you may need a configuration file named Assembly.Dll.config for your unit tests if you've incorporated them into your build process and a final App.config or Web.config for running the executable.
- Another great idea that I have used before is to use the Microsoft Enterprise Library to specifiy an external configuration file. This removes the naming problem with your configuration files in that you can have a seperate external file that represents the master configuration file and simply have Web.Config, App.Config, Assembly.Dll.Config point to your external file. This works quite nicely in my experience as long as you remember to add the external file to your project and to configure studio to always copy it into your build directory.
- You can build your own configuration loader. I have done this with custom defined configuration sections by having code in the custom section that contains a path to an external configuration file. You can arbitrarily load up any configuration file in code and grab whatever sections out of it. This is really useful for custom configuration sections where you want to provide code that saves and loads the configuration file with an arbitrary name. One important note with this strategy - there are cases where the Enterprise Library does the configuration loading for you, e.g. the DatabaseFactory will load connection strings for you automatically. In these cases, you cannot provide a configuration section or source as an object so you're stuck with the App.Config, Web.Config, etc. as a starting point.
- The ConfigurationManager in .NET allows you to open the Machine.config file. You might want to peer into this file directory to look at global values instead of your local App.config values.
- You can use a complete different configuration framework - no is forcing you to use App.config just because it's there (although most people do so). For example, look at Nini as an option (although I haven't tried it yet!)
I hope that provides some ideas on how to manage configuration files in a way that will allow you to have more re-usable configuration schemes than a basic App.config or Web.config file so that it can be used across multiple projects and different application contexts.