How to prevent an ASP.NET application restarting when the web.config is modified?
Asked Answered
T

5

38

I'm hosting the ASP.NET runtime via the ApplicationHost.CreateApplicationHost method. When I modify the web.config while the application is running, i see lots of first chance ThreadAbortExceptions thrown. This is right before my application comes crashing down. I'm assuming this is because the runtime has detected changes to the configuration and wants to restart.

This isn't really a supported scenario for us, so i'd prefer if I could just switch off the automatic reloading.

Does anyone know how to do this?

Tracheo answered 5/3, 2009 at 6:58 Comment(1)
<compilation debug="true" numRecompilesBeforeAppRestart="15000">Cynde
R
28

As far as I am aware there is no way to disable this behavior, changes to the webconfig force the application to be restarted.

Update: it is actually possible, there are a number of methods, well documented, as explained in this answer*

Original answer:

There is a similar question here just for other reference. I found additional info that may be helpful.

Configuration Changes Cause a Restart of the Application Domain
Changes to configuration settings in Web.config files indirectly cause the application domain to restart. This behavior occurs by design. You can optionally use the configSource attribute to reference external configuration files that do not cause a restart when a change is made. For more information, see configSource in General Attributes Inherited by Section Elements.

From This MSDN Article

* Disclaimer: I wrote the other answer and normally wouldn't make a self-reference, but find it relevant enough to link here since 8 years after this post it is really quite different: a solution is very easy by clicking through the IIS front-end, and workarounds exist since ASP.NET 1.0.

Reversioner answered 5/3, 2009 at 7:4 Comment(5)
Correct me if I'm wrong, but I believe that external configuration files will also restart the application?Desberg
OK I guess that MSDN article says that the don't cause application restarts, but does that mean that the config settings don't get loaded right away?Desberg
OK I just did some investigation, and on my ASP.NET 3.5 site, the App Pool did NOT restart, and the updated Setting Value WAS reflected in the web page. However, I still feel like I have seen a web app that WOULD reset when external configuration files were changed. Maybe there was something special about that app, or maybe it was an older version of ASP.NET.Desberg
It is very well and easily possible to change this default behavior (and already so since Windows 2003), see my answer below.Kaye
Using .Net 4+, we have not been able to consistently get the AppDomain to restart by modifying external config fileHaircloth
K
35

Actually, the first two answers are incorrect. It is possible, and quite easy, to prevent this recycling from happening, and this feature has been available since at least IIS6.

Method 1 (system wide)

Change the DWORD registry setting for HKLM\SOFTWARE\Wow6432Node\Microsoft\ASP.NET\FCNMode to the value 1, which will disable all file change notifications.

Don't be confused by the location: Wow6432Node has, in this case, no influence on the bitness of your web application.

Method 2 (.NET 4.5+)

If you are using .NET 4.5, then it is now possible to disable this on a per-site level, simply use the following in your web.config:

<httpRuntime fcnMode="Disabled"/> 

Method 3 (IIS6+)

Finally, and also (at least) around since IIS6, there's a setting called DisallowRotationOnConfigChange as a setting for only the application pool (at least that is what I think the text on MSDN tries to say, but I haven't tested it). Set it to true and changes to the configuration of the application pool will not result in an immediate recycle.

This last setting can also be set from Advanced Settings of the application pool:

Disable Recycling for Configuration Change

Method 4 (ASP.NET 1.0 and 1.1)

For (old) websites using ASP.NET 1.0 or 1.1, there is a confirmed bug that can cause rapid and repeated recycles on file changes. The workaround at the time was similar to what MartinHN suggested under the main question, namely, something like the following in your web.config:

<compilation 
   debug="false"
   defaultLanguage="vb"
   numRecompilesBeforeAppRestart="5000">

This does not disable recycling, but it does so only after 5000 recompilations have taken place. Whether this number is useful depends on the size of your application. Microsoft does not clearly say what a recompilation really is. The default, however, is 15.

As an aside: regardless of the version of .NET or Windows, we find that when the application is run from a share and used in a load-balanced environment, that the site recycles continuously. The only way to solve it was by adding that FNCMode setting to the registry (but now there are more fine-grained options).

