views:

165

answers:

3

I'm wondering if there is an event that can be handled or a method that can be overridden that takes place before the Web.config file is parsed and monitored by the asp.net 3.5 application / AppDomain lifecycle.

The practical reason for this is that I'd like to be able to write the Web.config file from a copy in the database while the application is starting up depending on the deployment environment. The reason for this is because we have a manual application deployment process and a web farm. Web.config changes often fall through the cracks or fail to be propagated to all servers on the web farm because of the manual process. Unfortunately we are going to be staying with a manual deployment process for the foreseeable future. This being the case, it would be great if there was a way for an app to go grab its web config on first startup. If I could get that working, the next logical thing to do would be to create a SQL dependency/notification to cause an AppDomain unload whenever the config file is changed in the databases so new changes would be pulled and written.

So far the only way I've figured out how to manage this is to do something like the below psuedocode that has the unfortunate side effect of causing two application load cycles per attempted start. Additionally, I'm pretty sure the first request that comes in if the app is idle will go up in smoke due to the restart.

// PSEUDOCODE
// In global.asax.cx
protected void Application_Start(object sender, EventArgs e)
{
   bool loadConfigFileFromDB = GetConfigLoadOptionFromLoadOptionsConfigFile();
   string webConfigPath = GetWebConfigPath();

   if (loadConfigFileFromDB)  // Most likely false in development so debugging works
   {                          // with a local web.config

      if (File.Exists(webConfigPath))  // We are not starting up for the first time 
      {                                // since app was deployed
         if (File.GetCreationTime(webConfigPath) < DateTime.Now.AddMinutes(-1))
         {
            // Web config is more than a minute old, so chances are we
            // aren't in an app restart after writing the config.
            WriteWebConfigFromDatabase(); // This will cause a restart.
         }

         // else, web.config was probably just written and we are in a 
         // restart after writing the config. In this case, let the application continue on
      }
      else // First time starting up, so it's safe to assume we can write
      {    // the config and restart.
         WriteWebConfigFromDatabase(); // This will cause a restart.
      } 
   }            
}

Obviously a build or deployment task would be the best way handle replacing the Web.config per environment, but unfortunately I am not in a situation where that can happen.

EDIT: The intent of this is not to have dynamic settings while the app is running, it is to help manage differing Web.config files per environment (Stage/QA/Production). Example, in a separate non-Web.config file we'd have an environment setting. After deployment when the app fired up, it would use the settings in this file (the environment and the connection string) to go pull and write the web config for that environment. The settings would not be dynamic after application startup.

+2  A: 

You are doing weird thing.

UPDATE (also removed unrelated text):
Ok. So you need to automatically propagte new version of the application to all servers. I do not see a reason to do it from application itself. Instead it should be another utility/batch/installer that does this kind of stuff. I believe ASP.NET application deploying itself will hit a lot of issues (what if you will need to deploy assemblies along with web.config)?

I think simple batch-xcopy approach will do the job for you:

  1. Create a .bat file that accepts 1 parameter:Envoronment=[Stage/QA/Production].
  2. Copy all the required files to a separate temporary directory (so you can modify things without touching the original code).
  3. Modify web.config and other things you need (you can use some utility for that) as per Environment parameter.
  4. XCOPY all files to all required servers as per Environment parameter.

There is no need to incorporate the deployment process into the application itself.
For Windows applications it is ok as you can use bootstrapper, but not for ASP.NET.

Dmytrii Nagirniak
Thanks for the answer. I've updated the question and following comments to clarify that I'm not trying to get dynamic configuration at runtime, but rather a way to automatically propagate the Web.config file to a deployed app.
Daniel Auger
I think you have a very good answer for most environments. However in my specific situation the web far is in a DMZ. There is no trust between our development domain and the web farm. A pull of the config makes the most sense. However, I am interesting in hearing what you have to say if I am missing something.
Daniel Auger
To clarify: due to the DMZ we can't batch push an x-copy.
Daniel Auger
To further clarify: we have a web farm on a DMZ. To install the apps, the servers are manually relocated off the DMZ to the LAN. The is no practical way to push files out to the DMZ. I hope this description paints a clearer picture.
Daniel Auger
Did you try to talk to the network admin on this?
Dmytrii Nagirniak
Yes. Unfortunately there are not plans to allow for any sort of trust between the internal network and the DMZ. The only link from the DMZ into the LAN is through the database connection. At this point, we either have to continue to live with the error prone manual process or come up with a "creative" solution such as this one. Obviously I know this is crazy/weird/unconventional, but sadly but after 5 years of botched deployments, we're ready to try something unconventional to solve the problem.
Daniel Auger
Ok. Then maybe you can create a small Windows service that will connect to the database and watch for the changes. If such are found - it updates the web.config. It will always work as it is outside of the Web application.
Dmytrii Nagirniak
I had the same thought today on my run. Good idea! It would solve the double start up issue.
Daniel Auger
A: 

Application_End is the closest event - it fires just prior to the unloading of the AppDomain for the web application. You could just update the Web.config file there.

In principle it should work - the AppDomain is unloaded, so the config has to be reloaded when the AppDomain starts up again, by which time the latest config would already exist on disk.

Also, I'm assuming that ASP.NET stops monitoring the Web.config for further changes, as it has already decided to shut down the application - my only concern is that writing the file again would cause an infinite loop to occur.

It can't hurt to try. It is a weird thing to do though. It would be good to have some more background on why you are needing to do this in the first place.

Sam
A: 

I'm wondering if there is an event that can be handled or a method that can be overridden that takes place before the Web.config file is parsed and monitored by the asp.net 3.5 application / AppDomain lifecycle.

After doing a few days of research I'm going to say the answer to this question is: No, there is no such event that can be handled or method that can be overidden. If someone ever comes along and can show otherwise, I will deselect this as the answer to the question.

Daniel Auger