loading...
Cover image for Native Dependency Injection in Azure Functions with C#

Native Dependency Injection in Azure Functions with C#

rmaurodev profile image Ricardo Originally published at rmauro.dev ・3 min read

C# Azure Functions support dependency injection through the native container.

This allows us to use the Dependency Inject principle in native Azure Functions. In this post, we're going to create a simple function to demonstrate the use of it.

Also, check out my blog with other articles --> https://rmauro.dev

Introduction

Azure Functions allows you to run small pieces of code (called "functions") without worrying about application infrastructure. With Azure Functions, the cloud infrastructure provides all the up-to-date servers you need to keep your application running at scale.
https://docs.microsoft.com/en-us/azure/azure-functions/functions-overview

For this demonstration, we're going to use this RandomNumberService to Inject into our function.

using System;

namespace DependFunction.Services
{
    public interface IRandomNumber
    {
        int GetRandom();
    }

    public class RandomNumberService : IRandomNumber
    {
        static readonly Random _rand = new Random();

        //Get's a random number
        public int GetRandom() => _rand.Next(0, 10);
    }
}

Required Dependencies

Install/Update the following NuGet packages in your project.

  • Microsoft.Azure.Functions.Extensions
  • Microsoft.NET.Sdk.Functions
<Project Sdk="Microsoft.NET.Sdk">
  <!--ommited code-->
  <ItemGroup>
    <PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.9" />
  </ItemGroup>
    <!--ommited code-->
</Project>

Registering the Services in the Container

To register the services and we need to create a startup function, just like we have in a common asp.net core application.

Create a file called FunctionStartup.cs at the root of your application.

Solution Explorer

Paste the following content into the file.

using DependFunction.Services;
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;

[assembly: FunctionsStartup(typeof(DependFunction.Startup))]
namespace DependFunction
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddSingleton<IRandomNumber, NumberService>();
        }
    }
}

Explanation

Before the namespace we're registering our class as a dependency start the function [assembly: FunctionsStartup(typeof(DependFunction.Startup))]. This will tell the function runtime to trigger our class before serving HTTP requests.
Do not use to process other things, only to register services.

Inheriting FunctionStartup we gain access to IFunctionsHostBuilder object where we can register all dependencies, such as Scoped, Transient, or Singleton.

Service Lifetime

  • 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.
  • Singleton: The singleton service lifetime matches the host lifetime and is reused across function executions on that instance.

Using the service though Dependency Injection

Open your function file do the following changes

  • Remove static marker from the class and the function (we need to inject using constructors)
  • Create a constructor and inject the dependency interface

You should end with something like this:

using System;
using System.Threading.Tasks;
using DependFunction.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;

namespace DependFunction
{
    public class Function1
    {
        private readonly IRandomNumber _randomService;

        public Function1(IRandomNumber randomService)
        {
            _randomService = randomService ?? throw new ArgumentNullException(nameof(randomService));
        }

        [FunctionName("Function1")]
        public IActionResult Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            var result = new { random = _randomService.GetRandom() };

            return new OkObjectResult(result);
        }
    }
}

Testing

Run the application and access the URL for testing.

test-result

Source Code

https://github.com/ricardodemauro/az-functions-article

Hope you like it. Leave a comment.

Also, check out my blog with other articles --> https://rmauro.dev

Posted on by:

rmaurodev profile

Ricardo

@rmaurodev

Software Architect | Cloud Expert | MCT

Discussion

pic
Editor guide