IIS Modules

Developing IIS Modules

Internet Information Services 7.0 (IIS7) has a completely new architecture that contains a core server containing a unified pipeline with notifications available to IIS and ASP.NET developers. This core engine relies upon modules to perform HTTP request processing and related services, such as user authentication, authorization, and compression. IIS7 has componentized functionality into various modules that expose features of IIS and ASP.NET.

This architecture is extensible, allowing third parties to readily develop modules through either Win32 or ASP.NET interfaces. In either case, creating a module is straightforward. It is the addition of notification-based, robust, scalable processing logic that requires more consideration and effort.

Creating Win32 HTTP Modules

A Win32 IIS module is a DLL that meets the following three requirements:

  • It implements and exports a RegisterModule function. This function is called by the core server engine to register the extension after an entry for it is read from the <globalModules> section of the applicationhost.config file. RegisterModule serves three primary purposes: it specifies the notifications that the module will handle, specifies the relative processing priority for the module, and provides the core engine access to the module factory.

  • It implements a public class derived from CHttpModule. This class represents the primary functionality for the extension module, which is implemented in a set of virtual functions that handle notifications.

  • It implements a module factory derived from the IHttpModuleFactory interface (virtual class). This class creates an instance of the CHttpModule-derived class for the extension.

Public declarations for the native-mode HTTP Server API (which includes declarations for RegisterModule, CHttpModule, and IHttpModuleFactory) are contained in the httpserv.h file.

Bb757040.collapse_all(en-us,MSDN.10).gifThe RegisterModule Function

This function has the following prototype:

HRESULT WINAPI RegisterModule(
    // IIS version
    DWORD dwServerVersion,

    // Module's registration
    IHttpModuleRegistrationInfo* pModuleInfo,

    // Describes and controls the core engine
    IHttpServer* pGlobalInfo
);

The parameters can be optionally used by the extension module to adapt to the current server state, request server functions, or modify the server environment.

The pModuleInfo parameter is used to set the characteristics associated with the module. The IHttpModuleRegistrationInfo class has the following members for this purpose:

Member

Description

SetGlobalNotifications

Specifies which global events the module should be notified of.

SetPriorityForGlobalNotification

Specifies the relative priority of the module in the chain of modules that handle global events.

SetRequestNotifications

Specifies which request processing events the module should be notified of. This function also specifies the module factory that the server engine uses to instantiate the extension module.

SetPriorityForRequestNotification

Specifies the relative priority of the module in the chain of modules that handle request processing events.

A collection of constants that represent the notification events and their relative priorities are provided to use when invoking these member functions. For more information, see IIS Request-Processing Constants.

The RegisterModule function must be exported in a standard fashion: either by specifying this in the module definition (.def) file for the project or by using the /EXPORT:RegisterModule compiler switch.

Bb757040.collapse_all(en-us,MSDN.10).gifThe CHttpModule-Derived Class

Each extension module must have a single class derived from CHttpModule that contains the primary module functionality. In addition to a constructor and a Dispose method, this class contains, for each server event, a virtual function of the following form:

virtual
REQUEST_NOTIFICATION_STATUS
On<event-name>(
    IN IHttpContext* pHttpContext,
    IN OUT IHttpEventProvider* pProvider)
{
    //...
    return RQ_NOTIFICATION_CONTINUE;
}

For each event that was specified as being handled within the RegisterModule function (see SetRequestNotifications and SetGlobalNotifications above), the corresponding virtual function should be overridden and handled properly. For example, if the AuthorizeRequest event was registered as being handled by the module, this derived class should override the OnAuthorizeRequest member function. The pHttpContext and pProvider parameters provide additional information about the current event.

Note

Although the type of pProvider parameter is prototyped as IHttpEventProvider*, it is often a derived type that corresponds to the event type. For example, the OnAuthenticateRequest method actually receives a second parameter of type IAuthenticationProvider*.

Bb757040.collapse_all(en-us,MSDN.10).gifThe Module Factory

A matching module factory class must be provided so that the core server engine can instantiate the main module class on demand. This class must be derived from IHttpModuleFactory, which is a simple class consisting of two member functions:

  • GetHttpModule creates an instance of the primary extension module (CHttpModule-derived) class.

  • Terminate deletes and cleans up the extension module in case the current process must be terminated by the core server.

For more information, including sample code, see Creating Native-Code HTTP Modules.

Creating ASP.NET Managed Extensions

The IIS7 unified pipeline enables managed extension modules using the standard ASP.NET extension classes. Two .NET types of extensions can be created:

  • HTTP handlers—associated with file extensions and invoked to service requests to their associated resource types. ASP.NET comes with several built-in handlers, including ASP.NET page handler (.aspx), Web service handler (.asmx), ASP.NET user control handler (.ascx), and trace handler (.axd).

  • HTTP modules—called on every request made to the application as part of the ASP.NET request pipeline event processing. HTTP modules are commonly used for customized functionality, such as security, statistics and logging, or customized content processing (for example, adding customized headers or footers).

