Inversion of Control (IoC) in Azure Functions

Ali Bahraminezhad
ITNEXT
Published in
5 min readFeb 5, 2020

--

Serverless computing and using Azure Functions are not only about writing a single method; in the real-world, it also includes logic and architecture.

Azure Functions is one of the serverless computing services that Microsoft Azure offers. They are easy to scale, in addition, they support various triggers, bindings, and you don’t need to pay lots of money for consuming them.

To write proper software, I need to follow SOLID principals and many other best practices. Testability, Abstraction, and Dependency Inversion are essential. Serverless computing with Azure Functions is still about writing an application.

In this article, I explain how you can implement dependency injection to achieve IoC in Azure Functions.

The full example is available here on my Github.

Before you start

You don’t need to have an Azure account. You can test and run the project locally on your machine. Just install VSCode, Azure Functions Extensions for VSCode, and .NET SDK.

Create the Azure Function Project

First, create a new folder and open the VSCode in it. Inside VSCode, go to Azure function extensions, and follow the instructions below:

  • Click on “Create a new project” and select the current folder as the project folder.
  • Choose C# as the language for the project.
  • You need to pick a template for scaffolding. For this article, I go with Http Trigger.
  • Enter the name of the function and namespace of the project.
  • Define the access type; I go with Annonymous.
Create a new AzureFunctions Project

To check if your project is created correctly, you can run it by pressing F5 or choosing Start debugging from the Debug menu.

Run an Azure Function inside VSCode

To implement IoC, install Microsoft.Azure.Functions.Extensions package with NuGet. Inside VSCode terminal enter following command:

dotnet add package Microsoft.Azure.Functions.Extensions

And make sure the Microsoft.NET.Sdk.Functions package on the project is 1.0.28 or later. You can check the CSProj file of your project for this.

Implement IoC and register types and services

Dependency injection in Azure Functions is built on the .NET Core Dependency Injection features. However, there are differences between how you override dependencies and how configuration values are read with Azure Functions on the Consumption plan on the Consumption plan. Support for dependency injection begins with Azure Functions 2.x.

Create a new class file called Startup. Azure Functions will use this class for configuring IoC and Services. The contents of this class should be like the following example:

  • The Startup class should inherit from the FunctionsStartup class.
  • It should override the Configure method to be able to configure your IoC.
  • With [assembly: FunctionsStartup(type of strtup class)] the attribute you define this class is the startup class. Azure Functions won’t find the startup class if you don't specify this attribute.

As you can see in the code, I commented a couple of examples of how services and types can be registered inside it.

Azure Functions provide the same service lifetimes as ASP.NET Dependency Injection. For a Functions app, the different service lifetimes behave as follows:

  • Transient: Transient services are created upon each request of the service.
  • Scoped: The scoped service lifetime matches a function execution lifetime. Scoped services are created once per execution. Later requests for that service during the execution, reuse the existing service instance.
  • Singleton: The singleton service lifetime matches the host lifetime and is reused across function executions on that instance. Singleton lifetime services are recommended for connections and clients, for example SqlConnection or HttpClient instances.

The dependency injection container only holds explicitly registered types. The only services available as injectable types are what are setup in the Configure method. As a result, Functions-specific types like BindingContext and ExecutionContext aren't available during setup or as injectable types.

Now, re-run the project; inside the output window, you can see that Azure Functions could find the Startup class.

If it finds the startup, you should see this message.

Working with options and settings

Every application at least requires some options and settings. In the Azure Functions app, these settings saved in local.settings.json file.

{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",

"AppInfo:Title": "Hello World",
"AppInfo:LogInformation": false
}
}

For example, in my app, I defined two options: Title and LogInformation. To work with these values, all I need is to create a class called AppInfo and create those properties for it.

namespace AzureFunctions.Ioc.Configurations
{
public class AppInfo
{
public string Title { get; set; }
public bool LogInformation { get; set; }
}
}

You can change the class name to whatever you like, but the name of the class should be the same as the options in the JSON file.

Inside startup class, in the Configuration method, it’s required to register the configuration class. The following code register the `AppInfo` settings for the project:

builder.Services.AddOptions<AppInfo>()
.Configure<IConfiguration>((settings, configuration)
=> configuration.GetSection("AppInfo").Bind(settings));

I have a service called HelloWorld. It has only one method for saying hello. Register the service in the Configuration method.

builder.Services.AddTransient<IHelloWorld, HelloWorld>();

Replace the content of the Azure Function file with the following code:

Constructor injection is used to make your dependencies available in a function. You can see in the example above.

The final result of running and debugging

Conclusion

We learned how to create a new Azure Function, how to use IoC to inject services or settings to the Function. What’s next? You can read more about the best practices for Azure Functions on Microsoft Docs.

--

--

I’m a geek, a software engineer who likes to build amazing stuff 😉Here on Medium I write about different things but mostly focused on programming and .NET!