Kaye answered 17/7, 2015 at 7:4 Comment(7)
I think method 2 would probably be the way to go now days. I'm not sure about method 3, is that settable via web.config and does it prevent reloading on all file changes? Note that this wasn't being run via IIS, it was an ASP.NET AppDomain hosted inside a WPF application. Method 1 isn't really an option as it will affect other apps.Tracheo
@JacobStanley: if you use a new AppDomain and run it inside the same AppPool, then it doesn't quite matter whether you set it on the AppPool settings (method 3) or by changing the fcnMode in the web.config (method 2). The same site's web.config can be used by multiple AppPools, though it's more common that the same AppPool is used for multiple sites, in which case it is probably better to use method 2 with fcnMode (better per-site granularity). Note that you can set fcnMode even for separate directories in one site by adding a web.config in it.Kaye
@JacobStanley: on your other question, disallowRotationOnConfigChange can be set in the ApplicationHost.config file, but depending on your access level to your production server, this may or may not be directly accessible. However, that link shows a code example on how to change these settings with C#.Kaye
@Kaye Actually DisallowRotationOnConfigChange setting is not valid for changes in web.config but only in settings of an application pool. See this thread for more info.Recept
@azi, that is what I explain in my text, where I wrote 'as a setting for only the application pool'.Kaye
I have tried method 1, 2 and 3 on Windows Server 2016 but even when combining all 3 methods, any changes to web.config or applicationHost.config cause a recycle. Can you confirm that these methods should work on Windows Server 2016?Burnie
I have an ASP.NET MVC application that I'm building a shared Blaszor / Angular frontend for... and #2 you mentioned here was perfect for stopping IIS from reloading each time I build the Angular files.Wysocki
R
28

As far as I am aware there is no way to disable this behavior, changes to the webconfig force the application to be restarted.

Update: it is actually possible, there are a number of methods, well documented, as explained in this answer*

Original answer:

There is a similar question here just for other reference. I found additional info that may be helpful.

Configuration Changes Cause a Restart of the Application Domain
Changes to configuration settings in Web.config files indirectly cause the application domain to restart. This behavior occurs by design. You can optionally use the configSource attribute to reference external configuration files that do not cause a restart when a change is made. For more information, see configSource in General Attributes Inherited by Section Elements.

From This MSDN Article

* Disclaimer: I wrote the other answer and normally wouldn't make a self-reference, but find it relevant enough to link here since 8 years after this post it is really quite different: a solution is very easy by clicking through the IIS front-end, and workarounds exist since ASP.NET 1.0.

Reversioner answered 5/3, 2009 at 7:4 Comment(5)
Correct me if I'm wrong, but I believe that external configuration files will also restart the application?Desberg
OK I guess that MSDN article says that the don't cause application restarts, but does that mean that the config settings don't get loaded right away?Desberg
OK I just did some investigation, and on my ASP.NET 3.5 site, the App Pool did NOT restart, and the updated Setting Value WAS reflected in the web page. However, I still feel like I have seen a web app that WOULD reset when external configuration files were changed. Maybe there was something special about that app, or maybe it was an older version of ASP.NET.Desberg
It is very well and easily possible to change this default behavior (and already so since Windows 2003), see my answer below.Kaye
Using .Net 4+, we have not been able to consistently get the AppDomain to restart by modifying external config fileHaircloth
T
20

I ran in to an even bigger problem along the same lines - changes to any file or sub-folder in the AppDomain base directory cause the hosting environment to shutdown. This is a pretty big issue for our application as we're running a WPF UI in the same AppDomain and we can't restart it without being distruptive to the user.

I really wanted to avoid having to run a separate AppDomain for the web based part of the application so I did some digging with Reflector. I found that the culprit was the internal class FileChangesMonitor.

So I wrote a horrible horrible reflection hack to solve the problem. I thought I'd post it here as a potential solution for anyone else having the same problem. You just need to call HttpInternals.StopFileMonitoring() to disable shutdown on file/folder changes.

internal static class HttpInternals
{
    private static readonly FieldInfo s_TheRuntime = typeof(HttpRuntime).GetField("_theRuntime", BindingFlags.NonPublic | BindingFlags.Static);

