Quick Overview of the IIS Extensibility API

A Web server is primarily a server application that can be contacted using a bunch of Internet protocols, such as HTTP, File Transfer Protocol (FTP), Network News Transfer Protocol (NNTP), and the Simple Mail Transfer Protocol (SMTP). IIS—the Web server included with the Microsoft Windows operating system—is no exception.

A Web server generally also provides a documented application programming interface (API) for enhancing and customizing the server's capabilities. Historically speaking, the first of these extension APIs was the Common Gateway Interface (CGI). A CGI module is a new application that is spawned from the Web server to service a request. Nowadays, CGI applications are almost never used in modern Web applications because they require a new process for each HTTP request. As you can easily understand, this approach is rather inadequate for high-volume Web sites and poses severe scalability issues. IIS supports CGI applications, but you will seldom use this feature unless you have serious backward-compatibility issues. More recent versions of Web servers supply an alternate and more efficient model to extend the capabilities of the module. In IIS, this alternative model takes the form of the ISAPI interface.

The ISAPI Model

When the ISAPI model is used, instead of starting a new process for each request, IIS loads an ISAPI component—namely, a Win32 DLL—into its own process. Next, it calls a well-known entry point on the DLL to serve the request. The ISAPI component stays loaded until IIS is shut down and can service requests without any further impact on Web server activity. The downside to such a model is that because components are loaded within the Web server process, a single faulty component can tear down the whole server and all installed applications. Starting with IIS 4.0, though, some countermeasures have been taken to address this problem. Before the advent of IIS 6.0, you were allowed to set the protection level of a newly installed application choosing from three options: low, medium, and high.

If you choose a low protection, the application (and its extensions) will be run within the Web server process (inetinfo.exe). If you choose medium protection, applications will be pooled together and hosted by an instance of a different worker process (dllhost.exe). If you choose high protection, each application set to High will be hosted in its own individual worker process (dllhost.exe).

Web applications running under IIS 6.0 are grouped in pools, and the choice you can make is whether you want to join an existing pool or create a new one. Figure 18-1 shows the dialog box picking the application pool of choice in IIS 6.0 and Microsoft Windows Server 2003.

Dd163839.figure_C18625273_1(en-us,MSDN.10).png

Figure 18-1 Configuring the protection level of Web applications in IIS 6.0 under Windows Server 2003.

All applications in a pool share the same run-time settings and the same worker process—w3wp.exe.

Illustrious Children of the ISAPI Model

The ISAPI model has another key drawback—the programming model. An ISAPI component represents a compiled piece of code—a Win32 DLL—that retrieves data and writes HTML code to an output console. It has to be developed using C or C++, it should generate multithreaded code, and it must be written with extreme care because of the impact that bugs or runtime failures can have on the application.

A while back, Microsoft attempted to encapsulate the ISAPI logic in the Microsoft Foundation Classes (MFC), but even though the effort was creditable, it didn't pay off very well. MFC tended to bring more code to the table than high-performance Web sites would perhaps like, and worse, the resulting ISAPI extension DLL suffered from a well-documented memory leak.

Active Server Pages (ASP), the predecessor of ASP.NET, is, on the other hand, an example of a well-done ISAPI application. ASP is implemented as an ISAPI DLL (named asp.dll) registered to handle HTTP requests with an .asp extension. The internal code of the ASP ISAPI extension DLL parses the code of the requested resource, executes any embedded script code, and builds the page for the browser.

As of IIS 6.0, any functionality built on top of IIS must be coded according to the guidelines set by the ISAPI model. ASP and ASP.NET are no exceptions. Today, the whole ASP.NET platform works closely with IIS, but it is not part of it. The aspnet_isapi.dll core component is the link between IIS and the ASP.NET runtime environment. When a request for .aspx resources comes in, IIS passes the control to aspnet_isapi.dll, which in turn hands the request to the ASP.NET pipeline inside an instance of the common language runtime (CLR).

As of this writing, to extend IIS you can write a Win32 DLL only with a well-known set of entry points. This requirement ceases to exist with IIS 7.0, which is scheduled to ship with Windows 2008 Server.

Note A good place to learn about IIS 7.0 and find good scripts and code snippets is https://www.iis.net. IIS 7.0 is also part of Windows Vista, but that is not particularly relevant here in the context of an ASP.NET book. Although you can certainly develop part of your Web site on a Windows Vista machine, it is simply out of question that you use Windows Vista as a Web server to host a site. Although fully functional, the IIS 7.0 that has shipped with Windows Vista can be seen as a live tool to experiment and test. The "real" IIS 7.0 for Web developers and administrators will ship in 2008 with Windows 2008 Server.

Structure of ISAPI Components

An ISAPI extension is invoked through a URL that ends with the name of the DLL that implements the function, as shown in the following URL:

https://www.contoso.com/apps/hello.dll

