The IIS management framework allows configuring the web server using the IIS7 GUI. To understand the code that needs to be written, you have to know more about the management architecture.
The IIS GUI allows configuring local and remote servers (the remote functionality is not included in Vista). The local case is easy and boils down to accessing the local configuration and state data. In the remote case, the IIS GUI opens a SSL connection to the remote server and uses a web service style protocol to talk to a service on the remote machine that does the configuration. The current plans are that the client can automatically download all the client parts from the server on the first connection. On subsequent connections the IIS GUI checks for updated and new features.
This is the reason why management modules will always have two logical parts. The server part implements some registration code and the configuration service. The client part consists of the UI that will be integrated into the IIS GUI and a service proxy to talk to the server configuration service. In the local case the proxy->service communication will be short-circuited to local calls.
BTW – in the remote scenario, the client will not directly talk to the “real” IIS but to a small, customized management server running on the same machine. This guarantees remote access even if the “real” IIS should be unresponsive.
OK – so first you should implement your module service. This is a simple class which reminds a little of .asmx web services. Every method that should be callable from the service proxy has to be decorated with a [ModuleServiceMethod] attribute. Inside the service methods you read or write the configuration. I have not extensively tested this, but it seems you can use any serializable type to transmit data between the service and the proxy. To minimize dependencies between the client and the server I would recommend using a data structure that comes with the BCL like a Dictionary<>. In this simple example I chose a PropertyBag. I omitted the configuration code since this works exactly as in the HttpModule, but this time you get the current configuration (in the context of the application you manage) from base.ManagementUnit.Configuration.
class ServerHeaderModuleService : ModuleService
{
[ModuleServiceMethod(PassThrough = true)]
public PropertyBag GetConfiguration()
{
PropertyBag bag = new PropertyBag();
bag[0] = Configuration.Enabled;
bag[1] = Configuration.Value;
return bag;
}
[ModuleServiceMethod(PassThrough = true)]
public void SetConfiguration(bool enabled, string headerValue)
{
Configuration.Enabled = enabled;
Configuration.Value = headerValue;
base.ManagementUnit.Update();
}
}
Another class you have to implement is a module provider. This class does the registration of the service and the client UI module. Furthermore you can also specify at which configuration level (machine, site, application) the module should be available. There are several base classes to derive from – most commonly you will use ConfigurationModuleProvider – this is the base class of all built-in modules and gives you feature delegation support.
class ServerHeaderModuleProvider : ConfigurationModuleProvider
{
// returns the name of the configuration section
protected override string ConfigurationSectionName
{
get { return ServerHeaderConfigurationSection.SectionName; }
}
// returns the fqn of the corresponding client (UI) module type
public override ModuleDefinition GetModuleDefinition(IManagementContext context)
{
string clientname = “…”;
return new ModuleDefinition(base.Name, clientname);
}
// hooks up the module service
public override Type ServiceType
{
get { return typeof(ServerHeaderModuleService); }
}
// specifies at which level the module should be available
public override bool SupportsScope(ManagementScope scope)
{
return true;
}
public override string FriendlyName
{
get { return “ServerHeader”; }
}
}
Configuration modules need to be registered in the GAC.
The last step is to register the module in administration.config (windowssystem32inetsrvconfig). You have to modify two configuration sections named <moduleProviders> and <modules> like this:
<moduleProviders>
<!– Custom Modules –>
<add name=“ServerHeader“ type=“… “ />
…
<location path=“.“>
<modules>
<!– Custom Modules –>
<add name=“ServerHeader“ />
…
OK – now we have finished the server side of the management integration. But on its own – the server module is not very useful. In the next post I will show you how to write the corresponding UI integration and proxy to talk to the configuration service.