DEV Community

Kenichiro Nakamura
Kenichiro Nakamura

Posted on

Azure Functions and .NET 5: Dependency Injection

.NET 5 support for Azure Functions is announced as GA in this blog article!

We can find developer guide at Guide for running functions on .NET 5.0 in Azure and Develop and publish .NET 5 functions using Azure Functions

Today, I want to share how to use DI (Dependency Injection) in this "isolated process" when we use .NET 5.

Reference: Start-up and configuration

Create project

First thing first! We need to create function project by using new template.

1. Install the latest version of Azure Function Core Tools v3. See here for more detail.

2. Once you install the tool, make sure to check the version. It should be higher than 3.0.3381.

func --version
Enter fullscreen mode Exit fullscreen mode

3. Create new folder and initialize the function.

mkdir dotnet5func
cd dotnet5func
func init
Enter fullscreen mode Exit fullscreen mode

4. Now, we can see new option available. Select "dotnet (isolated process".

Alt Text

5. Then, create new function project. Select any trigger as you want. I selected HttpTrigger this time.

func new
Enter fullscreen mode Exit fullscreen mode

Alt Text

6. Enter function name to complete, then run the function and confirm it works as expected.

func start
Enter fullscreen mode Exit fullscreen mode

7. Stop the function and open the project by using Visual Studio Code or Visual Studio.

code .
Enter fullscreen mode Exit fullscreen mode

Configure Dependency Injection

The most important thing to know when use DI is, that we don't need Startup.cs!! We can directly change code in Program.cs to configure DI now.

1.\ Program.cs should looks like below when we scaffold the project.

using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Azure.Functions.Worker.Configuration;

namespace dotnet5func
{
    public class Program
    {
        public static void Main()
        {
            var host = new HostBuilder()
                .ConfigureFunctionsWorkerDefaults()
                .Build();

            host.Run();
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

2.\ To use DI, we simply modify HostBuilder. Let's add HttpClient factory. We can simply use ConfigureServices method and use AddHttpClient() which is exactly same as ASP.NET project.

using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;

namespace dotnet5func
{
    public class Program
    {
        public static void Main()
        {
            var host = new HostBuilder()
                .ConfigureFunctionsWorkerDefaults()
                .ConfigureServices(s => {
                    s.AddHttpClient();
                })
                .Build();

            host.Run();
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

3. Open function code and accept IHttpClientFactory via DI. We need to change several places.

  • Remove static keywords so that we can instantiate class
  • Add private IHttpClientFactory and receive it via constructor
  • Change signature of Run method to make it asynchronous call

I use swapi.dev this time. swapi is a cool api if you love Star Wars. Check out swapi.dev for more detail.

using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;

namespace dotnet5func
{
    public class dotnet5func
    {
        private readonly IHttpClientFactory clientFactory;

        public dotnet5func(IHttpClientFactory clientFactory)
        {
            this.clientFactory = clientFactory;
        }

        [Function("dotnet5func")]
        public async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req,
            FunctionContext executionContext)
        {
            var logger = executionContext.GetLogger("dotnet5func");
            logger.LogInformation("C# HTTP trigger function processed a request.");

            var client = clientFactory.CreateClient();
            var swapires = await client.GetStringAsync("https://swapi.dev/api/people/1/");
            var response = req.CreateResponse(HttpStatusCode.OK);
            response.Headers.Add("Content-Type", "text/plain; charset=utf-8");

            response.WriteString(swapires);

            return response;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

4. Run the function again and call the endpoint.

func start
Enter fullscreen mode Exit fullscreen mode

Alt Text

Summary

Even though there are still slight differences between Azure Functions and Web API when we writing code, I can easily and effectively reusing my knowledge once I fill the gap!

I cannot wait .NET 6 release which is LTS next year!

Top comments (2)

Collapse
 
ffmathy profile image
Mathias Lykkegaard Lorenzen

How would I make this work with an IActionResult as the response type?

Collapse
 
kenakamu profile image
Kenichiro Nakamura

When and why do you want to use IActionResult?