Search code examples
c#.netazure-functionsazure-functions-core-tools

Local Azure Functions load local.settings.json from Core Tools Runtime folder and not from Working Directory


I am working on several Azure Functions v4 with .net6.0 at the moment. When trying to start the App locally, I realized that my local.settings.json is not properly loaded.

Before continuing, here is how I load the configuration in the Startup class.

public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            var configuration = new ConfigurationBuilder()
                .AddJsonFile("local.settings.json", true, true)
                .AddEnvironmentVariables()
                .Build();

            var dir = Directory.GetCurrentDirectory();
            // dir is $projectPath\bin\Debug\net6.0
            builder.Services.AddFunctions(configuration);
        }
    }

The file local.settings.json is in the working directory. When debugging into configuration.Providers[0].Data, I can see that nothing has been loaded.

When debugging further I can see configuration.Providers[0].Source.FileProvider.Root points to %localAppData%\AzureFunctionsTools\Releases\4.35.0\cli_x64.

Of course everything works fine, when I put my settings file in this path. But I don't understand why the functions core tools load it from there. Moreover I am working on several functions, all having their own settings. This would force me to manually copy the json files every time in this folder.

Any know, why this is the case?


Solution

  • By default, local.settings.json will be on the application root directory.

    enter image description here

    Local Azure Functions not from Working Directory

    • We can set the Working Directory in the Debug => General.

    • Right click on the Application Root folder => Properties =>Debug => General => Working Directory.

    • Select the Application root path.

    enter image description here

    • As mentioned in the MSDoc, we can use func start to set the path.

    • Also check the launchSettings.json file which specifies the workingDirectory path.

    {
      "profiles": {
        "FunctionApp3": {
          "commandName": "Project",
          "commandLineArgs": "--port 7132",
          "workingDirectory": "C:\\Users\\****\\source\\repos\\April\\FunctionApp3"
        }
      }
    }
    
    • Iam able to load local.settings.json file without any issues.
    • Set the localSetting key-value in local.settings.json.
      {
        "IsEncrypted": false,
      "Values": {
        "AzureWebJobsStorage": "UseDevelopmentStorage=true",
        "FUNCTIONS_WORKER_RUNTIME": "dotnet",
        "localSetting": "Value from local.settings.json file"
      }
    }
    
    • .SetBasePath(Directory.GetCurrentDirectory()) is missing in the Startup file.

    My Startup.cs:

    using FunctionApp3;
    using Microsoft.Azure.Functions.Extensions.DependencyInjection;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using System.IO;
    
    [assembly: FunctionsStartup(typeof(Startup))]
    namespace FunctionApp3
    {
        public class Startup : FunctionsStartup
        {
            public override void Configure(IFunctionsHostBuilder builder)
            {
    
                var configuration = new ConfigurationBuilder()
               .SetBasePath(Directory.GetCurrentDirectory())
               .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
               .AddEnvironmentVariables()
               .Build();
    
                builder.Services.AddSingleton(configuration);
            }
        }
    }
    

    Thanks Azure functions local.settings.json represented in appsettings.json for a ServiceBusTrigger for the reference.

    Function1.cs file:

    using System.IO;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Extensions.Http;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.Logging;
    using Newtonsoft.Json;
    using Microsoft.Extensions.Configuration;
    
    namespace FunctionApp3
    {
        public class Function1
        {
            private readonly IConfiguration _config;
            public Function1(IConfiguration configuration)
            {
                _config = configuration;
    
            }
    
            [FunctionName("Function1")]
            public async Task<IActionResult> Run(
                [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
                ILogger log)
            {
          
                var localsetting = _config["localSetting"];
                var runtime = _config["FUNCTIONS_WORKER_RUNTIME"]; 
    
                var localsetting1 = _config.GetValue<string>("localSetting");
                log.LogInformation(localsetting);
                    
                string name = req.Query["name"];
    
                string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
                dynamic data = JsonConvert.DeserializeObject(requestBody);
                name = name ?? data?.name;
    
                string responseMessage = string.IsNullOrEmpty(name)
                    ? "This HTTP triggered function executed successfully."
                    : $"Hello, {localsetting}.";
    
                return new OkObjectResult(responseMessage);
            }
        }
    }
    

    Output:

    enter image description here enter image description here