Chasing DevOps

A blog about software development, DevOps, and delivering value.

Dependency Injection in Azure Functions

The simplicity of Azure Functions makes it tempting to avoid following good design practices like dependency injection. The default project template doesn’t even support it. This may be fine for learning and quick experiments but would be a mistake for production code. Simplicity is not an excuse for bad engineering.

Luckily, setting up dependency injection in Azure Functions C# projects is easy. We can configure a .NET Azure Functions project to use the Microsoft.Extensions.DependencyInjection library that is widely used in ASP.NET Core. This post will show you how.

Install Prerequisites

First, we need to install some NuGet dependencies.

dotnet add package Microsoft.Extensions.DependencyInjection
dotnet add package Microsoft.Azure.Functions.Extensions
view raw nuget.sh hosted with ❤ by GitHub

Create a Startup Class

Then we need to define a Startup class. This is very similar to the Startup class used in some ASP.NET Core projects except it extends the FunctionsStartup class. We register our services with the dependency injection system inside the Startup.Configure method.

using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
[assembly: FunctionsStartup(typeof(DIExample.Startup))]
namespace DIExample
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddTransient<IMyService, MyService>();
}
}
}
view raw Startup.cs hosted with ❤ by GitHub

We also need to add the FunctionsStartup attribute (highlighted above) so the functions runtime knows to run this code on application start. Without that attribute, none of this will work.

Update Functions to use Dependency Injection

The framework we’re using injects dependencies into a class’s constructor. By default, functions are static methods in static classes and don’t have a constructor. We’ll need to remove the static keyword from the class and function. Don’t worry though, the runtime doesn’t require functions to be static.

Once the function and class are no longer marked as static we can define a constructor that accepts our dependencies and use them in our function.

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
namespace DIExample
{
public class HttpTrigger
{
private readonly IMyService _myService;
public HttpTrigger(IMyService myService)
{
_myService = myService;
}
[FunctionName(MyHttpTrigger)]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, get, Route = null)] HttpRequest req,
ILogger log)
{
// Call the service that the dependency injection system gave us
await _myService.DoSomethingAsync();
return new NoContentResult();
}
}
}
view raw HttpTrigger.cs hosted with ❤ by GitHub

That’s all! Your project is now ready to go.

Leave a Reply

Your email address will not be published.

Jesse Barocio

Software developer, DevOps engineer, and productivity tool nut. Continuously improving. Have a question or problem you need solved? Email me!