All of the classes and interfaces used to create HTTP handlers and modules are found in the System.Web namespace. Assemblies containing handlers or modules might be in the Global Assembly Cache (GAC), in the bin directory (most of the time), or in the containing Web site's App_Code directory as automatically compiled source code.

Bb757040.collapse_all(en-us,MSDN.10).gifHTTP Handlers

There are several steps that are required to create an HTTP handler:

  1. Create an association to a file extension. By default, ASP.NET maps the file extension .ashx for custom HTTP handlers. This association might be adequate for developing and testing HTTP handlers or generalized resource requests. However, for development of a dedicated handler for a particular file or information type, such as RSS feeds, it is beneficial to map the handler to an unused file extension by explicitly registering the extension by adding an appropriate <handlers> entry in the Web.config or applicationhost.config file.

  2. Create the handler class, the specifics of which depend upon whether the handler should respond to requests synchronously or asynchronously:

    • A synchronous handler will implement the IHttpHandler interface. This interface contains an IsReusable property, which indicates whether another request can use the same handler instance, and a ProcessRequest method, which performs the actual request processing, including creating the HTTP response. The ProcessRequest method takes an HttpContext parameter, which provides access to the intrinsic server objects (for example, Request, Response, Session, and Server).

    • An asynchronous handler will implement the IHttpAsyncHandler interface, which derives from IHttpHandler. This interface adds the BeginProcessRequest method, which initiates the asynchronous processing of individual HTTP requests, and the EndProcessRequest method, which runs cleanup code when the process ends.

  3. Optionally, create an associated handler factory and associate it with the file extension, instead of associating the handler directly with the extension. In this option, the handler factory class, which implements the IHttpHandlerFactory interface, dynamically determines which handler to use then creates and returns an instance of the handler. The IHttpHandlerFactory interface declares the GetHandler and ReleaseHandler methods. This option is used when more flexible request handling is required.

For more information and sample code, see Custom ASP.NET Processing with HTTP Handlers.

Bb757040.collapse_all(en-us,MSDN.10).gifHTTP Modules

Creating an HTTP module is straightforward, and involves the following two steps:

  1. Create the HTTP module by creating a class that implements the IHttpModule interface, which declares only two methods, Dispose and Init. The Init method should initialize the module and subscribe to any application events that require processing (for example, the BeginRequest or PostMapRequestHandler events). This class must therefore also contain an event handler for every subscribed event. The Dispose method can optionally be implemented to perform cleanup.

  2. Register the module in the Web.config file to associate it with one or more applications.

For more information and sample code, see Extending ASP.NET Processing with HTTP Modules.

Bb757040.collapse_all(en-us,MSDN.10).gifIIS Operation Modes and Interoperability

IIS7 offers two ways of running managed applications and extensions:

  • Integrated mode—the default, preferred method of operation. An integrated pipeline processes native and managed code. It supports ASP.NET version 2.1 and above.

  • ISAPI mode—the operation of previous versions of IIS by running managed code via a special ISAPI extension (AspNet_Isapi.dll). Although it is highly compatible with previous versions of IIS, it lacks the unified pipeline processing and some of the advanced features of integrated mode.

From the administrative perspective, configuration of IIS and ASP.NET applications are now uniform, using the new IIS configuration files, which can use the delegated XML web.config hierarchy familiar to ASP.NET developers. Older metabase properties are mapped to section groups, sections, elements, or attributes in the IIS7 configuration schema. For example, managed and native services are configured in the unified <modules> configuration section, and handlers are configured in the unified <handlers> configuration section. For more information, see Converting Metabase Properties to Settings Schema Elements.

When running in integrated mode, IIS uses its own module and handler configuration instead of the <httpHandlers> and <httpModules> sections that ASP.NET developers are used to. The newer management tools and utilities uniformly work with native IIS and ASP.NET applications. In ISAPI mode, AspNet_Isapi.dll uses legacy elements, such as <httpModules> and <httpHandlers>.

From a development perspective, much of the work within ASP.NET 2.1 to support the integrated mode of IIS7 is hidden to the developer. It simply works. Typically, these applications will also work under ISAPI mode in IIS7 or in a previous version of IIS with a loss of some functionality. In those situations where a capability is supported only under IIS7 integrated mode, the application will throw a PlatformNotSupportedException.

See Also

Concepts

Developer Story Internet Information Services

Other Resources

An End-to-End Extensibility Example for IIS7 Developers

IIS.Net

Internet Information Services 7.0 SDK