Create global configuration file for .net app - c#

I have a big application that has lots of app.config and web.config files.
I also have 4 environments so for each environment i need to change specific config values to match the working env.
I feel it is a waste of time doing it manually each time and leaves a lot of room for mistakes when changing values.
Do you know a way to make it easier working with all those config files?
I also need a way to deploy them to other servers (each config to its own server and folder).
Thanks,
Chen.

The steroid approach is the :
http://social.msdn.microsoft.com/Forums/vstudio/en-US/1bec3733-0d42-4d06-af61-5225bddbdb54/how-to-implement-configuration-service-50-of-the-stocktrader-50-sample-application
Configuration Service the StockTrader Application.
EDIT.............
The poor man's way is to zip up your config files SEPARATE from your binaries.
And zip up the config files in their own zip file. That way, you "have them" if you need them, but you don't accidentally overwrite them on fresh deploys.
And if you add values to the config files, put them in your release notes.
Also, throwing good ArgumentNullExceptions (or similar) in your app when something from the configuration file(s) is not there........is a best practice.

Related

Application Settings in MVC5 Web App - Using C# class vs Web.Config?

I'm building out my application and I'm at a point where I've hardcoded a lot of settings at the top of my class files - stuff like ApiSid and ApiKey, SmtpServiceUsername, MyEmailPassword etc. I'm now trying to consolidate these and I see two options:
1) Push them all into web.config. I don't like the thought of muddling up my web.config with tens (almost 100) settings though... I also feel uncomfortable with security here.
2) Build a static class that just contains these settings (Settings.cs) - basically housing a bunch of constants that are referenced throughout the app.
I feel more comfortable with the second approach because I can keep my settings totally isolated and not worry about exposing them via web.config - is there anything inherently wrong with this approach?
is there anything inherently wrong with this approach?
What makes you think putting constants in the code is any more secure than in the config? The compiled DLLs are right there next to the Web.Config, if somebody can examine one of them they can examine the other one. Hard-coded values can be de-compiled pretty easily.
Config files exist for a reason. Specifically, if any value is going to change per environment then it belongs in the config file. That way the same identical codebase can be used in any environment (development, test, production, etc.) and you'd just edit the config values for that environment. Having to re-compile the code just to deploy the same version to a new environment is less than ideal, since it's no longer the same version.
I don't like the thought of muddling up my web.config with tens (almost 100) settings though
Why not? If they're all flat static values, a list of appSettings keys would be fine. If there's more structure to them, create custom config sections.
This is not necessarily the best approach but I'd store these kind of settings in the database. This gives you database security for the settings plus it's easy to update the settings without having to stop / restart the application so you avoid kicking out users.
Once you have your settings in the database, you can load them periodically (like every 15-20 minutes) to detect changes. In the meantime, create a dictionary of the data and either wrap it in a class that provides type-safe access through properties or just use the dictionary directly. Since this is web application, you'll have to use a thread-safe class (like ConcurrentDictionary) to make sure multiple threads can safely access your settings.
If you have so many settings, web.config would be cluttered and every change would force an app pool restart. As #David mentions in his answer, the config file gives you an easy way to have different settings for different environments but this is also easy to do with a database approach where settings may be present once per environment.

RollingfileAppender failed to respond due to some specific configuration even-though the AdonetAppender works fine

In normal separate XML file configuration i place in my root directory my application works just fine with both appenders.
However, I have found an easy and more efficient way to configure from an external file Which allowed me the flexibility of using the same config file for different applications...
Also one more advantage is I dont need to make any modification to the global.asax and assembly.
Here is the code which i added to my web.config
<appSettings>
<add key="log4net.Config" value="C:\\log\Log4Net.config"/>
</appSettings>
This code is suppose to put the config file in my root directory. And all I needed to do was reference the log4net.dll and start logging.
Even-though my AdoNetAppender is completely working fine and i am seeing the messages instantly in my table.
But my fileAppenders arent creating any files neither logging the messages to existing files. Is this way only compatible with database or I'm missing something?
You can set the LockingModel of the RollingFileAppender to MinimalLock to force the appender to open and close the file for every logging event. Not exactly efficient, and there is still a possibility that one application will not be able to log if they try to log at the exact same time, but if your logging frequency is low enough it may be sufficient.
A better solution is to use a pattern string for the file name of the appender that includes the application name; that way, different applications can use the same config file, but will write to different log files. In most cases the "%appdomain" variable will work for that purpose (although for web or ClickOnce applications you have to get a little more creative).
It's not possible with the standard RollingFileAppender to log into one single file from multiple processes because the appender locks the file to write in it. The log4net FAQ provides a solution for this.
See log4net FAQ
Regards

Using the database to hold application settings