    private static readonly FieldInfo s_FileChangesMonitor = typeof(HttpRuntime).GetField("_fcm", BindingFlags.NonPublic | BindingFlags.Instance);
    private static readonly MethodInfo s_FileChangesMonitorStop = s_FileChangesMonitor.FieldType.GetMethod("Stop", BindingFlags.NonPublic | BindingFlags.Instance);

    private static object HttpRuntime
    {
        get
        {
            return s_TheRuntime.GetValue(null);
        }
    }

    private static object FileChangesMonitor
    {
        get
        {
            return s_FileChangesMonitor.GetValue(HttpRuntime);
        }
    }

    public static void StopFileMonitoring()
    {
        s_FileChangesMonitorStop.Invoke(FileChangesMonitor, null);
    }
}
Tracheo answered 10/3, 2009 at 12:16 Comment(7)
But appDomains are intended to reflect the, y'know, application domain - something that is clearly different between WPF and web. You're using the object in a way not it was not intended to be used.Fornof
That's true, and I have indeed considered the pros and cons of using multiple AppDomains. I ended up coming to the conclusion that running multiple AppDomains would add more complexity to the application than this approach does. I'd love to hear any more opinions on the issue.Tracheo
@Jacob Stanley: First of all thanks for this solution. I have only one question, how can I restore file monitoring? For example after updating some dll files manually I want to restore normal website behaviour.Baskett
That's probably a lot more complicated :) If you're comfortable with Reflector, you can see what System.Web.FileChangesMonitor.Stop() does, and perhaps try to reverse it. It looks like ASP.NET usually only uses the Stop() method when it's shutting down. FileChangesMonitor has some methods on it called StartListeningToLocalResourceDirectory and some other Start* methods which look promising. If you could figure out what the HttpRuntime class does to initialize the FileChangesMonitor, you'd be on the right track. Sounds even dodgier than what I was originally doing though! :)Tracheo
@Jacob Stanley: Yes, it's pretty dodgy, I'm trying to update a single function of a running precompiled website. Using Reflector and Reflexil to accomplish that :)Baskett
Although it seems that updating method in runtime is not yet possible. There's a method PrepareMethod() for compiling IL-code, but not for re-compiling. So, once the method is called replacing it's IL-code will do nothing.Baskett
Microsoft abandoned AppDomains altogether; they're not even supported in .NET Core/5/6 because they add unnecessary complexity. They're basically like "just use a different process" now. Also, if you're using a tracing library like SignalFx, which hooks into the CLR, they recommend using a single AppDomain anyway, because any kind of in-process recycle (i.e. such as when a web.config file changes) will result in an attempt to load domain neutral assemblies in a way that causes a sharing violation to occur and crashes the whole process. Best to avoid AppDomains at this point.Coyote
A
11

A solution would be adding following element to web.config section :

<httpRuntime
    waitChangeNotification="315360000"
    maxWaitChangeNotification="315360000"
/>
Auvergne answered 24/8, 2009 at 9:54 Comment(3)
But that doesn't quite work in IIS7, sadly: forums.iis.net/t/… (although I just realized the poster is not using IIS, so it's OK in this case)Zannini
I find this answer very useful for other reasons, when trying to update 10 files at once, but you don't want 10 app pool recycles. This setting will allow you to combine a bunch of updated files into one reset. Of course, lower numbers will be needed to make it useful.Amoral
Actually, it does. But only for the BIN folder. The web.config still causes an immediate recycle: beweb.pbworks.com/w/page/30073098/…Amoral
B
0

As mentioned by jfburdet the solution is to use waitChangeNotification and maxWaitChangeNotification.

That being said, you should know they don't work on IIS 7 if ASP.NET is run in mixed mode: http://forums.iis.net/t/1149344.aspx

Boyceboycey answered 10/12, 2009 at 9:20 Comment(1)
Actually it does work. But only for the BIN folder, the web.config still causes an immediate recycle. Check about a third down in this article: beweb.pbworks.com/w/page/30073098/…Amoral

© 2022 - 2024 — McMap. All rights reserved.