Azure Function inject setting.{environment}.json

Azure Functions 2.x, Function runtime V3.2

LAI TOCA
3 min readOct 13, 2021
Photo from: https://wardpeter.com/trigger-azure-function-using-power-automate-part-3/

Configuration

The common way that we apply our custom setting under azure function via local.settings.json (for development) as example below:

``` local.settings.json
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"BYOB_TokenMap": "D:\\Temp",
"Uri": "http://xxxxxx/api/getxxxxx"
}
}

For the application side we could retrieve the user defined (Uri) using below code snippet:

[FunctionName("SaveXXXXXXDataToBlobJob")]
public void SaveXXXXXXDataToBlobJob([TimerTrigger("0 3 21 * * *")]TimerInfo myTimer, ILogger log)
{
var uri = Environment.GetEnvironmentVariable("Uri",
EnvironmentVariableTarget.Process);
}

But someone might curious that how if we could introduce injection setting.{environment}.json files according different environments just similar .NET console we got used to.

appsettings.json
|---- appsettings.debug.json
|---- appsettings.qas.json
|---- appsettings.release.json

Here were cues for handle these staff.

  • Override method ConfigureAppConfiguration and setup your setting json files.
``` Startup.cs
public class Startup : FunctionsStartup
{
public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder)
{
if (builder == null) throw new ArgumentNullException(nameof(builder));
var context = builder.GetContext();
var env = Environment.GetEnvironmentVariable("NETCORE_ENVIRONMENT", EnvironmentVariableTarget.Process);
builder.ConfigurationBuilder
.SetBasePath(context.ApplicationRootPath)
.AddJsonFile($"{appsettings.json.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
}
}
  • Setup configure options to inject and bind class model into services via override method Configure.
``` Startup.cs
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services
.AddOptions<ConfigModel>()
.Configure<IOptions<ExecutionContextOptions>>((settings, exeContext) =>
builder.GetContext().Configuration.Bind(settings));
}}```appsetings.json
{
"Resource":
{"Uri": "http://xxxxxx/api/getxxxxx"}
}
```CofigModel.cs
public class ConfigModel
{
public Resource {get;set;}
}
public class Resource
{
public string Uri {get;set;}
}
  • After DI of configuration we could retrieve anywhere
```XxxService.cs
public class XxxService
{
private readonly ConfigModel _config;
public XxxService(
IOptions<ConfigModel> config)
{
_config = config.Value;
}

[FunctionName("SaveXXXXXXDataToBlobJob")]
public void SaveXXXXXXDataToBlobJob([TimerTrigger("0 3 21 * * *")]TimerInfo myTimer, ILogger log)
{
var uri = _config.Resource.Uri;
}}
  • By the way, we could also get our appsettting.json section and setup under method Configure.
``` Startup.cs
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
// optinal-1
var uri1 = builder.GetContext().Configuration.GetSection("Resource:Uri").Value;
// optinal-2
var uri2 = builder.Services.BuildServiceProvider().GetRequiredService<ConfigModel>().Resource.Uri;

// then we could create named http client with above uri
// ......
}}

Testing

Suppose we got below azure function with type of timer trigger:

[FunctionName("SaveXXXXXXDataToBlobJob")]
public void SaveXXXXXXDataToBlobJob([TimerTrigger("0 3 21 * * *")]TimerInfo myTimer, ILogger log)
{
log.LogInformation($"Timer trigger function executed at: {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}");
// your business logic
// ......
}

How to testing our azure function under local environment? You might not expect to wait for the timer fired or modify your schedule (CRON) expression to fire function in instance time (maybe less than 5 seconds).

The best approach would be using azure core tools’ admin mode. Then you could request a http post looks like-> http://localhost:7071/admin/functions/{your_function_name}.

As above postman show that with JSON body : {“input”: “”} even the trigger function with type of timer that we could easily fire under developer stage:)

The alternative way would be:

[FunctionName("SaveXXXXXXDataToBlobJob")]
public void SaveXXXXXXDataToBlobJob(
[TimerTrigger("0 3 21 * * *")]TimerInfo myTimer
#if DEBUG
, RunOnStartup = true
#endif

, ILogger log)
{
log.LogInformation($"Timer trigger function executed at: {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}");
// your business logic ......
}

The key point here we used directives to defined if we are under DEBUG flag existed then RunOnStartup should effect. Ugly but works!

Please make sure to install nuget package: Microsoft.NET.Sdk.Functions so that if we could hook Azure Functions Core Tools with your application under Visual Studio.

Reference

--

--

LAI TOCA

Coding for fun. (Either you are running for food or running for being food.)