3

I'm using appsettings.json in my ASP.NET Core web application to provide configuration values to my application. Some of the configuration is more complex than just "name/value pairs", such as the Serilog configuration:

"Serilog": {
    "MinimumLevel": {
        "Default": "Information",
        "Override": {
            "System": "Warning",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information",
            "Microsoft.AspNetCore.Authentication": "Information"
        }
    },
    "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
    "WriteTo": [
        { "Name": "Console" },
        {
            "Name": "File",
            "Args": {
                "path": "C:/Development/logs/log-auth.txt",
                "fileSizeLimitBytes": 1000000,
                "rollOnFileSizeLimit": true,
                "shared": true,
                "flushToDiskInterval": 1,
                "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {SourceContext} | {Message:lj}{NewLine}{Exception}"
            }
        }
    ]
}

What I want to know is, how can I provide my Azure web app with this configuration? I know I could create an appsettings.Production.json file and push that when I publish, but what is the point in deploying settings with a publish? They might as well be hard-coded. The point of a settings file is that you should be able to change settings and restart the app, changing its behaviour, with no code re-deployment.

The only thing I can see provided by Azure is its "Settings | Configuration" section in the portal, but these settings are only allowed to be simple name/value pairs. My Serilog configuration is not valid there. So how can I provide any kind of advanced configuration?

Jez
  • 27,951
  • 32
  • 136
  • 233

2 Answers2

3

the appsettings.Production.json file is ignored during the publish. You need to use powershell or CI/CD (using Azure Devops for example) in order to define the settings.

About the key/value pairs, you can specify complex types using ':' as the separator For example:

Serilog:MinimumLevel:Default

I've been using the following powershell script:

$appname = "name of your function app"
$rg = "name of resource group"
$webApp = Get-AzureRmwebApp -ResourceGroupName $rg -Name $appname
$webAppSettings = $webApp.SiteConfig.AppSettings
$hash = @{}
foreach ($setting in $webAppSettings) {
    $hash[$setting.Name] = $setting.Value
}
$hash['Serilog:MinimumLevel:Default'] = 'Information'
$hash['Serilog:MinimumLevel:Override:System'] = 'Warning'
$hash['Serilog:MinimumLevel:Override:Microsoft'] = 'Warning'
$hash['Serilog:MinimumLevel:Override:Microsoft.Hosting.Lifetime'] = 'Information'
$hash['Serilog:MinimumLevel:Override:Microsoft.AspNetCore.Authentication'] = 'Information'

$hash['Serilog:Enrich:0'] = "FromLogContext"
$hash['Serilog:Enrich:1'] = "WithMachineName"
$hash['Serilog:Enrich:2'] = "WithThreadId"

$hash['Serilog:WriteTo:0:Name'] = "Console"
$hash['Serilog:WriteTo:1:Name'] = "File"
$hash['Serilog:WriteTo:1:Args:path'] = "C:/Development/logs/log-auth.txt"
$hash['Serilog:WriteTo:1:Args:fileSizeLimitBytes'] = "1000000"
$hash['Serilog:WriteTo:1:Args:rollOnFileSizeLimit'] = "true"
$hash['Serilog:WriteTo:1:Args:shared'] = "true"
$hash['Serilog:WriteTo:1:Args:flushToDiskInterval'] = "1"
$hash['Serilog:WriteTo:1:Args:outputTemplate'] = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {SourceContext} | {Message:lj}{NewLine}{Exception}"


Set-AzureRMWebAppSlot -ResourceGroupName $rg -Name $appname -AppSettings $hash -Slot production

PS: double check the settings / values after the execution...

Thiago Custodio
  • 17,332
  • 6
  • 45
  • 90
  • Unfortunately, the Azure app portal doesn't allow colons in the key names. – Jez Mar 04 '20 at 16:40
  • it allows: https://blogs.msdn.microsoft.com/cjaliaga/2016/08/10/working-with-azure-app-services-application-settings-and-connection-strings-in-asp-net-core/ – Thiago Custodio Mar 04 '20 at 16:53
  • Have you actually tried creating a Web App in Azure app portal and creating config settings through the UI? That article is from 2016, perhaps they have introduced the restriction since. Here's a screenshot: https://i.stack.imgur.com/Ey2Ny.png – Jez Mar 04 '20 at 17:06
  • In fact I just did. Here's the printscreen: https://postimg.cc/Y4DC3Pdz – Thiago Custodio Mar 04 '20 at 17:09
  • It's working fine for me. Check if there's no empty spaces (before / after). If it's not the case, try using underscore rather than : – Thiago Custodio Mar 04 '20 at 17:10
  • I'm interested as to why it's letting you insert colons. Could you use LICEcap to show an animated GIF of you creating a new setting through that UI and typing it in? It's somehow behaving differently for me. – Jez Mar 04 '20 at 17:11
  • 1
    OK, looking at [this discussion](https://stackoverflow.com/questions/51480085/configuring-appsettings-with-asp-net-core-on-azure-web-app-for-containers-whith) I've figured it out. It's because the web app is hosted on Linux, which doesn't allow colons (this is why I hate using env variables; they differ per platform!) On Linux hosts you have to use the double underscore (`__`) instead. – Jez Mar 04 '20 at 17:14
3

As Thiago already said, you can add more then simple key/value configuration using :. However, if you have to deal with larger application configurations I would suggest using Azure App Configuration.

On Linux-hosted web apps, Azure won't allow you to insert colons into configuration settings presumably because it's not allowed in Linux environment variable names. Instead of colons, use double-underscores (__).

See also: Import or export configuration data

Jez
  • 27,951
  • 32
  • 136
  • 233
Martin Brandl
  • 56,134
  • 13
  • 133
  • 172