Per HTTP Request Dependency Injection in Azure Functions 2.0
The static nature of Azure Functions makes it difficult implement constructor dependency injection (DI). Fortunately, there are plenty of libraries out there on nuget that can help us with DI. Many of these libraries allow us to Inject a dependency as a parameter in the static function. This is great way to get started. However, it becomes hard to manage when we start passing in HTTP Request context information downstream to whoever needs it. For example, the HTTP Request context may contain User claims.
Each HTTP Request is injected via the static function as a parameter as Microsoft.AspNetCore.Http.HttpRequest instance. This means DI is not able to manage this particular dependency. One thought may be to Inject a "configuration" instance that is instantiated once via DI and use throughout the lifetime scope of the Azure Function instance. We can use that to store the HTTP Request context. However, the issue now is how to define the lifetime scope of the Azure Function.
To solve the lifetime scope issue, we may switch to use the Service Locator pattern and hence, be able to control the lifetime scope. We would require the use of a static Factory to create the DI setup each time. However, this approach has its own drawback as well. Implementation wise, it may require some custom knowledge of this Factory in order to maintain it. For example, we would write some custom tooling to capture HTTP Request context from the Azure Function parameter and set it against a "configuration" instance.
Here, we will bring up the IFunctionInvocationFilter interface. In ASP.NET MVC, we have the concept of Action Filters. The idea is that we are able to intercept an Action, which in our case, is the Azure Function instance, before it executes, and intercept an Action after it executes. This is perfect of our use case of being able to control the lifetime scope of the Azure Function instance. In addition, we have access to the ExecutionContext which carries the FunctionInstanceId. This property uniquely identities our Function instance and gives us more control of identifying and managing an Azure Function instance. One important as of the writing of this article is that the interface is still in preview and subject to changes per Microsoft.
With this in mind, I have created a nuget library package that encapsulates this concept at: https://www.nuget.org/packages/Eklee.Azure.Functions.Http. The purpose of this library is to help perform DI correctly per HTTP Request context. The source code is hosted on github at: https://github.com/seekdavidlee/Eklee-Azure-Functions-Http. Please do let me know what you think!
I hope this article is useful in describing an issue with Azure Function DI that is specific with how we wish to leverage HTTP Request context, as well as potential approach(es) to solving the issue.