Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Hosted-services / Azure

Using Dependency Injection with C# .NET Azure Functions (With Example)

5.00/5 (3 votes)
6 Jun 2019CPOL3 min read 19.3K  
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.

What Is Dependency Injection

Dependency injection (DI) is a software design pattern that allows developers to write loosely coupled code. This is accomplished by specifying which objects a class requires at run time, rather than implementing a concrete dependency. By using DI injection in your applications, you can ensure your code base 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. In this example, we will use this package to implement DI into a simple REST trigger C# function.

The first step is to create an HTTP function, this can be achieved by either 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.

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

First, you will need to create the function project:

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

Then change directory to the newly created project and run the following to create the function.

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

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

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

First, we are going to create the service that we will 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.

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

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

  1. Transient - An instance of your service is created every time they are requested from the service container. This is recommended for lightweight, stateless services.
  2. Scoped - Service is created once per client request (connection).
  3. Singleton - Singleton services are created the first time they’re requested, then every subsequent request uses the same instance.

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

C#
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, this means that we will also need to convert our function to be non-static.

C#
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.

func host start

If you see a message with “Greetings from Greeter!”, then that means dependency injection for our service has been configured correctly. Nice one!

Wrap Up

Using the dependency injection features provided with the Microsoft.Azure.Functions.Extensions package means that we can easily 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, please contact me using the comment section of this post or Twitter and I will be happy to help.

History

  • 6th June, 2019: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)