Type-safe ASP.NET Configuration in F#

Something that I always find confusing why is how .NET (specially ASP.NET) seems to be moving most of its API away from a type-safe design. One of the APIs that works this way is the application configuration. If you’re not using the Option pattern, this is how you access a configuration value:

ConnectionString = new configuration.GetValue<string>("ConnectionString");

Well, you can probably tell that this is not type-safe at all! In order to do this in a more elegant way in F#, we can leverage the FsConfig package as it has support for the Microsoft.Extensions.Configuration namespace. First, let’s add the package to our project:

$ dotnet add package FsConfig

Now, let’s define a Configuration record with our structure and a module with a helper function called init that will do the heavy lifting for us.

open System.IO
open FsConfig
open Microsoft.Extensions.Configuration

type Configuration =
    { SuperSecret: string }

module Configuration =
    let init =
        let configurationRoot =
            ConfigurationBuilder()
                .AddEnvironmentVariables()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("config.json")
                .Build()

        let appConfig = AppConfig(configurationRoot)
        appConfig.Get<Configuration>()

However, how useful would be our configuration if we couldn’t access it from within our ASP.NET application? In order to do just that, we can register our Configuration record as a Singleton (check out the service lifetime documentation) and retrieve it whenever we want it just like any other dependency. Adding it as a service is pretty straightforward:

let configureServices (services: IServiceCollection) =
    let config =
        match Configuration.init with
        | Ok config -> config
        | Error e -> failwithf "Error reading configuration: %A" e

    services.AddSingleton<Configuration>(config) |> ignore
    services.AddGiraffe() |> ignore

Consecutively, to retrieve it from, let’s say, an HttpHandler, you can do the following:

❗ Please, never print your secrets!

let handler : HttpHandler =
    fun (next: HttpFunc) (ctx: HttpContext) ->
        let config = ctx.GetService<Configuration>()
        let msg = sprintf "config: %s" config.SuperSecret
        text msg next ctx

Articles from blogs I follow around the net

The four tenets of SOA revisited

Twenty years after. In the January 2004 issue of MSDN Magazine you can find an article by Don Box titled A Guide to Developing and Running Connected Systems with Indigo. Buried within the (now dated) discussion of the technology…

via ploeh blog March 4, 2024

Building a demo of the Bleichenbacher RSA attack in Rust

Recently while reading Real-World Cryptography, I got nerd sniped1 by the mention of Bleichenbacher's attack on RSA. This is cool, how does it work? I had to understand, and to understand something, I usually have to build it. Well, friends, that is what…

via ntietz.com blog March 4, 2024

How to unbreak Dolphin on SteamOS after the QT6 update

A recent update to Dolphin made it switch to QT6. This makes it crash with this error or something like it: dolphin-emu: symbol lookup error: dolphin-emu: undefined symbol: _Zls6QDebugRK11QDockWidget, version Qt_6 This is fix…

via Xe Iaso's blog March 3, 2024

Generated by openring