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.
One Reply to “F#: When HttpClient PostAsJsonAsync no longer works”