4

I have trouble reading configuration values from appSettings.json file in webjob. The webjob uses the following nuget packages:

enter image description here

I have two settings file in my console application (webjob): appsettings.development.json appsettings.production.json

In the Main method, the webjob is configured as follows:

 static void Main(string[] args)
    {
        var builder = new HostBuilder()
                .ConfigureWebJobs(webJobConfiguration =>
                {
                    webJobConfiguration.AddTimers();
                    webJobConfiguration.AddAzureStorageCoreServices();  
                })
                .ConfigureAppConfiguration((hostingContext, config) =>
                 {
                     var env = hostingContext.HostingEnvironment;
                     Console.WriteLine("hostingContext.HostingEnvironment: " + env.EnvironmentName);
                     config.SetBasePath(Directory.GetCurrentDirectory())
                     .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: false, reloadOnChange: true)
                     .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: false, reloadOnChange: true)
                     .AddEnvironmentVariables().Build();
                 })
                .ConfigureServices((context, serviceCollection) =>
                {
                    serviceCollection.AddSingleton<IConfiguration>(context.Configuration);
                    serviceCollection.AddTransient<SayHelloWebJob>(job => new SayHelloWebJob(context.Configuration));
                })
                .Build();

        builder.Run();
    }

The code for SayHelloWebJob is below:

public class SayHelloWebJob
{
     static IConfiguration _configuration;
    public SayHelloWebJob(IConfiguration config)
    {
        _configuration = config;
        Console.WriteLine("Initialized SayHelloWebJob");
    }

    [Singleton]
    public static void TimerTick([TimerTrigger("0 */1 * * * *")]TimerInfo myTimer)
    {
        Console.WriteLine($"From SayHelloWebJob: Hello at {DateTime.UtcNow.ToString()}");
        var test = _configuration.GetSection("WebJobConfiguration:message").Value;
        Console.WriteLine("Configuration access: message: " + test);
        Console.WriteLine("Configuration access: " + _configuration.GetSection("WebJobConfiguration:api").Value);
        Console.WriteLine("configuration object: "+ _configuration.GetConnectionString("AzureWebJobsStorage"));

    }
}

When I run my webjob, I see that console.writeline logs never output the configurations which I'm trying to read in the TimerTick method.

Questions:

  1. How can I inject the appSettings configuration inside the TimerTick method?
  2. I have two appSettings files - for development & production. How can I make sure the correct file gets loaded during production?

Example appSettings.development.json file below:

{
"connectionStrings": {
    "AzureWebJobsStorage": stringhere",
    "AzureWebJobsDashboard": "stringhere"
},
"WebJobConfiguration": {
    "message": "I'm running locally!",
    "pfuWebApiUrl": "API link here",
    "api": "api here",
    "ApplicationInsights": {
        "InstrumentationKey": "key here"
    }
}

}

user2439903
  • 1,277
  • 2
  • 34
  • 68

2 Answers2

2

My preference is to have all environment configuration checked in as you have and it is definitely possible to load the correct file at runtime based on environment.

First set your config files to "copy to output directory in newer" in the Properties pane in Visual Studio or add this to your csproj:

    <None Update="base.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
    </None>
    <None Update="prod.settings.json">
      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
    </None>

Now you just need to load the correct configuration at runtime.

        private static IConfigurationRoot GetConfiguration(string basePath)
        {
            string filename = Constants.IsAzureEnvironment ? "prod.settings.json" : "dev.settings.json";

            IConfigurationBuilder configBuilder = new ConfigurationBuilder()
                .SetBasePath(basePath)
                .AddJsonFile("base.settings.json")
                .AddJsonFile(filename);

            return configBuilder.Build();
        }

I get basePath from the executionContext parameter of the azure function

        [FunctionName("Function1")]
        public static async Task<IActionResult> RunAsync([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log, Microsoft.Azure.WebJobs.ExecutionContext context)
        {
            // context.FunctionAppDirectory
            return new OkResult();
        }
Richard Fuller
  • 464
  • 3
  • 12
  • Thanks for replying. What do I do with app base path? – user2439903 Jan 14 '19 at 19:28
  • I pass it into ConfigurationBuilder().SetBasePath(basePath) so that it looks for the .json files in the folder where it's running from. It looks like you're doing that already but with a different property (I don't know if the value is different). – Richard Fuller Jan 14 '19 at 19:36
-1

I used the Json.NET to read the json file.

This is my json content:

{
   "object": {
      "name": "cwr"
   },
   "others": "123"
}

And this is function.cs code:

 public static void Run([TimerTrigger("0 */1 * * * *")] TimerInfo timer,
        ILogger logger)
    {
        
        JObject jsonData = JObject.Parse(File.ReadAllText(path));

        logger.LogInformation(jsonData["object"]["name"].ToString());
        logger.LogInformation(jsonData["others"].ToString());

    }

And here is output:

enter image description here

Hope this could help you, if you still have other questions, please let me know.

Community
  • 1
  • 1
George Chen
  • 13,703
  • 2
  • 11
  • 26
  • This answers neither of the 2 questions asked by the OP. 1.How can I inject the appSettings configuration inside the TimerTick method? 2, I have two appSettings files - for development & production. How can I make sure the correct file gets loaded during production? – BryceBy Aug 30 '23 at 17:32