How to use environment dependent app.config file - c#

We are a group of C#/.NET 4.5 developers working on the same application.
The application has a set of configurations related to each developer machine, like the connection string to the DB, network related settings (proxies, IPs, credentials) and a LOT MORE.
Because the application has grown we are incurring in a lot of environment related configurations like for example:
If this is MyPC then load the connection string for my PC.
If this is the XDeveloperPC then specify proxy’s settings.
Also if new developers leaves or join the group, then the process to update the file becomes a total head ache. Maintaining the file has become very hard and is a possible source of bug and errors.
I was thinking in having specific app.config files related to each developer environment like:
app_MyPC.config
app_XDeveloperPC.config
And when the application builds or executes then specify which one to load as if it where the default app.config of the application. Then, when the application or any class or method refers to a given configuration (like the connection string) is access to this configuration file as if it where accessing to the app.config default file.
I would not want to create a Configuration class that builds immediately when the application starts because then I should have references from every place to this class and the application is quite large, with a bunch of projects and dlls.
I rather prefer to hear some opinions and what do you think should be the best way to achieve this.
Is it possible to achieve this?
How?
Do you know a better approach?

FYI, please note that .NET only loads one config file for the whole application. You could try multiple config files something as like specified here,
Multiple App.Config Files in .NET Class library project
Hope this helps...

You can specify sections of app.config to be loaded from another file. See this answer
However, you might have to customize the above solution, the app.config files and the way configs are organized.
Another approach is to use a custom settings file instead of app.config. This will need some code change to use the config file. This config can either be an XML or a JSON file (JSON is easy to deal with). You can use an inheritance model wherein generic settings come from one file, specific settings come from another file and so on. Also, you can load settings from such file at runtime and change application behavior on the fly.
If you decide to use custom config file, and if you already have lot of code written considering App.config file, you can abstract the app.config calls to a method and let that method deal with where to pull the settings value from. That way you can minimize the code change and keep everything tidy.

Maybe you can use the machine.config file (C:\Windows\Microsoft.NET\Framework\your Framework version\Config\machine.config)

Related

Are strings in web.config compiled into the executable?

