When Nouns and Verbs Collide - Dependency Injection in F# and ASP.NET Core

This blog post is written by Timo Vilppu

This blog post is written by
Timo Vilppu

Background

This post is about taking a functional approach to dependency injection using an ASP.NET core application written in F# as an example.

Lets say that we are are building an ASP.NET Core web application that exposes an HTTP API, and we want to automatically test the whole application pipeline.

As we only want to test the application behavior we need to be able to identify and isolate any external dependencies. With that done, we will also be able to replace those with fake implementations when running tests. This way we can focus on testing the application behavior without worrying about any external components.

Next up I will be showing an example of how to use dependency injection and partial application to achieve this.

Example case

The application we are building is a service that takes in a URL that points to a text document and shows the contents of that document in uppercase text. The interface to our application is an URL that accepts HTTP GET request and this interface is also used in tests.

The example application source code can be found at https://github.com/vilppu/fun-playground

How-to

As previously said we need to first find the dependencies that we need to isolate and as we are using F# it is convenient to model dependencies as functions.

In this case we have only one dependency and it is the outgoing HTTP request. We model this dependency as a function named httpSend

let httpSend : HttpRequestMessage -> Task<HttpResponseMessage>

For the concrete implementation easiest way is to use built-in HttpClient class:

let httpClient = HttpClient()
let httpSend = httpClient.Send

We can pass this function to our application by adding it as parameter to function that is used to start up the web server:

let CreateHttpServer httpSend = ...

And then register the function as singleton dependency using dependency injection in SelfHost.fs:

WebHostBuilder().ConfigureServices(fun services -> services.AddSingleton(httpSend) |> ignore)

After that the registered function can be injected to an ASP.NET API controller in Api.fs:

type ApiController httpSend = inherit Controller() ...

In our example the ApiController forms a boundary between object-oriented and functional code and from that on we pass on the dependency function as normal parameter.

Then we can use partial application to handle this dependency in more functionally oriented way. In the Api module we apply the httpSend parameter to Application.GetUppercaseContent function:

let getUppercaseContent = Application.GetUppercaseContent httpSend

Later we can call this partially applied function without worrying about our dependency:

getUppercaseContent url

Deep dive to code

The actual code tells more than thousand lines of hand-waving, so if you are still interested I recommend you to check out the example from

git clone https://github.com/vilppu/fun-playground/

and look into the tests in Tests.fs