Blog Post:

Routing in Nancy from F#

Nancy is my web framework of choice for .NET. It is free, lightweight, easy to use, and comes without all the bloat of the more common .NET frameworks.

Nancy makes routing in C# simple. If you need to handle a form post, you simply set up the POST endpoint, and access the form variables via the dynamic Form object. For example if you’ve got a form with firstName and lastName, and need to respond with a “Hello”, here’s now that would be done.

When using from F# however, there is no “dynamic” functionality, so it’s not so simple. The common advice is to create an operator that mimics the dynamic functionality of C# as follows.

Then you can use that operator like this.

Okay, well, that works, but it’s not pretty. All that casting to and from String pollutes the code, and the ? operator just looks out-of-place. It can get especially unwieldy in a long module with many endpoints, since all of that code must go into the constructor of your NancyModule, and ends up being one big long block of mess. Externalizing these handlers into separate functions is an option, but then you’re passing dynamic variables around into the heart of your app, which is very antithetical to F#.

Fortunately there’s a better way. First off, use JSON encoding on your HTML form rather than URL encoding. This will mean a few extra lines of Javascript on your form, but this is standard with frameworks like AngularJS anyway. Now you can create a helper function using the excellent JSON.NET library to parse the JSON into a record. There’s also a function here to convert the result back to JSON:

Now within your NancyModule constructor, you can add the following inline function that maps an endpoint to a handler function.

What does this do? It sets up your endpoint to parse the body into a record, call your handler function f with that record, and return the response. So now, assuming we have a record type Person = {firstName: string; lastName: string}, we can write the handler as:

What’s especially nice is this can now be externalized to a function, so if we define let sayHi user = "Hello " + user.firstName + " " + user.lastName then our form handler becomes simply

All in all, this pattern makes API creation so simple and declarative, I find it much better than even the C# dynamic pattern. Your handlers go from being line-per-variable messes, to a simple line-per-endpoint mapping. You can put your handlers and datatypes in different files and namespaces too, to organize things even better. The full code is here, along with an async option as well. You can see how much easier this makes the API endpoint mapping to read, and how well componentized your code becomes, especially as the list of endpoints continues to grow.

DataTypes.fs:

Handlers.fs:

NancyHelp.fs:

API.fs:

Leave a Reply

Your email address will not be published. Required fields are marked *

Get in Touch

If you have a product design that you would like to discuss, a technical problem in need of a solution, or if you just wish you could add more capabilities to your existing engineering team, please contact us.