Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
Markdown Monster - The Markdown Editor for Windows

Use IIS Application Initialization for keeping ASP.NET Apps alive


:P
On this page:

I've been working quite a bit with Windows Services in the recent months, and well, it turns out that Windows Services are quite a bear to debug, deploy, update and maintain. The process of getting services set up,  debugged and updated is a major chore that has to be extensively documented and or automated specifically. On most projects when a service is built, people end up scrambling for the right 'process' to use for administration. Web app deployment and maintenance on the other hand are common and well understood today, as we are constantly dealing with Web apps. There's plenty of infrastructure and tooling built into Web Tools like Visual Studio to facilitate the process. By comparison Windows Services or anything self-hosted for that matter seems convoluted.

In fact, in a recent blog post I mentioned that on a recent project I'd been using self-hosting for SignalR inside of a Windows service, because the application is in fact a 'service' that also needs to send out lots of messages via SignalR. But the reality is that it could just as well be an IIS application with a service component that runs in the background. Either way you look at it, it's either a Windows Service with a built in Web Server, or an IIS application running a Service application, neither of which follows the standard Service or Web App template.

Personally I much prefer Web applications. Running inside of IIS I get all the benefits of the IIS platform including service lifetime management (crash and restart), controlled shutdowns, the whole security infrastructure including easy certificate support, hot-swapping of code and the the ability to publish directly to IIS from within Visual Studio with ease.

Because of these benefits we set out to move from the self hosted service into an ASP.NET Web app instead.

The Missing Link for ASP.NET as a Service: Auto-Loading

I've had moments in the past where I wanted to run a 'service like' application in ASP.NET because when you think about it, it's so much easier to control a Web application remotely. Services are locked into start/stop operations, but if you host inside of a Web app you can write your own ticket and control it from anywhere. In fact nearly 10 years ago I built a background scheduling application that ran inside of ASP.NET and it worked great and it's still running doing its job today.

The tricky part for running an app as a service inside of IIS then and now, is how to get IIS and ASP.NET launched so your 'service' stays alive even after an Application Pool reset. 7 years ago I faked it by using a web monitor (my own West Wind Web Monitor app) I was running anyway to monitor my various web sites for uptime, and having the monitor ping my 'service' every 20 seconds to effectively keep ASP.NET alive or fire it back up after a reload. I used a simple scheduler class that also includes some logic for 'self-reloading'. Hacky for sure, but it worked reliably.

Luckily today it's much easier and more integrated to get IIS to launch ASP.NET as soon as an Application Pool is started by using the Application Initialization Module. The Application Initialization Module basically allows you to turn on Preloading on the Application Pool and the Site/IIS App, which essentially fires a request through the IIS pipeline as soon as the Application Pool has been launched. This means that effectively your ASP.NET app becomes active immediately, Application_Start is fired making sure your app stays up and running at all times. All the other features like Application Pool recycling and auto-shutdown after idle time still work, but IIS will then always immediately re-launch the application.

Getting started with Application Initialization

As of IIS 8 Application Initialization is part of the IIS feature set. For IIS 7 and 7.5 there's a separate download available via Web Platform Installer. Using IIS 8 Application Initialization is an optional install component in Windows or the Windows Server Role Manager:

WindowsFeatures

This is an optional component so make sure you explicitly select it.

IIS Configuration for Application Initialization

Initialization needs to be applied on the Application Pool as well as the IIS Application level. As of IIS 8 these settings can be made through the IIS Administration console.

Start with the Application Pool:
AppPools

Here you need to set both the Start Automatically which is always set, and the StartMode which should be set to AlwaysRunning. Both have to be set - the Start Automatically flag is set true by default and controls the starting of the application pool itself while Always Running flag is required in order to launch the application. Without the latter flag set the site settings have no effect.

Now on the Site/Application level you can specify whether the site should pre load:

SiteConfig

Set the Preload Enabled flag to true.

At this point ASP.NET apps should auto-load. This is all that's needed to pre-load the site if all you want is to get your site launched automatically.

If you want a little more control over the load process you can add a few more settings to your web.config file that allow you to show a static page while the App is starting up. This can be useful if startup is really slow, so rather than displaying blank screen while the user is fiddling their thumbs you can display a static HTML page instead:

  <system.webServer>
    <applicationInitialization remapManagedRequestsTo="Startup.htm"  
                               skipManagedModules="true">
      <add initializationPage="ping.ashx" />
    </applicationInitialization>
  </system.webServer>

