Azure Functions fully supports F#, which raises the question of why we haven’t one for functional development. The reason is that there hasn’t been enough development done in the functional paradigm.
Giraffe meets Arcus
For developing Web APIs and Azure Functions HTTP triggers in F#, there’s a commonly used library called ‘Giraffe’ that helps overcome the tedious OOP-restrictions of the ASP.NET Core framework. The purpose of this post is not to explain Giraffe, as you can read their thorough documentation for more information on this framework.
All Giraffe needs is a reference in the Startup.fs
. Besides that, all of the Arcus registrations look almost the same in the official template:
Note that with Giraffe, we can only specify the JSON settings once, and then the input/output gets adapted directly.
The actual Azure Function HTTP trigger can be found in the Run.fs
file. I’ve already added some starter functions so you can get the idea of a simple Giraffe Azure Functions setup. In the next steps, we’ll look at how we can introduce the boilerplate code that you find in the official Arcus Azure Functions HTTP trigger project template.
Request restrictions
The Azure Functions HTTP trigger template contains some request restrictions to make sure that the HTTP request is valid. Normally, this is done in some middleware, but since we’re in Azure Functions (and not yet in out-of-process functions), we will assume that there’s no middleware available.
The Arcus project template uses a re-usable base class to provide you with some functionality to restrict the request. Fortunately, with Giraffe we can simply use functions for this.
I’ve created some functions in the Arcus style on a personal GitHub repo which can directly be referenced in F# paket projects. These functions will help with making sure that the incoming request has the correct metadata information before we do any binding or serialization. Here are some examples added to the Azure Function:
HTTP correlation
We use the HTTP correlation functionality from the Arcus Web API library to handle the correlation in the template. We can also add it in our functional example, but we need to make some alterations to easily integrate it into our Giraffe pipeline.
The Arcus correlation is now fully functional and can be added to our Giraffe pipeline:
JSON binding
To deserialize the request body, we provided some binding methods in the base class. With a concrete JSON exception type, we’ve handled any problems during deserialization. In Giraffe, the same sort of thing can be accomplished. We should make sure that we also verify any validation attributes on the type we’re trying to bind. All this functionality is also available in F#.
First things first, let’s start with our JSON model. Luckily, we can simply use F# records for this:
To deserialize, we can use Giraffe’s .BindJsonAsync
. Since we also need some additional error handling, let’s wrap these in a separate higher-order function to take in the successful flow:
To validate the model, we can use the Giraffe’s IModelValidation
interface. With a little tweak, we can let it validate our ASP.NET Core validation attributes:
The validateModel
Giraffe pipeline function (f:('T -> HttpHandler) -> model:'T -> HttpHandler
) will take care of this. In combination with our previously added JSON deserialization function, our Giraffe pipeline now looks like this:
Note that the validateModel
function takes in a result function where the successful validation result should be sent to (like our tryBindJson
function does). I’ve chosen here to take the same approach as with the Arcus template, and have sent back the order with Giraffe’s json
function.
Domain Modelling
As a bonus, try to introduce a domain model with some domain model requirements, and to parse that model. With my personal FPrmitive package, this can be done rather easily in the same functional manner. For more information on this package and examples on how this library can be used, see my other blog posts.
Conclusion
In this post, we’ve looked at some alternative ways to provide users with a starter project that already does much of the highly-needed boilerplate code. We’ve seen that with Giraffe and the built-in F# support for Azure Functions, we can accomplish a lot.
Hopefully, you will consider F# as an option in your next project, because it’s definitely worth a look. Combining C# and F# is even better.
Thanks for reading!
Subscribe to our RSS feed