Introduction to Web Programming in F# with Giraffe – Part 2
Introduction
In this series we are investigating web programming with Giraffe and the Giraffe View Engine plus a few other useful F# libraries.
In this post, we will creating a simple API. In later posts, we will delve a lot deeper into Giraffe but this will be a gentle but useful start.
If you haven't already done so, read the first post in this series.
Getting Started
Ideally, you should have .NET 5 SDK installed. If you haven't, it will still work for .NET 3.1 SDK.
I suggest that you use VSCode with the ionide F# extension. They work on Windows, MacOS and Linux.
Create a new folder called GiraffeApi and open it in VSCode.
Using the Terminal in VSCode type in the following command to create the project:
After a few seconds, the ionide extension will spring to life. When it does, add the following NuGet packages from the terminal:
open Program.fs and replace the code with the code from this gist:
https://gist.github.com/ianrussellsoftwarepark/8b02b1e07c65e956d921eac882d08f2b
Running the Sample Code
In the Terminal, type the following to run the project:
dotnet run
Go to your browser and type in the following Url:
https://localhost:5001
You should see some text.
Now try the following Uri and you should see some Json returned:
https://localhost:5001/api
You will need a tool to run HTTP calls (GET, POST, PUT, and DELETE). I use Postman but any tool including those available in the IDEs will work.
Our Task
We are going to create a simple API that we can view, create, update and delete Todo items.
Data
Rather than work against a real data store, we are going to create a simple store with a dictionary and use that in our handlers.
Create a new file above Program.fs called TodoStore.fs
and add the following code to it:
This is not production code. TodoStore is a simple class type that wraps a concurrent dictionary that we can test our API out with. It will not persist between runs. To plug it in, we need to make a change to configureServices
in Program.fs:
We add the TodoStore as a singleton as we only want one instance to exist. If you're thinking that this looks like dependency injection, you would be correct; It is!
You'll need to add an open Todos
to the top of the file as well.
Routes
We saw in the last post that Giraffe uses individual route handlers, so we need to think about how to add our new routes.
If we request GET /api/fred
from the following routing:
We will hit the route that calls the sayHelloNameHandler
handler. If we call a POST, no routes will match, so we will fall through to the last line and return a 404 - Not found.
The routes we need to add are:
Let's create our routes with the correct HTTP verbs:
Our todo routes live under the api subroute. We need to put the apiTodoRoutes route handler before the existing ones because the sayHelloNameHandler will be selected instead of our GET /api/todos route and return:
Next we have to implement the new handlers.
Handlers
Create a module above the routes called Handlers
and add the sayHelloNameHandler function to it.
Let's add the GET routes to our module:
We are using the context (ctx) to gain access to the TodoStore instance we set up earlier.
Let's add the remaining handler for create, update and delete:
The most interesting thing here is that we use a built-in function to gain strongly-typed access to the body passed into the handler.
Using the API
Run the app and use a tool like Postman to work with the API.
To get a list of all Todos, we call GET /api/todo
. This should return an empty json array.
We create a Todo by calling PUT /api/todo
with a json body like this:
You will receive a reponse of true. If you now call the list again, you will receive a json response like this:
I'll leave the other routes for you to investigate.
The code for this post is available here:
https://gist.github.com/ianrussellsoftwarepark/f1c0815efe309ee6dd4bebf397d75f8d
Summary
I hope that you found this post in the Introduction to Web Programming in F# with Giraffe series useful and interesting. We have only scratched the surface of what is possible with Giraffe for creating APIs.
In the next post we will start to investigate HTML views with the Giraffe View Engine.
If you have any comments on this series of posts or suggestions for new ones, send me a tweet (@ijrussell) and let me know.