This allows you to specify a page to execute in a dry run. IIS basically fakes request and pushes it directly into the IIS pipeline without hitting the network. You specify a page and IIS will fake a request to that page in this case ping.ashx which just returns a simple OK string - ie. a fast pipeline request. This request is run immediately after Application Pool restart, and while this request is running and your app is warming up, IIS can display an alternate static page - Startup.htm above. So instead of showing users an empty loading page when clicking a link on your site you can optionally show some sort of static status page that says, "we'll be right back".  I'm not sure if that's such a brilliant idea since this can be pretty disruptive in some cases. Personally I think I prefer letting people wait, but at least get the response they were supposed to get back rather than a random page. But it's there if you need it.

Note that the web.config stuff is optional. If you don't provide it IIS hits the default site link (/) and even if there's no matching request at the end of that request it'll still fire the request through the IIS pipeline. Ideally though you want to make sure that an ASP.NET endpoint is hit either with your default page, or by specify the initializationPage to ensure ASP.NET actually gets hit since it's possible for IIS fire unmanaged requests only for static pages (depending how your pipeline is configured).

What about AppDomain Restarts?

In addition to full Worker Process recycles at the IIS level, ASP.NET also has to deal with AppDomain shutdowns which can occur for a variety of reasons:

  • Files are updated in the BIN folder
  • Web Deploy to your site
  • web.config is changed
  • Hard application crash

These operations don't cause the worker process to restart, but they do cause ASP.NET to unload the current AppDomain and start up a new one. Because the features above only apply to Application Pool restarts, AppDomain restarts could also cause your 'ASP.NET service' to stop processing in the background.

In order to keep the app running on AppDomain recycles, you can resort to a simple ping in the Application_End event:

protected void Application_End()
{
    var client = new WebClient();
    var url = App.AdminConfiguration.MonitorHostUrl + "ping.aspx";
    client.DownloadString(url);
    Trace.WriteLine("Application Shut Down Ping: " + url);
}

which fires any ASP.NET url to the current site at the very end of the pipeline shutdown which in turn ensures that the site immediately starts back up.

Manual Configuration in ApplicationHost.config

The above UI corresponds to the following ApplicationHost.config settings. If you're using IIS 7, there's no UI for these flags so you'll have to manually edit them.

When you install the Application Initialization component into IIS it should auto-configure the module into ApplicationHost.config. Unfortunately for me, with Mr. Murphy in his best form for me, the module registration did not occur and I had to manually add it.

<globalModules>
  <add name="ApplicationInitializationModule"
       image="%windir%\System32\inetsrv\warmup.dll" />
</globalModules>

Most likely you won't need ever need to add this, but if things are not working it's worth to check if the module is actually registered.

Next you need to configure the ApplicationPool and the Web site. The following are the two relevant entries in ApplicationHost.config.

<system.applicationHost>
  <applicationPools>
    <add name="West Wind West Wind Web Connection"
          autoStart="true"
          startMode="AlwaysRunning"
          managedRuntimeVersion="v4.0"
          managedPipelineMode="Integrated">
      <processModel identityType="LocalSystem"
                    setProfileEnvironment="true" />
    </add>
  </applicationPools>

  <sites>
    <site name="Default Web Site" id="1">      
      <application path="/MPress.Workflow.WebQueueMessageManager"
                    applicationPool="West Wind West Wind Web Connection"
                    preloadEnabled="true">
        <virtualDirectory path="/"
                          physicalPath="C:\Clients\…" />
      </application>       
    </site>
  </sites>
</system.applicationHost>
On the Application Pool make sure to set the autoStart and startMode flags to true and AlwaysRunning respectively. On the site make sure to set the preloadEnabled flag to true.

And that's all you should need. You can still set the web.config settings described above as well.

ASP.NET as a Service?

In the particular application I'm working on currently, we have a queue manager that runs as standalone service that polls a database queue and picks out jobs and processes them on several threads. The service can spin up any number of threads and keep these threads alive in the background while IIS is running doing its own thing. These threads are newly created threads, so they sit completely outside of the IIS thread pool. In order for this service to work all it needs is a long running reference that keeps it alive for the life time of the application.

In this particular app there are two components that run in the background on their own threads: A scheduler that runs various scheduled tasks and handles things like picking up emails to send out outside of IIS's scope and the QueueManager.

Here's what this looks like in global.asax:

public class Global : System.Web.HttpApplication { private static ApplicationScheduler scheduler; private static ServiceLauncher launcher; protected void Application_Start(object sender, EventArgs e) { // Pings the service and ensures it stays alive scheduler = new ApplicationScheduler() { CheckFrequency = 600000 }; scheduler.Start(); launcher = new ServiceLauncher(); launcher.Start(); // register so shutdown is controlled HostingEnvironment.RegisterObject(launcher); }

}

By keeping these objects around as static instances that are set only once on startup, they survive the lifetime of the application. The code in these classes is essentially unchanged from the Windows Service code except that I could remove the various overrides required for the Windows Service interface (OnStart,OnStop,OnResume etc.). Otherwise the behavior and operation is very similar.

In this application ASP.NET serves two purposes: It acts as the host for SignalR and provides the administration interface which allows remote management of the 'service'. I can start and stop the service remotely by shutting down the ApplicationScheduler very easily. I can also very easily feed stats from the queue out directly via a couple of Web requests or (as we do now) through the SignalR service.

Registering a Background Object with ASP.NET

Notice also the use of the HostingEnvironment.RegisterObject(). This function registers an object with ASP.NET to let it know that it's a background task that should be notified if the AppDomain shuts down. RegisterObject() requires an interface with a Stop() method that's fired and allows your code to respond to a shutdown request. Here's what the IRegisteredObject::Stop() method looks like on the launcher:

public void Stop(bool immediate = false)
{
    LogManager.Current.LogInfo("QueueManager Controller Stopped.");

    Controller.StopProcessing();
    Controller.Dispose();
    Thread.Sleep(1500); // give background threads some time
 
    HostingEnvironment.UnregisterObject(this); 
}

Implementing IRegisterObject should help with reliability on AppDomain shutdowns. Thanks to Justin Van Patten for pointing this out to me on Twitter.

RegisterObject() is not required but I would highly recommend implementing it on whatever object controls your background processing to all clean shutdowns when the AppDomain shuts down.

Testing it out

I'm still in the testing phase with this particular service to see if there are any side effects. But so far it doesn't look like it. With about 50 lines of code I was able to replace the Windows service startup to Web start up - everything else just worked as is. An honorable mention goes to SignalR 2.0's oWin hosting, because with the new oWin based hosting no code changes at all were required, merely a couple of configuration file settings and an assembly directive needed, to point at the SignalR startup class. Sweet!

It also seems like SignalR is noticeably faster running inside of IIS compared to self-host. Startup feels faster because of the preload.

Starting and Stopping the 'Service'

Because the application is running as a Web Server, it's easy to have a Web interface for starting and stopping the services running inside of the service. For our queue manager the SignalR service and front monitoring app has a play and stop button for toggling the queue.

If you want more administrative control and have it work more like a Windows Service you can also stop the application pool explicitly from the command line which would be equivalent to stopping and restarting a service.

To start and stop from the command line you can use the IIS appCmd tool. To stop:

> %windir%\system32\inetsrv\appcmd stop apppool /apppool.name:"Weblog"

and to start

> %windir%\system32\inetsrv\appcmd start apppool /apppool.name:"Weblog"

Note that when you explicitly force the AppPool to stop running either in the UI (on the ApplicationPools page use Start/Stop) or via command line tools, the application pool will not auto-restart immediately. You have to manually start it back up.

What's not to like?

There are certainly a lot of benefits to running a background service in IIS, but… ASP.NET applications do have more overhead in terms of memory footprint and startup time is a little slower, but generally for server applications this is not a big deal. If the application is stable the service should fire up and stay running indefinitely. A lot of times this kind of service interface can simply be attached to an existing Web application, or if scalability requires be offloaded to its own Web server.

Easier to work with

But the ultimate benefit here is that it's much easier to work with a Web app as opposed to a service. While developing I can simply turn off the auto-launch features and launch the service on demand through IIS simply by hitting a page on the site. If I want to shut down an IISRESET -stop will shut down the service easily enough. I can then attach a debugger anywhere I want and this works like any other ASP.NET application. Yes you end up on a background thread for debugging but Visual Studio handles that just fine and if you stay on a single thread this is no different than debugging any other code.

Summary

Using ASP.NET to run background service operations is probably not a super common scenario, but it probably should be something that is considered carefully when building services. Many applications have service like features and with the auto-start functionality of the Application Initialization module, it's easy to build this functionality into ASP.NET. Especially when combined with the notification features of SignalR it becomes very, very easy to create rich services that can also communicate their status easily to the outside world.

Whether it's existing applications that need some background processing for scheduling related tasks, or whether you just create a separate site altogether just to host your service it's easy to do and you can leverage the same tool chain you're already using for other Web projects. If you have lots of service projects it's worth considering… give it some thought…

Posted in ASP.NET  SignalR  IIS  

The Voices of Reason


 

Eric
October 02, 2013

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

Next time you need a windows service try Topshelf http://topshelf-project.com/ Makes working with services a breeze.

Matt
October 03, 2013

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

"As of IIS 7.5 Application Initialization is part of the IIS feature set."

I believe IIS 7.5 still requires a separate extension to be downloaded and installed, it isn't built in.

Carel Lotz
October 04, 2013

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

You might also want to consider the impact of settings like "Disable Overlapped Recycle" and "Idle Timeout" if the idea is to use the IIS infrastructure as a "service" hosting environment. With a Windows Service you only have a single instance running at any time. With overlapping recycle you might run into issues. Also, if the services are stateless, the Idle timeout shouldn't be an issue, but the app pool recycle also introduces the possibility of loosing service state.

Steve
October 04, 2013

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

Very interesting, thank you. However I would try to replace DB polling if you have high db activity.

Rick Strahl
October 04, 2013

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

@Carel - yes in our case overlaps and multiple services running at the same time are part of the design. In fact the service scales by having multiple instances running side by side to scale up if necessary, but it's a point well taken: It's important to understand the differences between a single Windows Service process and the potential multi-process IIS hosting.

@Steve - Yeah db polling has some overhead but it's not an issue in what we do. Right now the queue sits inside of the main app DB, but if necessary it can be pulled into its own DB or DBserver if load becomes an issue to mitigate that issue. DB random access and the ability to track messages through the lifetime of queue request is well worth it over using classic Queue software which makes random access and progress info and item tracking and stats much more difficult.

@Eric - TopShelf is nice but honestly doesn't provide much value over what I already use here. I have a service class that provides similar functionality (ie. run as a console app or service depending how it was started. The issue isn't the service interface per se - it's managing deployment on a remote machine. By using IIS you can use the standard Web Publishing tools that are already in use for the Web application - there's no manual step required on the server to stop service/copy files/restart service which IMHO is a PITA for remote deployments. Much easier to use WebDeploy into the BIN folder that sorts itself out once the files have been updated.

Kevin Pirkl
October 04, 2013

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

My IIS 7.5 on Win7 64bit does not show the options after adding the App Init installer but Amol Mehrotra has a bolt that puts it on the IIS MMC UI. Might be old but seems to work (only if you don't have the options) - http://blogs.msdn.com/b/amol/archive/2013/01/25/application-initialization-ui-for-iis-7-5.aspx

Rick Strahl
October 04, 2013

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

@Kevin - so I'm getting conflicting reports. Some people told me the UI is included, others are saying it's not, so I'm not sure. I know on IIS 7 it's definitely not there even with the module installed, and on IIS 8 it is there. So looks like 7.5 definitely doesn't have it installed by default.

What happens if you install the Application Initialization Module from PI? It works but no UI?

Kevin Pirkl
October 04, 2013

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

@Rick - yeah it pulled from PI as it wasnt an otion for me in Add Win features. Needed a rebot to complete the PI install too but I only can see a Start Automatically option (was not sure if that was there before) but nothing else was showing for the app pool settings screen. I could swear that it only showed up on the features tab and only after adding Amols add on. But for sure a no show in advanced app pool settings and like you the warmup.dll did not auto-add so a manual add there too. it does spin up though as advertised. Nice article BTW I'm sharing it around. We had a msft guy out at the office for a week to just go over Service Bus 1.1 for windows and SignalR stuff for backplane, etc.

Anyway while my laptop was just reformatted a couple weeks back I've installed and reinstalled app fabric, SB , Workflow, etc over and over to refined a load of documentation from it all so my computer is probably not entirely reliable.. We run the whole mess under Win domain accounts least permissive.

Again, thanks for this article, its awesome.. Cheers

DalSoft
October 09, 2013

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive


Martin Meixger
October 10, 2013

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

Hi,

I've verified that autoStart, startMode AlwaysRunning and applicationInitialization is all working fine.

But how does everyone here handle restarting the app after deploy new binaries?

If i deploy new binaries or recompile the project in VS, the AppDomain shut's down and will **only be restarted on next apppool recycle** or if i hit the website manually!

Rick Strahl
October 11, 2013

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

@Martin - yes the Application Pool recycling feature only handles full Application Pool restarts, not AppDomain unloads reloads which occur if the BIN directory is updated or web.config files are touched.

There's a workaround for that though:

protected void Application_End()
{
        var client = new WebClient();
        var url = App.AdminConfiguration.MonitorHostUrl + "ping.aspx";
        client.DownloadString(url);
        Trace.WriteLine("Application Shut Down Ping: " + url);
}

This fires a new request at the very end of the shutdown procedure which effectively starts up the site again immediately.

Kevin Pirkl
October 17, 2013

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

Some more details - initializationPage gets hit by the IIS Account so that's "NT AUTHORITY\IUSR" and not your App Pool account so keep that in mind if your using Windows Authentication.

Even though initializationPage gets hit don't expect it to get written to the IIS Logs - I found this tid bit of info on an MSDN Blog after spending a crazy amount of time and manual loggin to figure that one out.

web.config touch or "net stop w3svc" or "sc stop w3svc" triggers IRegisteredObject.Stop() fine but a subsequent start is not enough to fire it again. appcmd and from the mmc stopping and starting the app pool works though to fire the initializationPage

Regarding ASP.Net as a service take into account when using a Web Garden or multiple servicing Threads for launcher and scheduler that you will get one instance per realize that you will get one per w3wp.exe process instance (one process is launched to service each garden.) Just keep this in mind.

I am playing around with the ASP.Net as a Service to handle Service Bus 1.1 Queue Messages. I spin up a separate worker thread and from there have a SB Queue Client set to only use 1 Thread and asynch processing of Queue items. The SB Queue is setup to only allow 2 items at a time and it uses round robin to Queue Clients which process 1 message at a time. It all distributes the load quite evenly. Plus if the App pool terminates abnormally the queue item will get picked up by one of the other app pool threads.

Typically an IISReset allows workers to finish processing before stopping but there are response timeouts defaults like 90 seconds and IIS Service account will kill the past that. Do little bits of work that finish quickly and you can scale HUGE!

public sealed class JobHost : IRegisteredObject {
    private static readonly JobHost instance = new JobHost();
    // Explicit static constructor to tell C# compiler not to mark type as beforefieldinit
    static JobHost(){}
    private JobHost(){}
    public static JobHost Instance { get { return instance; } }
 
    private readonly object _lock = new object();
    private bool _shuttingDown;
 
    public void Stop(bool immediate) {
        lock (_lock) {_shuttingDown = true;}
        HostingEnvironment.UnregisterObject(this);
    }
    public void Startup(Action work)  {
        lock (_lock) {
            if (_shuttingDown) {
                return;
            }
            System.Threading.Thread worker = new System.Threading.Thread(() => work());
            worker.Start();
            //work();
        }
    }
}
 
public class MvcApplication : System.Web.HttpApplication {
  protected void Application_Start() {
       JobHost.Instance.Startup(() => { 
                /* What is it that you do around here */
        });
   }
}


I cobbled this together from your stuff above and some of what Phil Haack mentioned..

Hope I did not bork the code I pasted in above very bad and I probably am violating some rule or other too.. Probably will leak like a sieve but I hope its of use to someone out there.

Shawn
October 17, 2013

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

Is there a race condition to worry about if you download/reload the site before the copy of binaries is complete?

Sebastiaan Janssen
October 18, 2013

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

Thanks, this works great!
One thing to note, the Application Initialization option was not enabled by default on my IIS8/Win2012 server install. But the Preload Enabled and Start Mode > Always running options were in IIS. So after and hour of double-checking, triple-checking and debugging I thought I'd check if AI was installed, turns out it wasn't.
After enabling AI, it immediately started working, very very handy!

Rajiv Mounguengue
January 21, 2014

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

Hi, I can't find a IIS 7 version of the module apparently only 7.5 is supported. Anyway, how about 7.0 apps??

Mike
February 06, 2014

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

Could it be that the Start Automatically option that you list under the Advanced Settings is now (2012 R2 / IIS 8.5) a checkbox named "Start application pool automatically" in the Basic Settings?

Mark Aurit
March 30, 2014

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

Thanks for the excellent documentation. Were you a tech writer in another life .5 :-)

Alex
April 01, 2014

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

I was using a "self-pinger" service based on your other blog-post - http://weblog.west-wind.com/posts/2007/May/10/Forcing-an-ASPNET-Application-to-stay-alive but guess no need for that now... Will try to move things to the App Initialization module. Great stuff, thanks Rick (again!)

Badrah
April 29, 2014

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

First of all, thanks for the well written illustration!
I understand the difference between AppDomain and AppPool recycles. I also, understand the workaround of the Application_End() trigger.

My problem is that, my own application initialization takes significant amount of time. I'd love to have AppDomain recycles to be pre-loaded the same way the Application Initialization works. Anyone succeeded to achieve that?

When ever I do a web.config change or change the physical path of the virtual directory, the AppDomain gets recycled and during that, all requests get queued for a significant amount of time (30-90 seconds). Is there a possible workaround for that?

TBoe
June 04, 2014

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

I tried Application Initialization for a WCF service based application. I want a WCF service to be called that does the warmup. However, I was not able to get this to work. I followed the intructions provided on the official IIS 8 Application Initialization web site and got the demo app to work. But when I configure my web.config to call my service by nominating a .SVC URL nothing happens (no warmup, no error). The section in my web.config looks like this:

<applicationInitialization skipManagedModules="true" >
<add initializationPage="/Service1.svc" />
</applicationInitialization>

My IIS seems to call somewhere into the Service1 because when I change the URL to something non-existing I can see an error message isued by IIS in the windows event log.
So my question is: How do I get things setup for a WCF service? Or putting it in other words: What method of the service class that serves as the code behind for Service1.svc gets called when I setup a warmup URL pointing to the .SVC? I put trace code into the constructor but that never gets executed.

Any help will be appreciated.

Sunil
July 02, 2014

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

Hi Rick,

What is the Impact of this on a Classic ASP web site. I normally keep idle time-out to 0 still if you don't use the site for a long time ( mainly test sites) you will see that it takes some time to start.

Thanks

Sunil

Rick Strahl
July 02, 2014

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

@Sunil - All of what's described - except for the startup hook callback - are IIS features so they work on any kind of site regardless of backend technology including ASP classic.

Vetri
October 08, 2014

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

Hi Rick,

We have two IIS 7.5 web applications with below settings (2 different app pools),

1. Application 1 - Idletimeout = 0

2. Application 2 - Idletimeout = 20 (default value) - Application Initialization configured for this site.

Question 1

When we analyzed the performance of the both the sites, Application 1 is responding faster than Application 2 (After the new worker process generated due to idleness)

Question 2

For application 2, the new worker process gets generated after few minutes when the site is idle. What does this few minutes/ warm up period refer to? Where it can be configured? Is this based on Idletimeout?

Question 3

Assume like I have configured 'Application Initialization' for Application 1 as well (along with Idletimeout = 0)

Now if I recycle the app pool manually and assume no requests have reached the server yet, then will the Application Initialization sends the request after the warm up period?

qakmak
November 22, 2014

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

1.So How about it when restart the website not application pool?
2.By the way: <add initializationPage="/" /> not working on IIS7.5 WINDOWS SERVER 2008 R2, it not send request event the application pool recycle.

Arunkumar
December 05, 2014

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

1)How to set Application Pool Start Mode = Always Running through appcmd..
Ex: Like this "%windir%\system32\inetsrv\appcmd set config -section:applicationPools -applicationPoolDefaults.processModel.idleTimeout:00:00:00"