The storage admins where I work have bought and configured a new huge NAS system.
Over time all current storage will migrate over there. This means that various network paths will change and this will break some in-house applications. We are reviewing a bunch of old apps the find the ones that use current paths like: \\old-file-system.company.com\Users so that we can modify them.
The old apps I have found all set these paths as strings in the project web.config file. My question is: are these paths compiled into the executable or are they read at runtime from this config file? Can we just modify the paths in the config files and not have to potentially rebuild them or upgrade them to newer .Net versions?
Cheers
The values are read from the config file.
That is precisely the point of config files: to provide the ability to alter these values without needing to redeploy the application.
Note that this may need you to restart the app pool on IIS after making changes. Usually, it should automatically do that when it detects changes to the config file, but from historical experience this sometimes breaks without you noticing.
As an aside: don't forget about alternative config storage methods such as databases.
yes, they are!
it will then depend on the code.
So, As a general rule no.
However, if you added new config items, then they may well not show up.
And if the code used the built in class in place of often used configuration manager to get values?
then you have to re-compile.
But, we also might use this:
vb.net:
Dim rstData As New DataTable
Using cmdSQL As New SqlCommand(strSQL, New SqlConnection(My.Settings.TEST3))
cmdSQL.Connection.Open()
rstData.Load(cmdSQL.ExecuteReader)
End Using
So, in place of config manager, I often use My.Settings.TEST3.
(you get intel-sense). So on build, a class is created for some of those web config files.)
In c#, the above is:
Properties.Settings.Default.TEST3
And again often used due to intel-sense in place of configuration manager.
That class is re-build at compile time. So, if the code used to get web.config values is always configuration manager, then you would/should be ok.
However, if code used the built-in class like above?
The values ARE pulled from web.config at compile (build) time.
the class is called
c#
Settings.Desinger.Cs
vb.net
Settings.Desinger.vb
So, I would check the above two files. That class tends to come from here:
Now the above when we add say a connection string to the project?
The above DOES update and put the above settings into web.config.
However, the class created (settings.Desing.cs/vb?
It is re-generated each time, and it DOES COPY the values from web.config.
So this means that after changing the settings in that project, you REALLY do have to re-build.
As noted, if one came from desktop land, then we just add settings to above, and use them. They actually are created in web config, but we often use the above - since as noted ANY new setting we add to the project now has intel-sense.
So, I would search the source code for:
vb:
My.Settings.TEST3
(search for My.Settings.)
or
c#
Properties.Settings.Default.TEST3
(search for Properties.Settings.)
if either of above are used in the code?
Then yes, you have to re-build since they are re-created at compile time into a class, and the values ARE pulled from web.config at compile time.
If configuration manager was used in all cases, then you are ok.
however, if the designer class was used, then a re-build is required, and worse a change in web.config will not be reflected in that class until a re-build.

Why use ConfigurationManager vs reading custom configuration file?

I've always used my own format of configuration files which is XML and then I just deserialise the XML into an object in my project or just read it into an XML document.
This seems alot easier to read and access the information I need.
I've had a look at the ConfigurationManager class this morning and it seems a bit overly complicated just to read a config file.
Is there any argument as to why I should use ConfigurationManager?
It is just a built-in mechanism in .NET which is already implemented for you, so you don't need any extra code (probably except for wrapping it in your own IConfig to separate concerns).
There is a GUI for editing .NET configuration files which sometimes comes in handy.
ASP.NET application, for instance, automatically restart when web.config has been changed, while you would need some custom logic to have the same behaviour with your own config files.
The ConfigurationManager is used internally and you're not obligated in any way to use it, and I used to do what you do. Nowadays it depends, if it is a file a user is supposed to change I might still do my own configuration, otherwise the file is added as an embedded resource and I use the ConfigurationManager to read it, because I don't think there is another way of reading those files. The thing is, use whatever mechanism you feel like, ConfigurationManager provides a bit more encapsulation though and out of the box utils classes.

Using .NET ConfigurationManager to read settings from a string instead of an app.config file

We are running multiple instances of our service (implemented as a .exe file) on different machines in our data center. However, we would like to store configuration parameters for this .exe file in a central location (as opposed to being in the .exe.config per machine).
To do this, we are planning to move the content of the .exe.config files to an attribute in a central repository (Active Directory or SQL) and make the .exe's running on all machines read from this repository.
I would like reuse all the existing classes used for reading/writing configuration information (using ConfigurationManager, ConfigurationProperty etc., basically using the entire .NET Configuration framework) - however, instead of loading it from the .exe.config file (which it does by default - I want it to load it from a string value of the XML blob that I will retrieve from that central repository.
I was trying to find ways to do it using the ConfigurationManager API but couldn't find anything that could load a Configuration Section from a string. Any pointers?
I suppose you could write your own ConfigurationSection that will then load the real config data from your central repository.
Alternatively, do you have some sort of centralized deployment system in place for installing software on your various servers? How does your service get deployed? Rather than adding complexity to your software you should look for existing tools that already solve your problem.
Although I doubt this is what it was intended for, we've done this in our project using ProtectedConfigurationProvider. Basically, this class is supposed to allow you to encrypt your configuration file but we simply have the Decrypt method connect to our database and return the configuration information. See this for notes on implementing. This felt a little hacky, but we couldn't find any other way without completely rewriting all of the configuration parsing logic.

c# pattern for two applications sharing a configuration file

I have two applications that have many common configuration properties. When a configuration property of one changes, I want the other to change as well. Does anyone have a sensible way to accomplish this before I start off down the wrong track?
EDIT: I'm using .NET 2.0
You can create and reference a common configSource for the configuration section(s) involved. For instance, if you wanted a common set of AppSettings, copy your current appSettings to a new file (say appSettings.shared.config) and replace them in both app configs with this:
<appSettings configSource="appSettings.shared.config"/>
Here's more documentation: http://sunali.com/2008/01/23/configsource-property-dividing-configuration-files-into-pieces/
Far as I know, this cannot be done for an entire file, only sections, and each section will need its own file (and the section must still be declared in the configurationsections element of the app.config). But, this has a number of really cool uses; for instance, you can separate your connection strings into files geared towards different environments (local, development, testing, staging, production) and by changing one filename in one place you've now pointed your app at the different environment.
One easy way to accomplish this is to use the configSource attribute in the app.config in both applications, and point this to a common file. Bingo, change one file, all apps are updated.
Check the MSDN documentation on it here.
there are a couple of different ways you could do this:
use the registry
use a config file in a common location
use a configuration table in a database

Configuring log4net in a VSTO

I've set up my VSTO Excel add-in to use log4net for logging. Unfortunately I'm (seemingly) not able to make it configure itself from the app.config (which I deliver together with the add-in via ClickOnce).
I have read http://www.darinhiggins.com/?p=13 which lists some ways to get the file name of the app.config and then configure log4net with
log4net.Config.XmlConfigurator.Configure(fileInfo)
However the approaches this blog lists seem very error-prone to me (they "smell bad").
Things like
ConfigurationManager.GetSection
make me believe the .NET framework knows exactly where to get the file and there must be a way to retrieve this information from the framework instead of having to figure it out on my own. However, the XmlConfigurator in turn only accepts a file name, stream or xml node...
(Why I believe it's not working at the moment: I have configured it to use a RollingFileAppender with the file name being H:\Data\Debug.log, but after a GetLogger(...).Debug(...), there is still no Debug.log in place...). I have used the exact same configuration in other places, successfully.
XmlConfigurator.Configure(); uses the app.config file. That should work since the ConfigurationManager seems to be able to read the config file.

Categories

Resources