Problems with Web.config and App.config


Intro:

  • Normally we store ConnectionStrings and some other settings (<appSettings> <add key...) in the Web.config or App.config.

My scenery:

  • Web application using factory pattern
    with direct injection to read data
    providers.

  • In the web.config I have the key
    that tells me which DLL (provider)
    will I use to retrieve my data.

  • I can have more than one provider
    (each DLL will be a provider for MS
    SQL, MySQL, or get the data from
    some SOA service).

  • Each DLL has his own name (ID and namespaces) and will need to have is own
    configurations (dataconnections,
    service urls, etc…) , the first
    idea is to write then in the
    app.config.

Problems:

  • #1 – The website is running (runtime) I need to change the Data Provider, how can I do this? Somehow the default value written in the Web.config will be changed.

    • My objective is to be able to have multiple providers (and during runtime: add/delete providers and change configurations) – this leads me to my second problem:

    .

  • #2 – Each Data Provider has custom configurations and App.Config files do not work with dll assemblies, only executables. This means that I need to write then on my Web.Config (I do not like this option, because once again I am updating my web.config in runtime). how can I solve this?

    • I am trying to avoid to write a custom settings XML file. My ideal solution is to deploy somehow the DLL and DLL.config per each provider. And once again during runtime I may need to change this configuration values.

.

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

Ok guys, while I was waiting for some help I put my hands to work and I was able to find a good solution (in my opinion of course :P).

Let me share it with you:

So, I have one web application, or one console application, or some other kind of application, and lots of class library, and I need to store informations (different per Visual Studio project) that will change during runtime.

Storing this information inside the Web.config or App.config is not a good idea for the many problems it takes.

The other way I see it is to have one XML config file per project.

Each application will read his own XML and add it to the Cache with CacheDependency (will expire when the XML config file is updated). This way we will not need to read the configuration all the times, and we also know when the configuration is changed.

IMO THIS IS THE FASTEST AND EASIEST WAY TO SOLVE THE PROBLEM, no need to use 3rd party frameworks (neither the time it takes to learn/program it).

.

Example code:

    protected void Page_Load(object sender, EventArgs e)
    {
        DBConfiguration cachConf;
        cachConf = Cache["cachConf"] as DBConfiguration;
        if (cachConf == null)
        {
            cachConf = new DBConfiguration();

            XmlDocument doc = new XmlDocument();
            doc.Load(HttpContext.Current.Request.PhysicalApplicationPath + "bin/MyConf.xml");
            XmlNodeList xnl = doc.GetElementsByTagName("username");
            XmlElement xe = (XmlElement)xnl[0];
            cachConf.Username = xe.InnerText.ToString();
            xnl = doc.GetElementsByTagName("password");
            xe = (XmlElement)xnl[0];
            cachConf.Password = xe.InnerText.ToString();               

            Cache.Insert("cachConf", cachConf, 
                new System.Web.Caching.CacheDependency(
                    HttpContext.Current.Request.PhysicalApplicationPath + "MyConf.xml"),
                    DateTime.Now.AddMinutes(60), TimeSpan.Zero,
                    System.Web.Caching.CacheItemPriority.Default,
                    new System.Web.Caching.CacheItemRemovedCallback(
                        CacheItemRemovedCallBack));
        }
        LabelUsername.Text = cachConf.Username;
        LabelPassword.Text = cachConf.Password;            
    }

    private void CacheItemRemovedCallBack(string key, object value, CacheItemRemovedReason reason)
    {
        //Response.Write("Hello world"); 
    }

Solution 2

You could store the credentials in a secondary config file referenced from web.config as follows:

<appSettings file="AppSettings.config"/>

You would still need to be careful to avoid editing conflicts on the external file.

Solution 3

Problem 1 – Runtime changes:
The solution that Microsoft hopes you apply to this type of problem is to simply keep the web server stateless. When an ASP.NET application recycles, it lets existing requests complete new requests start on a new process. For background, read about IIS Process Recycling. A change to web.config recycle the worker process, but users will not notice this (unless you keep state in the web server process). That’s the MS design.

If you want to monitor for changes without recycling a process, you’ll want something other than default web.config behavior. An example that comes to mind are cruise controls project files. They have a component that maps objects to and from xml, using that, you can use the FileSystemWatcher class to monitor for changes.

Problem 2 – Custom configurations:
It sounds like you have components from different libraries that have different dependencies. Your main assembly needs a means to instantiate a service, with a given set of dependencies. The MS data provider model is cool, but not this cool.

To be this cool, use an inversion of control container, because this is exactly what they do. I like autofac (because I like the Philip K Dick reference), but castle windsor is great.

Now, if you are talking about changes databases or data providers on the fly, it may be that configuration is not the right place. If your are reporting against x databases of y types, you need a central repository of that database information, and a configuration file is not the right place, nor is an IOC container the right solution.

Solution 4

As Precipitous suggested, try Castle Windsor:

http://www.castleproject.org/container/

You’re doing Inversion of Control manually. Windsor will take the burden off of you.

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply