Dependency Injection in Azure Functions
...and how to use HttpClient correctly!
A common scenario when using Azure Functions is to be able to do HTTP request. The HttpClient
is the preferred tool for that, so how do we use HttpClient
correctly?
By 'correctly' I refer to the fact that for years many .net developers (my self included) has been disposing the HttpClient
after each use. The reason for this is because HttpClient
implements IDisposable
and as a good developer, you have learned always to dispose the resources you are not using, well, what if you intend to use it again shortly after? There is a great Visual Studio Magazine article about that.
So, since we don't want to dispose the HttpClient
after each use, we are going to reuse, but how do we do that in a stateless environment as our Functions are running in?
Simple enough, we let the runtime handle that by using dependency injection. In fact there are built in library support for DI in the official runtime.
We have 2 options:
- Configure
HttpClient
for injection - Configure
HttpClientFactory
and get a reference when we need it
In this article I will go with the first, for simplicity, later I will publish an article about the HttpClientFactory
because that has some really nice features.
Let's get coding!
Installing the Required Packages
We need some Nugets to help us out:
Install-Package Microsoft.Extensions.Http -Version 3.1.14
Install-Package Microsoft.Extensions.DependencyInjection -Version 3.1.14
Install-Package Microsoft.Azure.Functions.Extensions -Version 1.1.0
Install-Package Microsoft.NET.Sdk.Functions -Version 3.0.11
Note if you want to deploy to Azure then stick with the version 3.x of the 2 first packages, as there is not full natively support for .net 5 yet.
Adding Startup.cs
We need to add a new class to our Function project, name it Startup.cs and define it like this:
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
[assembly: FunctionsStartup(typeof(MyFunction.Startup))]
namespace MyFunction
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddHttpClient();
}
}
}
Using the Dependency
Now can use our injected dependency in our functions, all we need to do is remove the static
things from our class and method definitions, then we need to add a constructor that takes the HttpClient
as a parameter, like this:
public class Function1
{
private readonly HttpClient httpClient;
public Function1(HttpClient httpClient)
{
this.httpClient = httpClient;
}
[FunctionName("Function1")]
public async Task Run([TimerTrigger("0 */5 * * * *")]TimerInfo myTimer, ILogger log)
{
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
await httpClient.GetAsync("blog.jepsen.ninja");
}
}
Wrap Up
That is really all there is needed to use DI and a HttpClient in an Azure Function. Stay tuned for my coming post about how to use the HttpClientFactory, and please let me know if you have any thoughts, comments, feedback or something else. Thanks for reading!