Always Running ASP.net - Azure and On-Prem

Introduction

As most asp.net developers know, the first request to an MVC or WebAPI site takes considerably longer than subsequent requests due to the necessary initialization and boostraping of the application. This brief post shows how to overcome this performance penalty so that the first user to hit your app does not have to sit around waiting for it to spin up.

On-premise or VM hosted Site

When deploying to an on-premise or cloud hosted VM, the solution is to run the following commands:

PS %windir%\system32\inetsrv\appcmd.exe %windir%\system32\inetsrv\appcmd set config -section:applicationPools -applicationPoolDefaults.processModel.idleTimeout:00:00:00

PS %windir%\system32\inetsrv\appcmd.exe %windir%\system32\inetsrv\appcmd set config -section:applicationPools -applicationPoolDefaults.startMode:AlwaysRunning

PS %windir%\system32\inetsrv\appcmd.exe %windir%\system32\inetsrv\AppCmd.exe list app /xml | %windir%\system32\inetsrv\appcmd set site /in -applicationDefaults.preloadEnabled:True

Please note that the above will apply to all sites hosted on the server.

Azure Cloud Service

The solution is ultimately the same, however as Azure takes care of provisioning our environment, we need to utilise a start up task so that the correct settings get applied each time the instance is deployed or recycled.

Step 1

Create a file called startup.cmd and add the following commands to the file and save it to the same directory as your *.csdef (normally ServiceDefinition.csdef):

if exist %windir%\system32\inetsrv\appcmd.exe %windir%\system32\inetsrv\appcmd set config -section:applicationPools -applicationPoolDefaults.processModel.idleTimeout:00:00:00

if exist %windir%\system32\inetsrv\appcmd.exe %windir%\system32\inetsrv\appcmd set config -section:applicationPools -applicationPoolDefaults.startMode:AlwaysRunning

if exist %windir%\system32\inetsrv\appcmd.exe %windir%\system32\inetsrv\AppCmd.exe list app /xml | %windir%\system32\inetsrv\appcmd set site /in -applicationDefaults.preloadEnabled:True

echo SUCCESS exit /b 0

Step 2

Edit your *.csdef file and add the following as the last child the StartUp node:

<Task commandLine="..\startup.cmd" executionContext="elevated" />

Your startup node will now look something like:

<Startup> <Task commandLine="setup_web.cmd &gt; log.txt" executionContext="elevated"> <Environment> <Variable name="EMULATED"> <RoleInstanceValue xpath="/RoleEnvironment/Deployment/@emulated" /> </Variable> <Variable name="RUNTIMEID" value="" /> <Variable name="RUNTIMEURL" value="" /> </Environment> </Task> <Task commandLine="..\startup.cmd" executionContext="elevated" /> </Startup>

Step 3

Deploy! All done.

Sam Shiles

Read more posts by this author.