Today, I ran into an unusual behavior of ASP.NET Core application deployed to Azure App Service. It could not find the connection string, even though it was present on the Connection Strings pane of the App Service in the Azure portal.
This is how the screen looked like:
The application was accessing the connection string using the standard ASP.NET Core configuration API, as shown in the following code snippet:
sevices.AddNpgsqlDataSource(configuration.GetConnectionString("aisistentka-db"));
Naturally, everything works as expected locally, but when I deployed the app to Azure, it did not start, with the exception “Host can’t be null.”
When diagnosing this kind of issues, it is a good idea to start with the Kudu console (located at https://your-site-name.scm.azurewebsites.net). A quick check of the environment variables usually shows what is wrong.
Every connection string should be passed to the application as an environment variable. Normally, the ASP.NET Core’s GetConnectionString method should look for the ConnectionStrings:connectionStringName configuration key (which is usually in the appsettings.json file or in User Secrets). Since environment variables cannot contain colons, they can be replaced with double underscores – the .NET configuration system treats these separators as equal.
However, the type field in the Azure portal (you can see it in the picture at the beginning of the article) provides a special behavior and somehow controls how the environment variable names are composed. In the case of PostgreSQL, the resulting variable name is POSTGRESQLCONNSTR_aisistentkadb. As you can see, instead of ConnectionStrings__ prefix, the prefix is POSTGRESQLCONNSTR_, and the dash from the connection string name is removed.
This was a bit unexpected for me. The GetConnectionString method cannot see the variable, but when I use the type “SQL Server”, the same approach works (though, the dashes in connection string names do not). How is this possible?
I looked in the source code of .NET and found out that there is a special treatment of these Azure prefixes, but not all of them are included. It only supports SQL Server, SQL Azure, MySQL, and Custom types. All other options will produce an incorrect name of environment variable that the application will not find.
/// <summary>
/// Provides configuration key-value pairs that are obtained from environment variables.
/// </summary>
public class EnvironmentVariablesConfigurationProvider : ConfigurationProvider
{
private const string MySqlServerPrefix = "MYSQLCONNSTR_";
private const string SqlAzureServerPrefix = "SQLAZURECONNSTR_";
private const string SqlServerPrefix = "SQLCONNSTR_";
private const string CustomConnectionStringPrefix = "CUSTOMCONNSTR_";
...
The solution was to use the Custom type and remove the dash from the connection string name.