The Configuration Model: web.config, applicationHost.config & Configuration Inheritance

IIS In Depth

Chapter 3 · The Configuration Model: web.config, applicationHost.config & Configuration Inheritance

Web Servers Fundamentals Chapter 3 introduced the shape of IIS's own configuration model — applicationHost.config machine-wide, web.config per-directory — and noted it sits structurally closer to Apache's own .htaccess philosophy than to Nginx's single centralized file. What it didn't cover is how a setting actually gets resolved once more than one web.config exists in the same directory chain, or what stops a subdirectory from overriding something the machine administrator deliberately locked down. That's this chapter.

The Configuration Hierarchy

Every configurable setting in IIS lives somewhere in a layered hierarchy of XML files, read in a fixed order from the most general to the most specific:

%windir%\System32\inetsrv\config\applicationHost.config -- machine-wide, all sites C:\inetpub\wwwroot\web.config -- site root C:\inetpub\wwwroot\api\web.config -- /api subdirectory C:\inetpub\wwwroot\api\admin\web.config -- /api/admin subdirectory

A request to /api/admin/users doesn't just read the deepest web.config in isolation — IIS reads every file in the chain above it, starting at applicationHost.config and walking down through each web.config in turn, merging settings as it goes. This is precisely the same directory-context idea Apache In Depth Chapter 3 covers for .htaccess — the deepest applicable file wins for any setting it actually specifies, and any setting it doesn't specify simply falls through to whatever the level above it already resolved to.

How Merging Actually Works: Add, Remove, Clear

For simple scalar settings — a boolean, a numeric limit — a more specific web.config value straightforwardly replaces the less specific one. Collection-based settings (a list of default documents, a list of MIME types, a list of modules) behave differently, because IIS's configuration schema exposes three explicit collection actions rather than silently overwriting the whole list:

<system.webServer> <defaultDocument> <files> <clear /> <add value="index.html" /> <add value="default.aspx" /> </files> </defaultDocument> </system.webServer>

<add> appends an item to whatever the collection already inherited from the level above. <remove> takes out one specific inherited item by name, leaving the rest. <clear> discards everything inherited so far and starts the collection fresh at that point in the hierarchy — used here before adding this directory's own two default documents, so this subdirectory's list isn't quietly appended onto whatever the site root or machine level already had configured.

Forgetting <clear /> doesn't reset a collection — it appends to it
A very common mistake: adding a web.config in a subdirectory intending to replace the default-document list, without a <clear /> first. Without it, the new <add> entries land on top of everything already inherited from the site root and machine level, producing a longer, unintended combined list rather than the shorter, intentional one — this is a genuine, easy-to-miss gotcha specific to how IIS's collection inheritance works, with no equivalent concept in a scalar setting.

Locking Sections: overrideModeDefault and allowOverride

Inheritance alone doesn't stop a subdirectory from overriding something a machine administrator never wanted overridden at all — that's a separate, deliberate lock, configured at the machine level:

<!-- applicationHost.config --> <section name="authentication" overrideModeDefault="Deny" /> <section name="defaultDocument" overrideModeDefault="Allow" />

Each configuration section — system.webServer/authentication, system.webServer/defaultDocument, and so on — carries its own overrideModeDefault, set in applicationHost.config's own <sections> declarations. Allow means any web.config further down the hierarchy is free to override that section. Deny means it isn't — a web.config that attempts to set a locked section produces an actual HTTP 500.19 configuration error rather than silently being ignored. Several security-sensitive sections ship Deny by default precisely so that an application deployed by someone without machine-level access can't quietly re-enable something an administrator locked down — system.webServer/authentication among them, which is exactly why Chapter 8's Windows Authentication material has to be configured at a level with the necessary permission, not casually from an arbitrary application's own web.config.

overrideModeDefaultEffectTypical use
AllowAny web.config down the chain may override this sectionMost content/display sections — defaultDocument, staticContent, etc.
DenyOnly applicationHost.config (or a location tag there) may set it; a web.config attempt fails with 500.19Security-sensitive sections — authentication, authorization, and similar

Overriding a Locked Section From the Machine Level: <location>

A locked (Deny) section isn't necessarily fixed identically for every site forever — an administrator with access to applicationHost.config itself can still grant one specific site or path a different value, using a <location> tag:

<!-- applicationHost.config --> <location path="Default Web Site/api"> <system.webServer> <authentication> <windowsAuthentication enabled="true" /> </authentication> </system.webServer> </location>

This is how a locked, Deny-mode section still ends up different for one specific site or subdirectory without unlocking it for every application on the server — the override lives entirely inside applicationHost.config, scoped by path, rather than inside that site's own web.config. The distinction that matters: a <location> block is still machine-level configuration, written by whoever has access to applicationHost.config itself — it is not a loophole an application deployer can reach from their own web.config.

Resolution Order, Put Together

  1. IIS Manager or a config tool checks applicationHost.config's section declarations for overrideModeDefault (and any <location> override) — this determines whether a lower-level web.config is even permitted to touch that section
  2. Reading proceeds top-down: applicationHost.config, then each web.config from the site root down to the requested directory
  3. Scalar settings from a deeper file simply replace shallower ones
  4. Collections accumulate via <add>/<remove> unless a <clear /> resets them at that level
  5. The final, fully-merged configuration for that specific request path is what IIS actually applies
Where this points forward in this course
Chapter 5's virtual directories and application boundaries determine exactly which physical folder a URL path maps onto in the first place — this chapter's own hierarchy walk only makes sense once that mapping is settled. And Chapter 6's URL Rewrite rules are themselves just another system.webServer section, subject to the exact same Allow/Deny/<location> mechanics covered here.
A 500.19 error means a locked section, not a syntax error
An HTTP 500.19 is easy to mistake for malformed XML, and it's worth checking for that first — but a perfectly well-formed web.config that attempts to set a section locked with overrideModeDefault="Deny" produces exactly the same 500.19 status. The actual IIS error page names the specific config source and section responsible, which is the fastest way to tell the two apart rather than guessing.

Hands-On Exercises

Exercise 1

A site's root web.config sets a defaultDocument list of index.html and default.aspx. A subdirectory's own web.config adds home.html with <add value="home.html" />, but includes no <clear />. List, in order, the final default-document list IIS will actually try for a request into that subdirectory, and explain why.

📄 View solution
Exercise 2

A developer with no access to applicationHost.config tries to enable Windows Authentication from their application's own web.config and gets an HTTP 500.19 error. Explain what's actually happening, and describe the one legitimate way an administrator could still grant that specific application a different authentication setting than the rest of the server.

📄 View solution
Exercise 3

Explain, in your own words, why IIS's configuration model needs three distinct collection actions (add, remove, clear) instead of just letting a more specific web.config's collection value silently replace a less specific one, the way a scalar setting does.

📄 View solution

Chapter 3 Quick Reference

  • Hierarchy — applicationHost.config (machine) → web.config at the site root → web.config at each subdirectory down to the request path
  • Scalars replace; collections accumulate via <add>/<remove> unless reset with <clear />
  • overrideModeDefault — Allow lets a web.config override a section; Deny restricts it to applicationHost.config, producing a 500.19 if violated
  • <location path="..."> — how a machine administrator grants one specific site/path a different value for an otherwise-locked section, without unlocking it server-wide
  • A 500.19 can mean either malformed XML or a locked section — the IIS error page names which