Trustbit

View Original

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:

See this content in the original post

After a few seconds, the ionide extension will spring to life. When it does, add the following NuGet packages from the terminal:

See this content in the original post

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:

See this content in the original post

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:

See this content in the original post

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:

See this content in the original post

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:

See this content in the original post

Let's create our routes with the correct HTTP verbs:

See this content in the original post

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:

See this content in the original post

Next we have to implement the new handlers.

Handlers

Create a module above the routes called Handlers and add the sayHelloNameHandler function to it.

See this content in the original post

Let's add the GET routes to our module:

See this content in the original post

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:

See this content in the original post

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:

See this content in the original post

You will receive a reponse of true. If you now call the list again, you will receive a json response like this:

See this content in the original post

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.