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.
Comments
Anonymous
May 20, 2011
excellent PostAnonymous
May 22, 2011
There was a comment about the deployment location of your IIS auto start provider assembly. You can add it to the bin folder of all the web sites that are going to use it or you can simply deploy it to the GAC.Anonymous
December 06, 2011
I like your post very much and i interested in your post because the post is very helpful and shareable. so, thanks for share it.Anonymous
April 24, 2012
Even though all the settings are as per the blog above, I found that the services under the site dont get live automatically and also requires a browse to instantiate. Also the "Auto-Start" tab under the WebApplication -> Configuration shows message that it is disabled and CustomAutoStartProvider XYZ is not supported. Can you give some idea why this happens?