Web.config location element demystified
I haven't actually met a lot of people who knew the details about the hierarchy of Web.config
files and how to utilize the location
element. In fact, I've heard multiple people ask "why is there a Web.config
file in the Views
folder of my MVC application?". Even ASP.NET Core projects require a Web.config
file (generated on publish) and you can still use some of the features in there to control the execution of your ASP.NET Core website. When you have finished this post you should be an expert.
If we forget about Web.config
being an XML file with the disadvantages this causes, it is a pretty powerful feature when hosting a website on IIS.
Web.config hierarchy
Before we start discussing the location
element, I want to introduce you to the concept of having multiple Web.config
files. You already know the one generated in the root of a new project:
This file controls a lot of features in this application, like application settings and HTTP modules and handlers. In a real application you typically have subdirectories, which will allow you to handle requests to an URL like /sub/
. The settings inside the Web.config
file are available for both the root as well as any subdirectories. Let's say you want some settings specific and visible for /sub/
only, you can place an overwriting Web.config
file inside the sub
folder. To illustrate, let's create a simple example where appSettings
are overwritten.
For the example, I've created a folder named sub
and a new Default.aspx
file inside that folder. This example is using WebForms but it could be anything on top of IIS. Inside the sub
folder, I'm also placing a new Web.config
file:
In the appSettings
element of the Web.config
file located in the root, I'll create a new setting named Message
:
<configuration>
<appSettings>
<add key="Message" value="Frontpage"/>
</appSettings>
...
</configuration>
In the appSettings
element of the Web.config
file located in the Sub
folder, I'll create a similar setting also named Message
:
<configuration>
<appSettings>
<add key="Message" value="Subpage"/>
</appSettings>
</configuration>
Notice how the first file contains more configuration (represented by the three dots) and the configuration in the Web.config
file in the Sub
folder only contains the overwriting config.
To test that everything is working, replace the content of the Default.aspx
file in the Sub
folder with the following markup:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication9.sub.Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<h1>Hello from <%= ConfigurationManager.AppSettings["Message"] %></h1>
</body>
</html>
You already guessed it. When navigating to /sub/
, the message is Hello from Subpage
:
Location element
Finally! This is why you came here in the first place, right? While having Web.config
files spread across folders, sometimes it is just easier to configure everything in the same place. The location
element lets us do exactly that. By specifying a location
start and end tag inside the web application, we have a "mini" Web.config
file included in the normal Web.config
. Confused? Let's re-create the previous scenario, but with everything included in the same Web.config
file:
<configuration>
<appSettings>
<add key="Message" value="Frontpage"/>
</appSettings>
<location path="Sub">
<appSettings>
<add key="Message" value="Subpage"/>
</appSettings>
</location>
...
</configuration>
If you are creating your own example, make sure to delete theWeb.config
file in theSub
folder.
Inside the location
element, I've added a new appSettings
element. In fact, the possible nested elements of location
are the ones from the configuration
element. This means you can add a system.webServer
element or any other element allowed for a Web.config
file inside location
.
allowOverride
Besides the path
attribute on the location
element, there's another interesting attribute named allowOverride
. With this attribute, you can lock the content of the location
element. Let's create an example illustrating how this works.
You can combine the use of both the location
element and a Web.config
file in a subdirectory. ASP.NET will always use the configuration closest to the page you are requesting. In the scenario where we have appSettings
specified in three different locations, when requesting /Sub/
IIS will look for configuration in the following order:
- In a
Web.config
file in theSub
folder. - In a
location
element withpath
set toSub
in theWeb.config
file in the root folder. - In the
Web.config
file in the root folder.
To test this, add the Web.config
file from the first example to the Sub
folder and replace the content with this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="Message" value="Web.config in Sub folder"/>
</appSettings>
</configuration>
When running the application, you will see the new message:
To lock the configuration in the Web.config
file in the root directory, add allowOverride="false"
:
<configuration>
<appSettings>
<add key="Message" value="Frontpage"/>
</appSettings>
<location path="Sub" allowOverride="false">
<appSettings>
<add key="Message" value="Subpage"/>
</appSettings>
</location>
...
</configuration>
Launching the project will now cause an exception, since the Web.config
file in the Sub
folder is trying to override settings that it isn't allowed to:
Wildcard and regular expression
I've seen question after question, requesting the use of wildcards, regular expressions and similar in the path
attribute of the location
element. Like being able to target something like all sub-directories with a specific naming pattern:
<location path="languages/*">
I'm sorry to be the one to break it to you. It's not possible. The path
attribute requires an absolute path to an existing file or directory.