Home > Mobile >  What is the correct way to add a named HttpClient in an F# Web API application?
What is the correct way to add a named HttpClient in an F# Web API application?

Time:01-06

I'm trying to get a named HttpClient to work in an F# Web API project. When I make the call to CreateClient on the injected IHttpClientFactory instance and supply the name, I'm expecting the HttpClient instance that I get back to include the settings I used when I add it to the services collection. However, the client I get back is a default.

Here is how I'm registering the named client.

// From: Program.fs
module Program =
    let exitCode = 0

    [<EntryPoint>]
    let main args =

        let builder = WebApplication.CreateBuilder(args)
        builder.Services.AddControllers()
        builder.Services.AddHttpClient("MyClient", (fun client ->
            let creds = Convert.ToBase64String(Encoding.ASCII.GetBytes($"user01:password123"))
            client.BaseAddress <- Uri("https://my-service-url")
            client.DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue("application/json"))
            client.DefaultRequestHeaders.Authorization <- AuthenticationHeaderValue("Basic", creds)
            )) |> ignore
        ...

Here is where I inject the factory into the controller and try to get an instance of the pre-configured named client.

// From: WeatherForecastController.fs
[<ApiController>]
[<Route("[controller]")>]
type WeatherForecastController (logger : ILogger<WeatherForecastController>, httpClientFactory:IHttpClientFactory) =
    inherit ControllerBase()

    let httpClient = httpClientFactory.CreateClient("MyClient")
    ...

When I inspect the httpClient instance, I find that BaseAddress is null. I'm expecting it to be https://my-service-url since that was what I set in the call to AddHttpClient.

I've tried to follow the docs but I may have missed something critical in the translation from C# to F#. If I set up this same exact sample in a C# app it works as expected.

Is there a mistake in the way I'm setting up the named client?

CodePudding user response:

You are trying to set the BaseAddress property of the HttpClient instance by using the <- operator.

In F# the <- operator is used for assigning values to variables, not for setting properties.

Use the BaseAddress property setter like this::

client.BaseAddress <- new Uri("https://my-service-url")

Alternative:

client <- client with { BaseAddress = new Uri("https://my-service-url") }

CodePudding user response:

I found that the F# version works if I add a type parameter in the call to AddHttpClient. So I changed the line

builder.Services.AddHttpClient("MyClient", (fun client ->

to

builder.Services.AddHttpClient<HttpClient>("MyClient", (fun client ->

and then it started working and giving back a configured HttpClient instance as expected.

  • Related