IIS7 uses (nearly) standard .NET .config XML files for configuration. This is great and is one of the coolest features of IIS7 IMO. The metabase is gone (woohoo) and you can mix ASP.NET and IIS7 settings in a single web.config file. This means that you don’t have to adjust settings in two places and that you can deploy your ASP.NET application together with IIS7 configuration. That’s awesome.
How often have I wished in the past that I can configure Windows authentication in ASP.NET and IIS in a single step and without having to navigate GUIs. Like this:
<configuration>
<system.web>
<authentication mode=“Windows“ />
</system.web>
<system.webServer>
<security>
<authentication>
<anonymousAuthentication enabled=“false“ />
<windowsAuthentication enabled=“true“ />
</authentication>
</security>
</system.webServer>
</configuration>
To read or modify configuration you have several choices, notepad, the IIS GUI, a command line tool (appcmd.exe) or the IIS configuration API.
You can find the API in the Microsoft.Web.Administration.dll assembly located in the GAC or WindowsSystem32Inetsrv. The most obvious class to start with is called ServerManager – this gives you full access to the IIS7 configuration and you can easily navigate through most settings using the Sites, Applications, ApplicationDomains and ApplicationPools collections. Another not so obvious class is called WebConfigurationManager which also gives you access to configuration. What’s the difference and when to use which?
ServerManager is an administration (or design-time) API mostly useful for deployment and automated configuration. ServerManager is (currently) not designed for partial trust scenarios and some functionality requires elevated OS privileges.
WebConfigurationManager is a fast, light-weight runtime configuration API for applications, handlers and modules that need to read configuration settings. This is the one you want to use in your ASP.NET application code.
To get access to configuration you need a Configuration object. ServerManager features two methods called GetAdministrationConfiguration() and GetApplicationHostConfiguration() which return the Configuration object for the two machine wide config files (the Application class also has a method called GetWebConfiguration()). From there you usually call the GetSection() method and specify the configuration section you want to access using an XPath like expression, e.g. “system.webServer/directoryBrowse”. WebConfiguration also has a GetSection() method – the configuration returned here is always the one for the current application.
GetSection() returns a ConfigurationSection (derived) class from which you can read and write configuration attributes and, when using ServerManager, write the changes back to the config file. The following code changes configuration to allow directory browsing for an application:
Configuration config = app.GetWebConfiguration();
// weak typed
ConfigurationSection sectionBrowse = config.GetSection
(“system.webServer/directoryBrowse”);
sectionBrowse[“enabled”] = true;
Those of you who have looked at ASP.NET custom configuration sections know that you can provide a class that does the mapping between the object and XML worlds. This allows using strongly typed properties instead of string values to change attributes. The IIS7 configuration API uses a similar approach (but not the same). You can provide a ConfigurationSection derived class that gives you properties – but the actual schema of the configuration section (enums, default and required values, min/max values etc.) is specified in an XML file. The reason for that is (I believe) that configuration has to be usable from managed and unmanaged code – and the custom attribute approach to define schema would tightly-couple the configuration section to the CLR.
The schema definition for the <directoryBrowse> section looks like this:
<sectionSchema name=“system.webServer/directoryBrowse“>
<attribute name=“enabled“ type=“bool“ defaultValue=“false“ />
<attribute name=“showFlags“ type=“flags“ defaultValue=“Date, Time, Size, Extension“>
<flag name=“None“ value=“0“ />
<flag name=“Date“ value=“2“ />
<flag name=“Time“ value=“4“ />
<flag name=“Size“ value=“8“ />
<flag name=“Extension“ value=“16“ />
<flag name=“LongDate“ value=“32“ />
</attribute>
</sectionSchema>
You can find the complete schema file in Windowssystem32inetsrvconfigschema.
The corresponding configuration section class would look like this:
public class DirectoryBrowseSection : ConfigurationSection
{
public static string SectionName = “system.webServer/directoryBrowse”;
public bool Enabled
{
get { return (bool)base[“enabled”]; }
set { base[“enabled”] = (bool)value; }
}
public EnumDirectoryBrowseShowFlags ShowFlags
{
get { return (EnumDirectoryBrowseShowFlags)base[“showFlags”]; }
set { base[“showFlags”] = (int)value;
}
}
public enum EnumDirectoryBrowseShowFlags
{
None = 0,
Date = 2,
Time = 4,
Size = 8,
Extension = 16,
LongDate = 32
}
With such a strong typed wrapper, the configuration code looks more OO:
Configuration config = app.GetWebConfiguration();
DirectoryBrowseSection sectionBrowse = (DirectoryBrowseSection)
config.GetSection(
DirectoryBrowseSection.SectionName,
typeof(DirectoryBrowseSection));
sectionBrowse.Enabled = true;
While technically there are already ConfigurationSection classes defined for all IIS7 and ASP.NET settings (in the Microsoft.Web.Management*.dll) – they are currently internal. Fortunately Kanwal from the IIS team posted a tool that generates configuration classes from the XML definition file. Simply point it at the IIS7 schema file and you will get an object model for all configuration groups and sections. Nice!