.NET’s IOptions have made using application configuration in any type of project more consistent and easier to implement than it ever was before. I found myself recently trying to use it in an Azure Functions project, and ran into some trouble along the way. I had to combine a few different solutions to get everything working properly, so I decided to group it all together for anyone else trying to do something similar.
Startup Configuration
There is an article in the official docs on how to set up IOptions to work with Azure Functions, but you wouldn’t know it from the page’s title (it’s called Using dependency injection in Azure Functions). It’s lacking a few bits of information that I’ll clarify below.
The first step is to create the class you’ll use to load the configuration:
public class SomeOptions
{
public string SomeString { get; set; }
public int SomeInt { get; set; }
}
To load the data, in your Startup class, you configure it using IConfiguration:
builder.Services.AddOptions<SomeOptions>()
.Configure<IConfiguration>((settings, configuration) =>
{
configuration.GetSection("SomeOptions").Bind(settings);
});
At which point, you’ll be able to inject an instance of IOptions<SomeOptions> anywhere in your function’s code.
You’d represent these values in the local.settings.json as follows:
{
"IsEncrypted": false,
"Values": {
"SomeOptions:SomeString": "Some valid string",
"SomeOptions:SomeInt": 12345
}
}
The object can’t be stored as a JSON object in the local.settings.json because of the way the functions runtime loads configurations from the Values object. You’d create the properties exactly the same way in the Configuration section of the functions runtime in the Azure Portal.
Using Arrays in Configuration
The above approach works well when all you’ve got is an object with a bunch of properties and values. But what happens when you want to use some type of enumeration in the options? That’s when you need to get a bit creative.
The C# class that you’ll use with IOptions is what as you’d expect, defined as a list of strings:
public class SomeOptions
{
public List<string> SomeListOfOptions { get; set; }
}
The difficulty comes when trying to represent this data in the local.settings.json and in the function’s configuration in Azure. There is a way to do it, even if it is a bit ugly:
{
"IsEncrypted": false,
"Values": {
"Environment": "Development",
"SomeOptions:SomeListOfOptions:[0]": "string-1",
"SomeOptions:SomeListOfOptions:[1]": "string-2"
}
}
Once again, configure it exactly the same in Azure, either through the portal or your build & release pipelines.
Wrap Up
Working with IOptions in Azure Functions is relatively easy, if a bit unsightly. Configuring our functions in this way keeps our configuration code separate from our business logic, and sets our code on the path to being easily maintainable and extendable.
Thanks for this insightful article. However, I wonder whether it might be better practice to use appsettings.json like other net projects do and leave localsettings.json for the functions runtime? What are your thoughts on that?
LikeLike
Hmmmm. I’ve never done that. Have you experimented with this? I’d be curious to know if you got it working.
LikeLike
I have tried your code. It was working but for arrays. So ended up reading a bit more and found Martin’s suggestion worked.
https://docs.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection
LikeLike