2)And also set [preloadEnabled ='true'] through appcmd

3)How to install Application Initialization through appcmd

Because i need to run batch file in my system while hosting my application..

Arunkumar
December 05, 2014

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

1)How to set Application Pool Start Mode = Always Running through appcmd..
Ex: Like this "%windir%\system32\inetsrv\appcmd set config -section:applicationPools -applicationPoolDefaults.processModel.idleTimeout:00:00:00"

2)And also set [preloadEnabled ='true'] through appcmd

3)How to install Application Initialization through appcmd

Because i need to run batch file in my system while hosting my application..

Mike Moorman
December 10, 2014

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

This self-ping mechanism with internally running threads is an antipattern. I've been down this path too, and generally the symptom is when we find ourselves trying to do timed or schedule-oriented tasks in Application_Start or Application_End.

The iron-clad best practice is to have an external process connect to the web service or web site on a schedule, say, every minute, with the following caveats:

* The application uses a http handler to handle the ping request
* The application only honors requests from localhost

I have a windows service that I use for this purpose. It's installed on every web server where I want this behavior. I've taken it a bit further actually, using the ping as a status reporter, and each site can return whatever metrics are relevant, to the windows service pinging it.

Rick Strahl
December 10, 2014

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

@Mike - I actually do the same. In fact every Web site I run is hooked up to a monitor that checks whether the site is running and notifies me of failures and it doubles as the ping mechanism.

