IIS AppDomain unloading after deployment - asp.net

I'm deploying an ASP.NET application (just a simple Http Handler) to IIS (7.5) and I'm seeing the AppDomain unload after the first request following the deployment.
I'm just doing a simple file system deployment (copying the new files (web.config, bin folder, etc.) to the application location (C:\inetpub\wwwroot.....)) and based on messages being logged from the Application_Start and Application_End event handlers in Global asax, this is what I'm seeing:
The initial file copies cause the AppDomain to unload and I get a message logged via Application_End: the shutdown reason is generally 'ConfigurationChange'.
A request to the application causes the AppDomain to be re-loaded, so I get a message logged via Application_Start.
Once this request has been serviced the AppDomain is unloaded again, this time with the reason 'BuildManagerChange'.
I've tried stopping the application pool before step 1 and starting it again before step 2, but with the same result.
Searching around the web, the usual reason for a 'BuildManagerChange' shut down is that the hash.web file has changed in the Temporary ASP.NET Files folder for the app, and indeed this does seem to be what's happening in this case. As part of the application startup I'm guessing that, as part of the BuildManager initialization, it's calculating a hash of the various files in which it's interested (web.config, global.asax, etc.) and that because this is different to the value currently on file (because it's just been deployed), it's unloading the AppDomain.
So I guess my question is, why doesn't the original AppDomain unload caused by the file copying update the hash.web file? And is there any way for force this? At the moment all of the evidence suggests that it will always go through a shutdown-startup-shutdown cycle before it gets going, but I just can't believe that this is correct. Am I missing something really simple?

Related

ASP.net Web API Singleton doesn't work

I'v used many ways to keep an object instance alive to share it's data between request.But All the methods even dependency injection doesn't work at all.
Finally I've realized that my App get recycled by every request and the reason was I wrote some log files in bin folder.So if you make any change in your bin directory, IIS will recycle your application.

Killing ASP.NET threads

In my ASP.NET application, I have a script that I periodically automatically call to update the database. Due to a bug in this code, several invocation of it entered an infinite loop.
I am on a shared hosting, so I can't just restart IIS. I have tried “stopping” the website from the hosting's management website, but it had no effect.
Since they are running for seveal hours now, I assume there is no timeout configured. So, I would like to kill those “processes” (I assume it's actually just threads), is there a way to do that without contacting my hosting company?
Updating the web.config will stop your application. Assuming you can access the files of the website.
Have you tried stopping the application pool for the website?
I was logging some information from the threads I wanted to kill to a file. The code is able to create the file if it doesn't exists, but the same does not apply, to the folder it's in.
So I temporarily renamed the folder with the log and the threads seem to have stopped.

Using a 3rd party COM dll in ASP.NET

I have an ASP.NET project using a COM dll. When I load the site, I login without a problem and I can browse the site fine as long as I don't go to a page which uses the COM library.
When I go to a page which uses the COM library to get data from a database, the page loads fine. The problem comes when I navigate away form this page. For some reason I am sent back to the login page as if the initial session was dropped.
If I take away the component on the page which displays the data which the library retrieves, I can navigate away from the page, so it is definitely the call to the library that kills the session.
Does anyone have any idea why this could happen??
Fixed it. It was a silly problem. The library created a log file in the bin directory every time it did something. The session gets dropped everytime there's a change in a file in the bin directory because the AppDomain gets destroyed and restarted.
I wonder if the COM component crashes and tears down your application pool (or whatever it's called these days in ASP.NET).
Can you keep an eye on the ASP.NET worker process (it used to be called aspnetwp.exe) and see if it disappears when you navigate to the page with the COM calls?
If so, the COM component probably throws a structured exception, which terminates the process, causing your session state to be lost, if you store it in-process on the server.
You might be able to glean more information from the Event Viewer (Start -> Run -> eventvwr), where ASP.NET logs any crashes.

Is there an event to handle/method to override that takes place before the Web.config is parsed/checked for changes?

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.
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:
Create a .bat file that accepts 1 parameter:Envoronment=[Stage/QA/Production].
Copy all the required files to a separate temporary directory (so you can modify things without touching the original code).
Modify web.config and other things you need (you can use some utility for that) as per Environment parameter.
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.
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.
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.

How to update ASP.Net site dll without stopping site

Is it possible to update the site dll for a precompiled site without stopping IIS.
Currently, if I try to just copy the new file to overwrite the current file, All users receive runtime errors while the file is being copied. Is there a way to avoid this?
even if you don't stop, any change to the web.config file, BIN folder, App_Data or App_Code will force the .NET compiler to perform ...
and you will loose any Session variables in memory.
What I do is to use Session State in SQL Mode and if your system is set up like this, user will remain in the site (after a longer exposition to a page reload)
.NET will still invoke the compiler in order to compile the new set of instructions but soon it is done, all sessions will be read from SQL Server and because they are still there (and not lost with a memory refresh) users will remain in the website with current credentials.
it is a little bit slower than In-Memory Session State, but much more reliable, specially with Shared hosting :) this is the way to increse/decrese the minutes in your session, as Shared hosting do not allow it to change even if you do
Session.Timeout = 5;
their machine configuration will override everything you do, with SQL Session State, you will be able to set your time as this is all made by SQL Server.
Fell free to read this article to know how everything is done.
Hope it helps.

Resources