In order to get your websites to automatically run the Application_Start of your global.asax in an Azure WebRole, some changes to your application are neccesary. This solution is probably not the only solution for this problem, but it worked for me. Let me know in the comments if you have a (much) easier solution.

I’ve created an empty webrole in a new cloud service and added the following code to the global.asax for testing purposes:

    static string systemtmp = Environment.GetEnvironmentVariable("TEMP", EnvironmentVariableTarget.Machine);

    protected void Application_Start(object sender, EventArgs e)
    {
        using (var sw = File.AppendText(Path.Combine(systemtmp, "mywebapp.log")))
        {
            sw.WriteLine(DateTime.UtcNow.ToString("HH:mm:ss.fff") + " - Application_Start");
        }
    }

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        using (var sw = File.AppendText(Path.Combine(systemtmp, "mywebapp.log")))
        {
            sw.WriteLine(DateTime.UtcNow.ToString("HH:mm:ss.fff") + " - Application_BeginRequest from " + HttpContext.Current.Request.UserHostAddress);
        }
    }

Now we’ll start modifying the app so that it automatically starts up.

WebRole.cs

Your webapplication may or may not have a WebRole.cs out-of-the-box. If you don’t, create the file yourself. Make sure it inherits from RoleEntryPoint, which is what Azure will be looking for.

Add a reference to Microsoft.Web.Administration, which you can find as nuget package, in your Azure SDK installation directory or on any Windows Server with IIS installed. Then add/merge the OnStart method in your WebRole.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.Diagnostics;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.Web.Administration;

namespace WebRole1
{
    public class WebRole : RoleEntryPoint
    {
        public override bool OnStart()
        {
            if (!RoleEnvironment.IsEmulated)
            {
                using (ServerManager serverManager = new ServerManager())
                {
                    foreach (var app in serverManager.Sites.SelectMany(x => x.Applications))
                    {
                        app["preloadEnabled"] = true;
                    }
                    foreach (var appPool in serverManager.ApplicationPools)
                    {
                        appPool.AutoStart = true;
                        appPool["startMode"] = "AlwaysRunning";
                        appPool.ProcessModel.IdleTimeout = TimeSpan.Zero;
                        appPool.Recycling.PeriodicRestart.Time = TimeSpan.Zero;
                    }
                    serverManager.CommitChanges();
                }
            }

            return base.OnStart();
        }
    }
}

Startup.cmd

We’ll need a startup script to install the IIS-ApplicationInit module on our IIS webserver when the WebRole initializes for the first time. For this purpose we’ll use a startup script.

Create an App_Data folder in your webapplication and add a new file named startup.cmd, or merge the following commands in your own startup file. Set this file to Copy if newer.

:: Install IIS ApplicationInit for preloading ability
start /w pkgmgr /iu:IIS-ApplicationInit

:: Done, make sure we exit gracefully
exit /b 0

ServiceDefinition.csdef

In the cloudproject we’ll do two important things: add the startup task so that it gets executed at startup, and make sure our OnStart method runs with administrator privileges in order to make the neccesary changes on the IIS configuration.

Under the WebRole node, add the following xml:

    <Startup>
      <Task commandLine="App_Data\startup.cmd" executionContext="elevated" taskType="simple" />
    </Startup>
    <Runtime executionContext="elevated" />

The startup task will run elevated so that it can install the ApplicationInit module. The Runtime will run elevated for the WebRole.cs logic.

Deploy and test

Now it’s just a matter of publishing the webrole and checking if everything worked. When the webrole has finished deploying, visit the website. When your Remote Desktop to your instance, you should see that Application_Start has executed and a request from 127.0.0.1 (or ::1 for IPv6) was received. The logfile should be in D:\Windows\Temp, which is the default system TEMP directory.

15:41:44.203 - Application_Start
15:41:44.218 - Application_BeginRequest from 127.0.0.1
Advertisements