I recently experienced the same problem and fixed it:
In Azure App Services, the machine-wide web.config
file is located at D:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\web.config
.
This file differs to a normal machine-wide web.config
file because it has this extra element:
<system.web>
...
<compilation>
<assemblies>
<add assembly="EnvSettings, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
...
</assemblies>
</compilation>
</system.web>
The EnvSettings.dll
assembly is located inside D:\Program Files\IIS\Microsoft Web Hosting Framework
(unfortunately this directory is access-controlled and I can't get into it).
- But
EnvSettings.dll
is mirrored in the GAC, so I was able to copy it from there.
Inside EnvSettings.dll
is an [assembly: PreApplicationStartMethod]
attribute that runs a method in EnvSettings.dll
which copiesthe APPSETTING_
and database connection-string settings from Environment Variables into the .NET Framework ConfigurationManager.AppSettings
and ConfigurationManager.ConnectionStrings
collections.
- Note this copying only happens once (during application startup), and only in the first
AppDomain
- so if you have other AppDomain
instances in your application they won't see the updated ConfigurationManager
.
Therefore, if you see that your Azure Portal configuration settings for your App Service are not being used when you dump your ConfigurationManager
, then the following is likely happening:
- You used
<clear />
in your <compilation><assemblies>
element, which stops EnvSettings.dll
from being loaded at all.
- In which case you need to either add back the
<add assembly="EnvSettings...
element from above to your own web.config
, or find some other way to load it.
- I don't recommend saving
EnvSettings.dll
locally and adding an assembly reference to your project, as EnvSettings.dll
is part of the Microsoft Web Hosting Framework.
- Or you have code that is clearing or resetting
ConfigurationManager
after EnvSettings
populates it for you.
- Or something else is going on that I have no idea about!
As an alternative to having EnvSettings.dll
copy your settings over, another option is to copy the environment-variables over yourself - and as you control the code that does this it means you can call it whenever you need to (e.g. if you ever reset them).
Here's the code I used:
public static class AzureAppSettingsConfigurationLoader
{
public static void Apply()
{
foreach( DictionaryEntry environmentVariable in Environment.GetEnvironmentVariables() )
{
String name = (String)environmentVariable.Key;
String value = (String)environmentVariable.Value;
if( name.StartsWith( "APPSETTING_", StringComparison.OrdinalIgnoreCase ) )
{
String appSettingName = name.Substring( "APPSETTING_".Length );
ConfigurationManager.AppSettings[ appSettingName ] = value;
}
else if( name.StartsWith( "SQLAZURECONNSTR_", StringComparison.OrdinalIgnoreCase ) )
{
String csName = name.Substring( "SQLAZURECONNSTR_".Length );
ConfigurationManager.ConnectionStrings.Add( new ConnectionStringSettings( csName, value, providerName: ""System.Data.SqlClient" ) );
}
}
}
}