views:

825

answers:

4

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.

.

+2  A: 

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.

Precipitous
+2  A: 

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"); 
    }
emanyalpsid
In the lack of better answers, this will be the "accepted answer", it will stay in this way until new updates.
emanyalpsid
A: 

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.

ctford
A: 

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.

Fábio Batista