Introduction to Web Programming in F# with Giraffe — Part 1

Introduction

According to the website (https://github.com/giraffe-fsharp/Giraffe), Giraffe is "an F# micro web framework for building rich web applications" and was written by Dustin Moris Gorski (https://twitter.com/dustinmoris).
Giraffe is a thin functional wrapper around AspNetCore. If you want something more opinionated and want to use F# everywhere, have a look at Saturn (https://saturnframework.org/) and the Safe Stack (https://safe-stack.github.io/).

Getting Started

I suggest that you use VSCode with the ionide F# extension. They work on Windows, MacOS and Linux.
Create a new folder called GiraffeExample in VSCode.
Using the Terminal in VSCode type in the following command to create the project:

dotnet new console -lang F#

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

dotnet add package Giraffe
dotnet add package Giraffe.ViewEngine

open Program.fs and replace the code with the code from this gist:

https://gist.github.com/ianrussellsoftwarepark/cc70ef9a1849f5c1e49a9339b6b56ea4

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 URLs and you should see some JSON:


 
https://localhost:5001/api
https://localhost:5001/api/Ian [Replace my name with yours]

Reviewing the Code

Start with the main function. If you've done any AspNetCore, this will look very familiar because Giraffe is a thin functional wrapper over AspNetCore. Everything you can use in C# is useable in F# for configuration.

The interesting parts will be the routing, handlers and views.

Views

The GiraffeViewEngine is a DSL that generates HTML.

let indexView =
    html [] [
        head [] [
            title [] [ str "Giraffe Sample" ]
        ]
        body [] [
            h1 [] [ str "I |> F#" ]
            p [ _class "some-css-class"; _id "someId" ] [
                str "Hello World"
            ]
        ]
    ]

Each element like html has the following structure:

html [] []

Each element has two supporting lists: The first is for attributes and the second for data. You may wonder why we need a DSL to generate HTML but it makes sense as it helps prevent badly formed structures. All of the features you need like master pages, partial views and model binding are included. We will have a deeper look at views in the third post in this series.

Routes

Rather than use MVC-style controller routing, Giraffe uses individual route handlers.


 
let webApp =
    choose [
        GET >=> choose [
            route "/" >=> htmlView indexView
            subRoute "/api"
                (choose [
                        route "" >=> json { Response = "Hello world!!" }
                        routef "/%s" sayHelloNameHandler
                ])
        ]
        setStatusCode 404 >=> text "Not Found"
    ]

The Fish operator (>=>) [compose combinator] allows the routing to support the pipelining of handlers on a route by composing two HttpHandlers together. The choose combinator tries to match the incoming request with a route.

We can easily move sets of routes to their own handler and include it in the main routing structure like this:

let apiRoutes : HttpHandler =
    subRoute "/api"
        (choose [
            GET >=> choose [
                route "" >=> json { Response = "Hello world!!" }
                routef "/%s" sayHelloNameHandler
            ]
        ])

let webApp =
    choose [
        GET >=> choose [
            route "/" >=> htmlView indexView
        ]
        apiRoutes
        setStatusCode 404 >=> text "Not Found"
    ]

We will look at using different types of middleware over the course of the next three posts.

Handlers

The handlers are usually the functions that do the work. Notice that the querystring item is automatically bound to the handler function if we have a matching input parameter of the same type.

let sayHelloNameHandler (name:string) =
    fun (next : HttpFunc) (ctx : HttpContext) ->
        task {
            let msg = sprintf "Hello, %s" name
            return! json { Response = msg } next ctx
        }

This function could be written like the following but it is convention to use the style above.

let sayHelloNameHandler (name:string) (next : HttpFunc) (ctx : HttpContext) =
    task {
        let msg = sprintf "Hello, %s" name
        return! json { Response = msg } next ctx
    }

The task {} is a Computation Expression of type System.Threading.Tasks.Task<'T data-preserve-html-node="true">. F# has another asynchronous feature called async but we won't use that as Giraffe has chosen to work directly with Task instead.

You will see a lot more of task {} in the next post in this series as we expand the API side of this site.

Summary

I hope that you found this introduction to web programming in F# with Giraffe useful and interesting. We have only scratched the surface of what is possible with Giraffe.

In the next post we will expand the API side of the application.

If you have any comments on this series of posts or suggestions for new ones, send me a tweet (@ijrussell) and let me know.

Blog 3/11/21

Introduction to Web Programming in F# with Giraffe – Part 2

In this series we are investigating web programming with Giraffe and the Giraffe View Engine plus a few other useful F# libraries.

Blog 3/12/21

Introduction to Web Programming in F# with Giraffe – Part 3

In this series we are investigating web programming with Giraffe and the Giraffe View Engine plus a few other useful F# libraries.

Blog 5/18/22

Introduction to Functional Programming in F#

Dive into functional programming with F# in our introductory series. Learn how to solve real business problems using F#'s functional programming features. This first part covers setting up your environment, basic F# syntax, and implementing a simple use case. Perfect for developers looking to enhance their skills in functional programming.

Blog 11/30/22

Introduction to Partial Function Application in F#

Partial Function Application is one of the core functional programming concepts that everyone should understand as it is widely used in most F# codebases.In this post I will introduce you to the grace and power of partial application. We will start with tupled arguments that most devs will recognise and then move onto curried arguments that allow us to use partial application.

Blog 8/8/23

Introduction to Functional Programming in F# – Part 12

Explore reflection and meta-programming in F#. Learn how to dynamically manipulate code and enhance flexibility with advanced techniques.

Blog 7/12/23

Introduction to Functional Programming in F# – Part 11

Learn type inference and generic functions in F#. Boost efficiency and flexibility in your code with these essential programming concepts.

Blog 10/1/22

Introduction to Functional Programming in F# – Part 4

Unlock F# collections and pipelines. Manage data efficiently and streamline your functional programming workflow with these powerful tools.

Blog 9/15/22

Introduction to Functional Programming in F# – Part 3

Dive into F# data structures and pattern matching. Simplify code and enhance functionality with these powerful features.

Blog 5/17/23

Introduction to Functional Programming in F# – Part 10

Discover Agents and Mailboxes in F#. Build responsive applications using these powerful concurrency tools in functional programming.

Blog 10/11/22

Introduction to Functional Programming in F# – Part 5

Master F# asynchronous workflows and parallelism. Enhance application performance with advanced functional programming techniques.

Blog 9/13/22

Introduction to Functional Programming in F# – Part 2

Explore functions, types, and modules in F#. Enhance your skills with practical examples and insights in this detailed guide.

Blog 12/22/22

Introduction to Functional Programming in F# – Part 7

Explore LINQ and query expressions in F#. Simplify data manipulation and enhance your functional programming skills with this guide.

Blog 3/22/23

Introduction to Functional Programming in F# – Part 9

Explore Active Patterns and Computation Expressions in F#. Enhance code clarity and functionality with these advanced techniques.

Blog 12/22/22

Introduction to Functional Programming in F# – Part 6

Learn error handling in F# with option types. Improve code reliability using F#'s powerful error-handling techniques.

Blog 3/22/23

Introduction to Functional Programming in F# – Part 8

Discover Units of Measure and Type Providers in F#. Enhance data management and type safety in your applications with these powerful tools.

Blog 8/10/22

So, I wrote a book

Join me as I share the story of writing a book on F#. Discover the challenges, insights, and triumphs along the way.

Blog 7/21/20

Understanding F# applicatives and custom operators

In this post, Jonathan Channon, a newcomer to F#, discusses how he learnt about a slightly more advanced functional concept — Applicatives.

Blog 12/3/21

Using Discriminated Union Labelled Fields

A few weeks ago, I re-discovered labelled fields in discriminated unions. Despite the fact that they look like tuples, they are not.

Blog 5/1/21

Ways of Creating Single Case Discriminated Unions in F#

There are quite a few ways of creating single case discriminated unions in F# and this makes them popular for wrapping primitives. In this post, I will go through a number of the approaches that I have seen.

Blog 8/7/20

Understanding F# Type Aliases

In this post, we discuss the difference between F# types and aliases that from a glance may appear to be the same thing.