The ping check in the code above is just a last ditch fail safe. With Application Initialization there's only one scenario where that's required and that's for AppDomain shutdowns. All other scenarios Application Initialization handles for restarting the service and keeping it running (ie. crashes, restarts).

Abhijeet P
July 10, 2015

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

Hi Rick,
This only seems to work for the default website, the app initilization module will only perform the initialization for localhost:80 , so if you create a new website and want to use this feature you are SOL.
Also, "https" is not supported which makes the usability of this feature pretty darn useless IMHO

Christian Rodriguez
August 03, 2015

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

Excellent information. I wrote an article on how to automate these steps in case it helps someone https://christianarg.wordpress.com/2015/08/03/automating-iis-always-running-to-auto-start-your-application/

Harry Cummings
August 10, 2015

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

This is a really useful article, thanks!

This article doesn't mention the doAppInitAfterRestart attribute of the applicationInitialization config element. From my understanding of the documentation, I believe this would be a simpler way to address the cases covered in "What about AppDomain Restarts?" above. Is anyone able to confirm/deny this?

Adam
January 28, 2016

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

Does it really only make requests over localhost? If so what are the hostname and initalizationPage settings for? Can i set the hostname with a custom host or ip address? will this override it trying to make requests over localhost? enter image description here

Does it work over SSL?

