Modules & the Integrated Pipeline: Handlers, Managed Modules & Native Modules
IIS In Depth
Chapter 4 · Modules & the Integrated Pipeline: Handlers, Managed Modules & Native Modules
Web Servers Fundamentals never covered this at all — the module pipeline is a genuinely new topic for this course, not a deepening of something already introduced. It's also the mechanism that makes Chapter 3's own configuration sections actually do something: a locked system.webServer/authentication section only matters because an authentication module reads it on every single request, at a specific, predictable point in a fixed processing pipeline.
Request Processing: A Sequence of Named Events
Every request IIS handles moves through a fixed sequence of named pipeline events, in this order:
A module doesn't run "somewhere during the request" — it registers itself against one or more of these specific named events, and IIS calls it at exactly that point for every applicable request. An authentication module hooks AuthenticateRequest. An authorization module hooks AuthorizeRequest, immediately after. Output caching hooks ResolveRequestCache (checking for a cached response) and UpdateRequestCache (storing a new one) — the exact mechanism behind the Output Caching that Web Servers Fundamentals Chapter 9 only named in passing. The actual content-generating work — running an ASP.NET page, serving a static file — happens at ExecuteRequestHandler, which is where handlers (below) come in, distinct from modules.
Modules vs. Handlers: A Genuine Distinction
It's easy to conflate the two, but they do different jobs. A module can run on every request, hooks one or more pipeline events, and typically doesn't generate the actual response body — authentication, authorization, logging, URL rewriting, and compression are all modules. A handler is what actually produces the response content for a specific request, and exactly one handler runs per request, selected by matching the request against a table of path/verb patterns:
A request for /images/logo.png matches the StaticFile handler mapping and gets served directly off disk. A request into an ASP.NET Core app matches the AspNetCore handler mapping and gets handed off to that runtime entirely. Handler mappings are themselves just another system.webServer section — subject to exactly the same inheritance, <clear />/<add>/<remove>, and overrideModeDefault locking behavior Chapter 3 already covered.
Native Modules vs. Managed Modules
A module is either native (a compiled C++ DLL, running as part of the IIS worker process itself — HttpModule entries registered in <globalModules>) or managed (a .NET class implementing IHttpModule, running inside the .NET runtime hosted by that same worker process). Both kinds can hook the same pipeline events shown above — the distinction is about what actually executes the module's code, not which events are available to it.
| Native modules | Managed modules | |
|---|---|---|
| Written in | C++, compiled to a DLL | .NET (C#/VB), an IHttpModule class |
| Runs | Directly in the IIS worker process | Inside the .NET runtime hosted by the worker process |
| Applies to | Every request, regardless of content type | Every request, in Integrated mode (see below) |
| Examples | StaticFileModule, DefaultDocumentModule, HttpCacheModule | FormsAuthenticationModule, SessionStateModule, custom ASP.NET modules |
Why Integrated Mode Was a Real Architectural Change
Before IIS 7, a request destined for ASP.NET ran through two genuinely separate pipelines: the native IIS pipeline handled the request first, then handed off to a completely separate ASP.NET pipeline (via the ISAPI extension aspnet_isapi.dll) for anything .aspx. A managed IHttpModule could only ever see the second, ASP.NET-only pipeline — it had no visibility into, say, a plain static file request, since that never entered the ASP.NET pipeline at all. Integrated mode, introduced in IIS 7 and the modern default ever since, merges these into one single pipeline: the same eleven events shown above apply uniformly, and a managed module can now hook AuthenticateRequest for any request — a static image, a classic ASP page, anything — not just ASP.NET content. Classic mode (the old two-pipeline behavior) still exists for legacy application compatibility, but is genuinely a compatibility fallback at this point, not a real architectural choice for anything new.
BeginRequest/ResolveRequestCache) — which is exactly why a rewrite rule can redirect a request before any handler, native or managed, ever runs against it.
applicationHost.config's <globalModules>/<modules> sections and simply never appear in any individual application's own web.config at all — it still runs against every request that application serves. When troubleshooting unexpected behavior (a header appearing that no application code sets, a response being compressed or cached unexpectedly), checking the full registered module list at the machine level is often more informative than searching application-level configuration for an explanation that isn't there.
Hands-On Exercises
Explain, in your own words, the difference between a module and a handler in IIS's pipeline model, and why exactly one handler runs per request while many modules can run against the same request.
📄 View solutionBefore IIS 7's Integrated mode, why couldn't a managed IHttpModule affect how IIS served a plain static image file, even if that module hooked an event equivalent to AuthenticateRequest? What specifically changed with Integrated mode to fix this?
📄 View solutionA site is unexpectedly compressing responses even though no application code or web.config on that site enables compression. Using this chapter's own module concepts, explain the most likely cause and where you'd look to confirm it.
📄 View solutionChapter 4 Quick Reference
- Pipeline events — a fixed sequence (BeginRequest → AuthenticateRequest → AuthorizeRequest → ResolveRequestCache → MapRequestHandler → ... → ExecuteRequestHandler → ... → EndRequest) that every request moves through in order
- Modules — hook one or more pipeline events, can run on every request, don't generate the response body themselves (auth, logging, rewriting, compression)
- Handlers — exactly one per request, matched by path/verb, actually produce the response content at ExecuteRequestHandler
- Native (C++, in-process) vs. Managed (.NET, IHttpModule) — both hook the same events, differing in what executes the code
- Integrated mode (modern default) merges the old dual native/ASP.NET pipelines into one, letting managed modules see every request; Classic mode is a legacy compatibility fallback