The DLL must export a couple of functions—GetExtensionVersion and HttpExtensionProc. The GetExtensionVersion function sets the version and the name of the ISAPI server extension. When the extension is loaded, the GetExtensionVersion function is the first function to be called. GetExtensionVersion is invoked only once and can be used to initialize any needed variables. The function is expected to return true if everything goes fine. In the case of errors, the function should return false and the Web server will abort loading the DLL and put a message in the system log.

The core of the ISAPI component is represented by the HttpExtensionProc function. The function receives basic HTTP information regarding the request (for example, the query string and the headers), performs the expected action, and prepares the response to send back to the browser.

Note Certain handy programming facilities, such as the session state, are abstractions the ISAPI programming model lacks entirely. The ISAPI model is a lower level programming model than, say, ASP or ASP.NET.

The ISAPI programming model is made of two types of components—ISAPI extensions and ISAPI filters.

ISAPI Extensions

ISAPI extensions are the IIS in-process counterpart of CGI applications. As mentioned, an ISAPI extension is a DLL that is loaded in the memory space occupied by IIS or another host application. Because it is a DLL, only one instance of the ISAPI extension needs to be loaded at a time. On the downside, the ISAPI extension must be thread-safe so that multiple client requests can be served simultaneously. ISAPI extensions work in much the same way as an ASP or ASP.NET page. It takes any information about the HTTP request and prepares a valid HTTP response.

Because the ISAPI extension is made of compiled code, it must be recompiled and reloaded at any change. If the DLL is loaded in the Web server's memory, the Web server must be stopped. If the DLL is loaded in the context of a separate process, only that process must be stopped. Of course, when an external process is used, the extension doesn't work as fast as it could when hosted in-process, but at least it doesn't jeopardize the stability of IIS.

ISAPI Filters

ISAPI filters are components that intercept specific server events before the server itself handles them. Upon loading, the filter indicates what event notifications it will handle. If any of these events occur, the filter can process them or pass them on to other filters.

You can use ISAPI filters to provide custom authentication techniques or to automatically redirect requests based on HTTP headers sent by the client. Filters are a delicate gear in the IIS machinery. They can facilitate applications and let them take control of customizable aspects of the engine. For this same reason, though, ISAPI filters can also degrade performance if not written carefully. Filters, in fact, can run only in-process. Filters can be loaded for the Web server as a whole or for specific Web sites.

ISAPI filters can accomplish tasks such as implementing custom authentication schemes, compression, encryption, logging, and request analysis. The ability to examine, and if necessary modify, both incoming and outgoing streams of data makes ISAPI filters very powerful and flexible. This last sentence shows the strength of ISAPI filters but also indicates their potential weakness, which is that they will hinder performance if not written well.

Changes in IIS 7.0

ASP.NET 1.0 was originally a self-contained, brand new runtime environment bolted onto IIS 5.0. With the simultaneous release of ASP.NET 1.1 and IIS 6.0, the Web development and server platforms have gotten closer and started sharing some services, such as process recycling and output caching. The advent of ASP.NET 2.0 and newer versions hasn't changed anything, but the release of IIS 7.0 will.

A Unified Runtime Environment

In a certain way, IIS 7.0 represents the unification of the ASP.NET and IIS platforms. HTTP handlers and modules, the runtime pipeline, and configuration files will become constituent elements of a common environment. The whole IIS internal pipeline has been componentized to originate a distinct and individually configurable component. A new section will be added to the web.config schema of ASP.NET applications to configure the IIS environment.

Put another way, it will be as if the ASP.NET runtime expanded to incorporate and replace the surrounding Web server environment. It's hard to say whether things really went this way or whether it was the other way around. As a matter of fact, the same concepts and instruments you know from ASP.NET are available in IIS 7.0 at the Web server level.

To illustrate, on Windows 2008 Server (and for testing purposes, also on a Windows Vista machine) you can use Forms authentication to protect access to any resources available on the server and not just ASP.NET-specific resources. You might already know that static resources such as HTML pages and JPG images are not served by ASP.NET by default; as such, they're not subject to the authentication rules you set for the application. Where IIS 7.0 is supported, you can now define a handler for some specific and static resources and be sure that IIS will use your code to serve those resources.

Managed ISAPI Extensions and Filters

Today if you want to take control of an incoming request in any version of IIS older than version 7.0, you have no choice other than writing a C or C++ DLL, using either MFC or perhaps the ActiveX Template Library (ATL). More comfortable HTTP handlers and modules are an ASP.NET-only feature, and they can be applied only to ASP.NET-specific resources and only after the request has been authenticated by IIS and handed over to ASP.NET.

In IIS 7.0, you can write HTTP handlers and modules to filter any requests and implement any additional features using .NET code for whatever resources the Web server can serve. More precisely, you'll continue writing HTTP handlers and modules as you do today for ASP.NET, except that you will be given the opportunity to register them for any file type. Needless to say, old-style ISAPI extensions will still be supported, but unmanaged extensions and filters will likely become a thing of the past. I'll demonstrate IIS 7.0 handlers later in the chapter.

< Back      Next >