Writing an IIS 7.5 Auto Start Provider

In IIS 7.5 there is a new feature called the auto start provider. This feature allows you to load any custom web application resources to allow the application to provide better performance right from the first request.

 

Usually implementing an auto start provider is a simple task but what I think needs more clarification is how to write a setup module to configure it using code. So I will first start by implementing a custom auto start provider by implementing the interface “IProcessHostPreloadClient”. This interface has only one method as follows.

    public class CustomAutoStartProvider : IProcessHostPreloadClient

    {

        public void PreloadThread(Object obj)

        {

            // Load your custom resources here

        }

        public void Preload(string[] parameters)

        {

            ThreadPool.QueueUserWorkItem(new WaitCallback(PreloadThread), null);

        }

    }

It is not required to start a new loading thread but it is always preferable that you put the extensive loading code in a different thread.

Now to configure this new auto start provider, you need to add its configuration to the ApplicationHost.Config file. You need to perform the following steps:

1- Register the new auto start in the section “system.applicationHost/serviceAutoStartProviders”.

2- Change the web application app pool field “startMode” to be “AlwaysRunning”.

3- Change the web application field “serviceAutoStartEnabled” to be “true”.

4- Change the web application field “serviceAutoStartProvider” to the name you used when you registered the auto start provider.

Here is how you do it in code.

using (ServerManager serverManager = new ServerManager())

{

    Configuration config = serverManager.GetApplicationHostConfiguration();

    ConfigurationSection serviceAutoStartProvidersSection = config.GetSection("system.applicationHost/serviceAutoStartProviders");

    ConfigurationElementCollection serviceAutoStartProvidersCollection = serviceAutoStartProvidersSection.GetCollection();

    ConfigurationElement addElement = FindElement(serviceAutoStartProvidersCollection, "add", "name", @"CustomAutoStartProvider");

    if (addElement == null)

    {

        addElement = serviceAutoStartProvidersCollection.CreateElement("add");

        addElement["name"] = @"CustomAutoStartProvider";

        addElement["type"] = @"My.Custom.Providers.CustomAutoStartProvider,My.Custom.Providers";

        serviceAutoStartProvidersCollection.Add(addElement);

    }

    else

    {

        addElement["name"] = @"CustomAutoStartProvider";

        addElement["type"] = @"My.Custom.Providers.CustomAutoStartProvider,My.Custom.Providers";

    }

 

    ConfigurationSection applicationPoolsSection = config.GetSection("system.applicationHost/applicationPools");

    ConfigurationElementCollection applicationPoolsCollection = applicationPoolsSection.GetCollection();

    addElement = FindElement(applicationPoolsCollection, "add", "name", siteName);

    if (addElement == null) throw new InvalidOperationException("Element not found!");

    addElement["startMode"] = @"AlwaysRunning";

 

    ConfigurationSection sitesSection = config.GetSection("system.applicationHost/sites");

    ConfigurationElementCollection sitesCollection = sitesSection.GetCollection();

    ConfigurationElement siteElement = FindElement(sitesCollection, "site", "name", siteName);

    if (siteElement == null) throw new InvalidOperationException("Element not found!");

    ConfigurationElementCollection siteCollection = siteElement.GetCollection();

    ConfigurationElement applicationElement = FindElement(siteCollection, "application", "path", @"/");

    if (applicationElement == null) throw new InvalidOperationException("Element not found!");

    applicationElement["serviceAutoStartEnabled"] = true;

    applicationElement["serviceAutoStartProvider"] = @"CustomAutoStartProvider";

 

    serverManager.CommitChanges();

}

The helper function FindElement code is as below.

private static ConfigurationElement FindElement(ConfigurationElementCollection collection, string elementTagName, params string[] keyValues)

{

    foreach (ConfigurationElement element in collection)

    {

     if (String.Equals(element.ElementTagName, elementTagName, StringComparison.OrdinalIgnoreCase))

        {

            bool matches = true;

 

            for (int i = 0; i < keyValues.Length; i += 2)

            {

                object o = element.GetAttributeValue(keyValues[i]);

                string value = null;

                if (o != null)

                {

                    value = o.ToString();

                }

 

                if (!String.Equals(value, keyValues[i + 1], StringComparison.OrdinalIgnoreCase))

                {

                    matches = false;

                    break;

                }

            }

            if (matches)

            {

                return element;

            }

        }

    }

    return null;

}

 

Have fun coding.