I have an existing Linux Azure Function running on .Net 6 (In-process) v4. I have a lot of configuration coming from appsettings.json. Most of these configurations are objects with nested properties or arrays (nothing fancy, but common JSON). Some of these configurations are overridden by the Azure Environment Variable panel (former Configuration panel), especially for connectionStrings or some prod-related settings (expiry timer, etc), but most of the appsettings.json config is default settings to apply on each env.
I am trying to update the Azure Function to .NET 8. According to the documentation, I have to migrate to the isolated worker model. This is a heavy breaking change and causing a lot of pain, but I can manage that. The real problem is that the appsettings.json config is not loaded anymore (as it used to) when running in Azure. Everything is fine when running locally. I wasted a lot of time trying to get it to load without success. Config is coming nicely from the Azure Environement Variable panel though.
local.json as it is not able to deal with JSON objects or arrays. I would have to flatten all my configs and that would be a mess.I've reproduced the problem in a test project with a dummy setup and am experiencing the same behavior
Program.cs
var host = new HostBuilder()
.ConfigureFunctionsWebApplication()
.ConfigureServices((appBuilder, services) =>
{
var configuration = appBuilder.Configuration;
services.AddApplicationInsightsTelemetryWorkerService();
services.ConfigureFunctionsApplicationInsights();
services.Configure<DummyOption>(configuration.GetSection(nameof(DummyOption)));
})
.ConfigureAppConfiguration((hostingContext, configBuilder) =>
{
var env = hostingContext.HostingEnvironment;
configBuilder
.AddJsonFile(Path.Combine(env.ContentRootPath, "appsettings.json"), optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
})
.Build();
host.Run();
DummyOption
public class DummyOption
{
public string Foo { get; set; }
}
DummyFunction.cs
public class DummyFunction
{
private readonly ILogger<DummyFunction> _logger;
private readonly DummyOption _options;
public DummyFunction(ILogger<DummyFunction> logger, IOptions<DummyOption> options)
{
_logger = logger;
_options = options.Value;
}
[Function("DummyConfig")]
public IActionResult Run([HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequest req)
{
var json = JsonSerializer.Serialize(_options);
return new OkObjectResult(json);
}
}
appsettings.json
{
"DummyOption": {
"Foo": "Test"
}
}
The function returns {"Foo":"Test"} when running locally but {"Foo":null} when running in Azure. The function returns {"Foo":"yolo"} if I add a DummyOption__Foo = yolo in the Azure Envrionement panel, but again I dont want to do that. This would be a pain to maintain and scale.
Also, I have added the following csproj code to deploy the appsettings.json file with the build, and confirmed the file exist next to the DLL in the Function App files.
<Content Include="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
I even confirmed the file exists, and is accessible by adding some logs in ConfigureAppConfiguration.
Finally, by adding more logs in the ConfigureService, I can see the appsettings.json config is just not loaded in the configuration at all.
I am running out of options and would love some help.
Thanks
Finally managed to get it working by adding this logic
if (context.HostingEnvironment.IsDevelopment() == false)
builder.SetBasePath("/home/site/wwwroot");
The application files (DLLs + appsettings.json) are deployed under "/home/site/wwwroot" BUT context.HostingEnvironment.ContentRootPath resolves to "/azure-functions-host" which contains the DLLs and appsettings.json of the Function Host (not the application itself). So appsettings.json was resolved to {"IncludeScopes":false,"LogLevel":{"Default":"Warning"}}
Directory.GetCurrentDirectory() resolves to "/tmp/functions\\standby\\wwwroot" which isn't helpful.
This is fine on windows but apparently off for Linux. To be honest, I'm not a fan of the solution, but I can't think of anything else for now.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With