Arrays in Azure Web App Configuration

In this blog I'll show you why to avoid arrays in appsettings.json when deploying to Azure.

Strange Behavior

When deploying a Web App to Azure you need to override your configuration. I had this in my appsettings.json file:

appsettings.json

{
  ...
  "CORS": {
    "AllowedDomains": [ "https://localhost:44306" ]
  }
}

And I used the Azure portal to override the configuration as follows:

/azureconfigarray/azureconfigoverride.png

To my surprise the deployed application was still using localhost instead of the production URL.

Investigation

I set up a little test with the following C# code:

ViewBag.AllowedDomainsAsString = configuration["CORS:AllowedDomains"]; // read as string

var strings = configuration.GetSection("CORS:AllowedDomains").Get<string[]>();
ViewBag.AllowedDomainsAsStringArray = string.Join(',',strings);

This gave me the following result:

/azureconfigarray/azureconfigresult.png

It turns out that reading configuration as a string[] would always give me the values from appsettings.json.

This makes sense when you think about it. The way Azure overrides configuration is by setting environment variables. And environment variables have to be strings, not arrays. I could clearly see my mistake when using the 'Advanced Editor' in Azure.

Advanced Editor

[
  {
    "name": "CORS:AllowedDomains",
    "value": "[\"https://lander.edu\"]",
    "slotSetting": false
  }
]

Removing the double quotes would lead to an invalid file. So, no luck there.

Solution

Three solutions came to mind:

  • Overriding appsettings.json in the build pipeline
  • Using Azure App Configuration (which is a separate service in Azure)
  • Using a string and separating the URLs using a specific character

appsettings.json

{
  ...
  "CORS": {
    "AllowedDomains": "https://localhost:44306;https://localhost:44307"
  }
}

I ended up doing the last thing since it was a minor change.

Conclusion

Be wary about using arrays in your configuration. The problem does not occur with objects, or non-string primitives like numbers. For objects you can simply use the : or __ separator. And non-string primitives simply convert properly from a string.