I am looking at ways to make our application more extensible and easier to manipulate without having to alter the web.config (or, in our case, application.config files, which contain the appsettings node).
One way I have thought about is keeping the app settings in the database table that has a sqlcachedependancy. This means that:
Any time a setting is changed in the database, the cache is invalidated, and the settings are retrieved again, thus updating the application in realtime without having to alter files and restart the entire app.
We can create a custom tool which allows us to alter the settings.
The cons as I see it are that this may cause serious logic problems in that, if you have something that checks an appsetting at the start of a process, and it then changes halfway through, you could end up unintentionally altering the process flow, as the requirement for a complete application restart is negated.
Is there a way round this?
Is there a better way to manage appsettings, so that you can alter them on the fly remotely for one, several, or all servers in one go?
I think you've nailed the two major players:
either you have access to the file system and you put all your settings in a plethora of *.config files there
OR:
you don't have access (or only very limited access) to the server's file system and thus you're probably better off putting config settings and user preferences in a database, basically leaving nothing but the connection string to the config file on disk
Both approaches have their pros and cons. I've been trying for a long time to find a way to "materialize" a config section from a database field, so that I could basically just use the config XML, but stored in a database field. Unfortunately, the entire .NET 2.0 config system is very much "locked down" and just only assumes data will come from files - there's no way to plug in e.g. a database provider to allow the config system to read its contents from a database field :-( Really too bad!
The only other approach I've seen is a "ConfigurationService" in the StockTrader 2.0 sample app provided by Microsoft, but for my needs, it felt like overkill and like a really complex, really heavy-weight subsystem.
You could use SQLite, which will be a self-contained DB in a single file. Two birds with one stone?
If you reference an external config file that contains appsettings (leaving everything else in the normal app.config) then I believe editing it only reloads those settings, it doesn't force the whole app to restart.
There's a similar question on the subject here:
Nested app.config (web.config) files
WRT the problem of values changing in the middle of program execution, I guess you could locally cache the values, and raise an event when they change, allowing routines to reach a suitable point before using the updated values.
I think in asp.net we sort of get this for free because each page lifecyle is distinct, so the value is simply applied to new page requests only, not in the middle of an execution.
Edit: A little extra info:
Configuration Changes Cause a Restart of the Application Domain
From MSDN:
Changes to configuration settings in Web.config files indirectly cause the application domain to restart. This behavior occurs by design. You can optionally use the configSource attribute to reference external configuration files that do not cause a restart when a change is made. For more information, see configSource in General Attributes Inherited by Section Elements.
More information on the ConfigurationManager class in the System.Configuration namespace which could be used to modify the config files programatically (ie in a custom tool, if relevant disk read permissions can be provided). If you stick to using the built in configuration classes, I think changing the external configs, would not cause application restart, but would raise events (such as property changed) which you could handle, to ensure your code is not caught out by changing settings.

Why do Settings.settings files dump all their values into the app.config?

Why do Settings.settings files dump all their values into the app.config?
Its not that much of a big problem, however, my application is getting larger and I think grouping them into separate files would help me organise things better. I was thinking of just creating multiple settings files, which is fine, but app.config is blowing up mighty big.
What's everyone's take on the app.config? Do you really care about it since logically everything is grouped in your solution or do you like to have some order after the deployment as well?
for some sections you can specify external config files ... just as a hint :)
eg
<appSettings configSource="appsettings.config" />
edit:
your app.config will get smaller due to swapping out the settings to a seperate file. you can then seperate from production and test settings (maybe in the build process, eg. this or this)
more info here
edit:
found another solution to not swap a whole section out, but add a delta to a section (more info here)
eg
<appSettings file="config.config">
edit:
short answer: you are probably using not the user-property for your settings, so your settings will get stored in the app.config (or .dll) to basically not be changable during runtime (there are some "hacks" for that). if you want to change your settings, use the user-property!
here's a nice description...
ps.: sorry for editing so much! :)

Letting several assemblies access the same text file

I've got many assemblies/projects in the same c#/.net solution. A setting needs to be saved by people using the web application gui, and then a console app and some test projects need to access the same file. Where should I put the file and how to access it?
I've tried using "AppDomain.CurrentDomain.BaseDirectory" but that ends up being different for my assemblies. Also the "System.Reflection.Assembly.Get*Assembly.Location" fail to give me what I need.
Maybe this isn't something I should but in a file, but rather the database? But it feels so complicated doing that for a few lines of configuration.
Put the file in
Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
"[Company Name]\[Application Suite]");
Personally, I would be leveraging the database because the alternative is either a configuration headache or is more trouble than it's worth.
You could configure each application to point to the same file, but that becomes problematic if you want to move the file. Or you could write a service to manage the file and expose that to clients, but at this point you may as well just use the DB.
Thought about storing it in the registry or in Isolated Storage? Not sure if multiple applications can share Isolated Storage or not, though.
projects can have build events -- why not add a post-build event to copy the file to all required locations?

Categories