json.netazureconfigurationazure-functions

Using profile/environment specific local.settings.json in Azure Functions


Just in the same way you can use the launchSettings.json in other project types to then specify what appsettings file you would like to include, I was wondering if there was a way to do this with local.settings.json in an Azure Function.

I have this in use in a Blazor WASM project and have used similar things in the past, but this approach causes exceptions:

Used in other projects:

builder.Configuration.AddJsonFile("local.settings.json", optional: false);

builder.Configuration.AddJsonFile($"local.settings.{builder.Environment.EnvironmentName}.json", optional: true);

Similar approach used in Azure Function:

      .ConfigureAppConfiguration((context, config) =>
      {
          var env = Environment.GetEnvironmentVariable("NETCORE_ENVIRONMENT", EnvironmentVariableTarget.Process);
          config.SetBasePath(Directory.GetCurrentDirectory());
          config.AddJsonFile($"local.settings.environment.json", optional: true, reloadOnChange: true);
          config.AddEnvironmentVariables();
      })

Exception:

Failed to load configuration from file 'api\bin\Debug\net8.0\local.settings.environment.json'
Inner Exception:
FormatException: A duplicate key 'Values:ApplicationSettings:AzureTableSettings:ConnectionString' was found.

This what how I have configured my launchSettings.json

{
    "profiles": {
        "Development": {
            "commandName": "Project",
            "environmentVariables": {
                "AZURE_FUNCTIONS_ENVIRONMENT": "Development",
                "LOCAL_SETTINGS_FILE": "local.settings.json"
            }
        },
        "Environment": {
            "commandName": "Project",
            "environmentVariables": {
                "AZURE_FUNCTIONS_ENVIRONMENT": "Development",
                "LOCAL_SETTINGS_FILE": "local.settings.environment.json"
            }
        }
    }
}

I can't seem to find any guidance on how to configure an Azure Function to use environment or profile specific app settings files.

Any help would be greatly appreciated.


Solution

  • I do agree with @Harshitha that in local, you can only use local.settings.json , So you use locally (local.settings.json) and you can use Custom Json file in Portal/Production ( I am using appsetting.json) to get values or use it without Adding values in Environment Variables. To achieve this you can follow below approach:

    appsettings.json:

    {
    "Rithsetting":"cc"
    }
    

    csproj:

    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <TargetFramework>net8.0</TargetFramework>
        <AzureFunctionsVersion>v4</AzureFunctionsVersion>
        <OutputType>Exe</OutputType>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
      </PropertyGroup>
      <ItemGroup>
        <FrameworkReference Include="Microsoft.AspNetCore.App" />
        <PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.20.1" />
        <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.1.0" />
        <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="1.2.0" />
        <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.16.4" />
        <PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.21.0" />
        <PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="1.1.0" />
      </ItemGroup>
      <ItemGroup>
        <None Update="host.json">
          <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </None>
        <None Update="local.settings.json">
          <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
          <CopyToPublishDirectory>Never</CopyToPublishDirectory>
        </None>
          <None Update="appsettings.json">
              <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
          </None>
          <None Update="appsettings.Development.json">
              <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
              <CopyToPublishDirectory>Never</CopyToPublishDirectory>
      </None>
          </ItemGroup>
      <ItemGroup>
        <Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext" />
      </ItemGroup>
    </Project>
    

    Program.cs:

    using FunctionApp7;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    
    var rith = new HostBuilder()
                   .ConfigureFunctionsWebApplication()
                   .ConfigureAppConfiguration((context, builder) =>
                   {
                       builder.SetBasePath(context.HostingEnvironment.ContentRootPath)
                              .AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
                              .AddJsonFile($"appsettings.{context.HostingEnvironment}.json", optional: true, reloadOnChange: false)
                              .AddEnvironmentVariables();
                       if (context.HostingEnvironment.IsDevelopment() == false)
                           builder.SetBasePath("/home/site/wwwroot");
                   })
                   .ConfigureServices((context, services) =>
                   {
                       var configuration = context.Configuration;
    
                       services.AddLogging();
                   })
                   .Build();
    
    rith.Run();
    

    Function.cs:

    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Azure.Functions.Worker;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.Logging;
    
    namespace FunctionApp7
    {
        public class Function1
        {
            private readonly ILogger<Function1> rilg;
            private readonly IConfiguration _configuration;
    
            public Function1(ILogger<Function1> logger, IConfiguration configuration)
            {
                rilg = logger;
                _configuration = configuration;
            }
    
            [Function("Function1")]
            public IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req)
            {
                rilg.LogInformation("C# HTTP trigger function processed a request.");
    
                var RithSetting = _configuration["RithSetting"];
                var rithSetting = _configuration.GetValue<string>("RithSetting");
                rilg.LogInformation(rithSetting);
                rilg.LogInformation($"RithSetting value: {rithSetting}");
                return new OkObjectResult($"Welcome to Azure Functions! Rith Setting: {rithSetting}");
            }
        }
    }
    

    loacl.settings.json:

    {
      "IsEncrypted": false,
      "Values": {
        "AzureWebJobsStorage": "UseDevelopmentStorage=true",
        "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
        "RithSetting": "Testing"
      }
    }
    

    Output:

    local:

    enter image description here

    Portal:

    enter image description here

    You can use this way only as this is inbuilt property that it only uses local.settings.json in local and from Custom Json File(appsettings.json in my case).

    For further information refer my answer's from SO-Thread1 and SO-Thread2.