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.
Related
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?
I've got an ASP.NET application running on IIS 7 with multiple application domains, and I can't fathom why there are multiple app domains in a single process. I've grepped my code base, and I'm not explicitly creating a second application domain. Is it possible that a recycle has failed to time out?
These double domains will persist for sometime.
If a recycle occurs because of a web config or binary change, both app domains will go down, and two new ones will start up.
These servers are subject to several binary patches and IISResets per day - sometimes there are 2 domains, sometimes only 1.
Web gardening is disabled.
I discovered this because there is a timer in the application heart-beating to the database, and noticed one day the server had two heartbeats.
In windbg, !dumpdomain shows me the following result: (filtered to only show names of app domains):
Line 59: Name: None
Line 66: Name: None
Line 372: Name: DefaultDomain
Line 460: Name: /LM/W3SVC/1/ROOT/MyAppDomain-1-129882892717131250
Line 4437: Name: /LM/W3SVC/1/ROOT/MyAppDomain-4-129285605131450579
Even though you aren't creating an AppDomain, a library that you are using might be. What third-party components are you using? Do you have any Inversion of Control or Dynamic Proxy libraries that might be responsible? Here's an explanation of this happening with Castle.
Are you sure the application is only running in one place in IIS? It's possible to have multiple IIS sites/applications running off of the same files. This would be consistent with (1) getting your debug info from the db, rather than the app, and (2) the recycle due to editing web.config consistently resulting in duplicate domains. If one location is more commonly accessed than the other this could explain why there is sometimes only one AppDomain.
If you are leveraging ASP.NET's dynamic compilation and shadow copying feature, ASP.NET will at times have multiple AppDomains. Jim Schubert wrote an article called ASP.NET, AppDomains, and shadow-copying which explains this in more detail as well as makes several suggestions as to how to modify web.config to customize this. He also has a helpful answer over at Does my ASP.NET application stop executing if I overwrite the DLLs? Shadow copying can be disabled by setting <hostingEnvironment shadowCopyBinAssemblies="false" />.
Update
I got sucked into Jim Schubert's blog and ended up reading this unrelated post on Allowing Only A Single Instance of a .NET application. If all else fails, you could use this approach to ensure only one instance of the application is running.
May have a look at your ApplicationHost.config.
have a look at: maxProcesses it should be 1.
It seems your IIS starts multiple worker-processes.
As suggested by the following answer https://stackoverflow.com/a/3318367/2001769
in another thread, it seems the ASP.NET runtime keeps a pool of HttpApplication instances (irrespective of maxProcesses / Web Garden).
I don't know if is possible, or even desirable, to control this pool. The best practice could be to instantiate all application singletons in the Application_Start event that is supposed to run only once per application and not once per pooled HttpApplication instance.
If there are multiple IIS Applications targeting the same path. An AppDomain will be created per such IIS Application if the app is invoked.
For example:
http://myServer/App1
http://myServer/App2
If both target the same path they still count as two different applications and two AppDomains will be created.
I have an ASP.NET project which is a front-end to a database. In addition to the large tables, the DB contains a few small tables to help normalize the larger tables with common values. I have a VB.NET project which loads the smaller tables into memory, using "Shared" (i.e., "static" in C#) member variables, and uses them. I have a call to load the tables in Global.asax - Application_Start. This works for a while. That is, Application_Start runs when I first run my project, loads the cached values, and will correctly keep them in memory for a while.
What I'm seeing (when running my project via Visual Studio 2008 Debugger, hosted locally) is:
A) The Application_Start code will run more than once. Not in a row, but after the user has navigated to some other pages, I'll see (my breakpoint in) another call to initialize the cache, coming form Application_Start. Is it expected?
B) The "Shared" variable that was set to True when the cache was initialized is now False again (which should only happen when the class is first loaded). Similarly, all the data that was chached is no longer present. That is, it looks like VB is unloading all the Shared members. Is this expected?
If these are the expected behaviors, is there a way to do what I want? The code is in a module that is also used by other (non-ASP.NET) projects, and seems to work correctly for them. I'd rather not have to duplicate this functionality for something specific to ASP.NET, but would like to know what my options are. Thanks for any advice.
Here is an article you might find helpful about Caching Data at Application Startup. It sounds like you are doing everything right, but Application_Start should only get called once, unless some external change happens that restarts the app pool, but in this case i would think you would get detached from the debugger (assuming you are attached to the app pool process for your asp.net application).
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.
Basically I want the effect that would occur if I were to edit the web.config file. The application basically completely unloads itself and starts again, thus re-firing Application_Start and also ditching any dynamically created Types created by the now-defunct AppDomain.
EDIT
I need to do this in my C# code inside my web application. I know it can be done; I did it ages ago but have since lost the code and forgotten how I did it.
For full trust you can use HttpRuntime.UnloadAppDomain(). If you aren't running in full trust you can modify the last write time on the web.config file. Rick Strahl has wrapped these two approaches up in a nice class.
You can "touch" the web.config file (i.e. rewrite it to disk unchanged), or any file in the bin directory to recycle the application. Of course this means the identity under which your application is running needs appropriate permissions.
Lately I seem to be answering my own questions a lot :P
Here we go:
HttpRuntime.UnloadAppDomain();
If all the options above fail, you can also create an endless recursive function as a final resort. The resulting stackoverflow exception will force a reload of the application. (don't do this when you have the visual studio debugger attached)
In IIS you can recycle the worker processes. You don't need to restart IIS.
http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/24e3c22e-79a9-4f07-a407-dbd0e7f35432.mspx?mfr=true
If you have created a separate application pool for your application, you can reset the Application Pool.
In general, it's always a good idea to have separate app pool's for each application.