Does it work with authentication? Within the original Application Warm-Up implementation it looked as though you could specify auth credentials but i don't see how that is possible anymore.

Dave Myers
March 14, 2016

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

Great info. I keep going back to this page every time I have to set up a new IIS instance of my web application.

Eniep
April 11, 2016

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

Thanks so much for the great post!!! This was exactly what I was looking for. I'm having one small issue though. I can't find
App.AdminConfiguration.MonitorHostUrl
Is there a special namespace I need to import? I'm working on a WebApi2 app.

Thanks again!!!

Rick Strahl
April 12, 2016

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

@Eniep - This is an application specific value - I use a custom configuration class to store this URL, but you can use whatever works for your to house that value (AppSettings, static value etc.).

Saurav
September 21, 2016

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

Application Initialization module is available for IIs 7.5 onwords.Can you please help me to find some solution for IIS 7.

Finnur Jonsson
September 18, 2017

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

Thanks for an informative article and helpful comments. Can anyone comment how much of this applies to using IIS to front an ASP.NET Core application running on Kestrel?


Pravin Jaiswal
April 04, 2020

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

How to Avoid Application Domain / Pool Recycling or Restart in case of config changes.. How to achieve the same ? (ASP.Net)


Rick Strahl
April 05, 2020

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

@Pravin - it's not possible. Built into IIS when config changes are made the Application domain restarts. No way to make that not happen.


