F#: When HttpClient PostAsJsonAsync no longer works

Intro

I recently upgraded all of the NuGet packages inside my Visual Studio solution. The result was breaking changes at runtime. Specifically, HttpClient::PostAsJsonAsync was resulting in an empty JSON value.

The following HttpClient::PostAsJsonAsync example of such code:

        use  client   = httpClient baseAddress
        let  encoded  = Uri.EscapeUriString(resource)
        let! response = client.PostAsJsonAsync(encoded, payload) |> Async.AwaitTask

Here are the implementation details for the httpClient function declaration:

let httpClient baseAddress =

    let handler = new HttpClientHandler()
    handler.AutomaticDecompression <- DecompressionMethods.GZip ||| DecompressionMethods.Deflate

    let client = new HttpClient(handler)
    client.Timeout     <- TimeSpan(0,0,30)
    client.BaseAddress <- Uri(baseAddress)
    client.DefaultRequestHeaders.Accept.Clear()
    client.DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue("application/json"))
    client

Returning back to the focal point, the following line of code wasn’t working anymore:

        let! response = client.PostAsJsonAsync(encoded, payload) |> Async.AwaitTask

After investigating, I found a clue. I learned that the attributes on my record declarations, which were intended to support serialization to JSON, were now causing issues after upgrading NuGet packages.

Specifically, I had the following attributes on my records:

    [<DataContract>]
    type Token = {

        [<field: DataMember(Name="AccessTo")>]
        AccessTo : CustomerId

        [<field: DataMember(Name="APIKey")>]
        APIKey   : APIKey
    }

The attributes, DataContract and field, were once required for serializing records in F#. However, after the NuGet package updates, they were now preventing records in F# from serializing.

I removed the field attributes from my record declaration and then applied the CLIMutable attribute.

The following code reflects my updates to the record declaration:

    [<CLIMutable>]
    type Token = {
        AccessTo : CustomerId
        APIKey   : APIKey
    }

I then had to write my calling code as follows:

let post baseAddress (resource:string) (payload:Object) =

    async {

        use  client    = httpClient baseAddress
        let  json      = JsonConvert.SerializeObject(payload)
        let  content   = new StringContent(json, Encoding.UTF8, "application/json")
        let! response  = client.PostAsync(resource, content) |> Async.AwaitTask

        return response

    } |> Async.StartAsTask

After applying the update, I observed serialization of records.

Advertisement

One Reply to “F#: When HttpClient PostAsJsonAsync no longer works”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: