Setting an aspnet.config File per Application Pool

The aspnet.config file is a little known config file which is supported by ASP.NET 2.0 and greater.  Generally it lives in the root of the framework folder, for example:

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet.config
C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet.config
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\aspnet.config
C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet.config

This config file is further leveraged in ASP.NET 4.0 for concurrency and threading.  For example, you can set maxConcurrentRequestsPerCPU, maxConcurrentThreadsPerCPU and requestQueueLimit, in addition to the previous runtime settings.

In Windows Server 2008 R2 (IIS 7.5) support was added to allow different settings per application pool.  Where previously the settings had to be applied to the whole framework version, now they can be specific to each app pool.

This is supported by a new attribute for the IIS app pool called CLRConfigFile mentioned in this MSDN article.  There is no default value which means that if you don’t set it, it will read the framework’s aspnet.config file and not look for additional files.

It doesn’t appear to be configurable from the application pool settings in IIS so you must use any of the manual ways to set it.  appcmd is probably the easiest.  Here’s what it will look like, notice the two variables are the path and the application pool name:

%windir%\System32\inetsrv\appcmd.exe set config  -section:system.applicationHost/applicationPools /[name='DefaultAppPool'].CLRConfigFile:"c:\inetpub\AppPoolClrConfig\DefaultAppPool_aspnet.config"  /commit:apphost

Below is another copy of the same, but as a template.  Just swap out the {AppPoolName} and {FilePath} with your settings. (run appcmd from %windir%\System32\inetsrv)

appcmd.exe set config  -section:system.applicationHost/applicationPools /[name='{AppPoolName}'].CLRConfigFile:"{FilePath}"  /commit:apphost

Note that the framework aspnet.config file is still used so only differences per app pool need to be set here.

Here’s an example of what the file can contain:

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<runtime>
<legacyUnhandledExceptionPolicy enabled="false" />
<legacyImpersonationPolicy enabled="true"/>
<alwaysFlowImpersonationPolicy enabled="false"/>
<SymbolReadingPolicy enabled="1" />
<shadowCopyVerifyByTimestamp enabled="true"/>
</runtime>
<startup useLegacyV2RuntimeActivationPolicy="true" />
<system.web>
<applicationPool
maxConcurrentRequestsPerCPU="5000"
maxConcurrentThreadsPerCPU="0"
requestQueueLimit="5000" />
</system.web>
</configuration>

As for disk permissions, the app pool will try to read the file using the app pool’s identity.  Since this file is probably not a security risk you can grant Users with read permissions and it will work.  Alternately, you can properly lock down the file like so:

icacls c:\inetpub\AppPoolClrConfig\DefaultWebSite_aspnet.config /grant "IIS APPPOOL\DefaultAppPool":(R)

Be sure that the file doesn’t have inheritance or other more permissive permissions already set.

Now you can make adjustments per app pool in each of the corresponding config files, and it’s also fine to point multiple app pools to the same config file.

Changes are picked up when the app pool is created, so after applying any changes be sure to recycle the app pool. 

Note also that this is for IIS 7.5 and greater, and the applicationPool settings only apply in Integrated Pipeline mode.

Here are some good links with further reading:

No Comments