I have trouble reading configuration values from appSettings.json file in webjob. The webjob uses the following nuget packages:
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:
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"
}
}
}
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();
}