Using this guide today#

This post covers the in-process model. Microsoft ends support for that model on 10 November 2026. In the isolated worker model, register services through the standard .NET dependency injection setup in Program.cs; the FunctionsStartup approach below does not apply. See the isolated worker guide and migration instructions.

The code for this example can be found here.

What is dependency injection#

Dependency injection (DI) is a software design pattern that allows developers to write loosely coupled code. We can accomplish this by specifying which objects a class requires at run time rather than implementing a concrete dependency. Using DI injection in your applications ensures your codebase is maintainable, testable, and easy to update.

Implementing dependency injection in Azure Functions#

Microsoft has recently released the Microsoft.Azure.Functions.Extensions NuGet package (at the time of writing version 1.0.0). This package adds native support for dependency injection by building upon the existing ASP.NET Core Dependency Injection features. We will use this package to implement DI into a simple REST trigger C# function in this example.

The first step is to create an HTTP function; this can be achieved through Visual Studio or using the Azure Function CLI.

To use the Azure Function CLI, you will need the Azure Functions Core Tools, which you can install through npm:

text
npm i -g azure-functions-core-tools --unsafe-perm true

First, you will need to create the function project:

text
func init <PROJECT NAME> --worker-runtime dotnet

Then change the directory to the newly created project and run the following to make the function:

text
func new --name <FUNCTION NAME> --template "HttpTrigger"

After creating the project, you must add a reference to Microsoft.Azure.Functions.Extensions package and update to the latest version of the function SDK. You can do this by using the dotnet CLI:

text
dotnet add package Microsoft.Azure.Functions.Extensions
dotnet add package Microsoft.NET.Sdk.Functions

First, we will create the service to inject into our function. In this example, we will be using a simple class that returns a greeting message. Create the following files (IGreeter.cs and Greeter.cs) in your function project:

csharp
namespace DependencyInjectionTutorial
{
    public interface IGreeter
    {
        string Greet();
    }
}
csharp
namespace DependencyInjectionTutorial
{
    public class Greeter : IGreeter
    {
        public string Greet()
        {
            return "Greetings from Greeter!";
        }

    }
}

Next, we will need to set up the Startup class, which we will use to register our service in the application. There are three main types of service lifetimes you can choose from when registering a service.

Transient - An instance of your service is created every time it gets requested from the service container. Microsoft recommends this for lightweight, stateless services.

Scoped - Service is created once per client request (connection).

Singleton - Singleton services get created the first time they're requested, then every subsequent request uses the same instance.

For this example, I will use the transient service lifetime, as I want to create an instance of the Greeter every time my function gets invoked.

csharp
using DependencyInjectionTutorial;
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;

[assembly: FunctionsStartup(typeof(Startup))]

namespace DependencyInjectionTutorial
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddTransient<IGreeter, Greeter>();
        }
    }
}

Finally, we need to adapt our HTTP function to use our Greeter service by using constructor injection; we will also need to convert our function to be non-static.

csharp
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;

namespace DependencyInjectionTutorial
{
    public class DependencyInjectionTutorialFunction
    {
        private readonly IGreeter _greeter;

        public DependencyInjectionTutorialFunction(IGreeter greeter)
        {
            _greeter = greeter;
        }

        [FunctionName("DependencyInjectionTutorialFunction")]
        public IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequest req, ILogger log)
        {
            var greeting = _greeter.Greet();
            log.LogInformation($"Got Greeting: {greeting}");

            return new OkObjectResult(greeting);
        }
    }
}

To test our function, run the following command using the function CLI and navigate to the link provided in the terminal in a browser.

text
func host start

If you see a message with "Greetings from Greeter!" we have correctly configured dependency injection for our service. Nice one!

Wrap up#

The utility provided by Microsoft.Azure.Functions.Extensions package means that we can quickly produce code that is maintainable, testable and easy to refactor. If you require any more additional information about implementing DI into Azure functions, then check out the official Microsoft page here. If you have any questions, don't hesitate to get in touch with me using my Twitter handle @tomlingdev.