mms
June 11, 2020

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

This is not good.

Recycling on every Virtual Directory change/create (for which I can't really think of a good reason) combined with the fact that IIS can't serve Symbolic Link directories (it does not recognize any file changes and serves stale content), makes it unusable for us for a very simple use case 😦 IIS needs to be rewritten, though I thought it was already.

Any way perhaps that url rewriting can be used to serve files out of a folder other than they physically exist? Need to be able to create these rewrite rules at runtime without bringing down the domain.

https://stackoverflow.com/questions/6698481/how-do-i-prevent-iis-7-5-from-caching-symlink-content


Allan
November 25, 2020

# re: Use IIS Application Initialization for keeping ASP.NET Apps alive

Old post but I recently ran across it and also had the issue with the site not restarting on deploy. Looking around for different solutions I found that you can actually restart the app pool using webdeploy as well:

msdeploy.exe -verb:sync -source:recycleApp -dest:recycleApp="MyAppPool",recycleMode="RecycleAppPool",UserName='Administrator',AuthType='Basic',ComputerName="https://myserver:8172/msdeploy.axd?site=MyApp",Password=mypassword -allowUntrusted

Msdeploy is installed by visual studio at C:\Program Files (x86)\IIS\Microsoft Web Deploy V3

Perhaps someone will find this useful 😃


West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024