Search code examples
c#json.netflurl

Sending json to an API as a string causes an error, but sending the dotnet object does not


Language: C# .net framework 4.8 Visual Studio 2019.

I was trying to send a json to an API, and if I send it as a string:

string jsonString = JsonConvert.SerializeObject(dataToSend, Formatting.Indented);


var result = await urlApi.
          WithTimeout(TimeSpan.FromSeconds(timeout)).
          PostJsonAsync(jsonString).
          ReceiveString();

NOTE: dataToSend is a dotnet object. I am using newtonsoft's json framework: https://www.newtonsoft.com/json, to serialize the object to a json. I am using flurl: https://flurl.dev/, to send the json.

The remote host answer with an error:

{
    "Status": "-1",
    "Description": "System.NullReferenceException: Object reference not set to an instance of an object.",
    "Result": null
}

However, when I send the object directly:

var result = await urlApi.
         WithTimeout(TimeSpan.FromSeconds(timeout)).
         PostJsonAsync(dataToSend).
         ReceiveString();

NOTE: dataToSend is a dotnet object.

I don't get any error.

I want to know why sending the json as a string causes an error.

¿Do you know why?

¿How can I find out?


Solution

  • Your problem is that you are double-serializing your JSON. The extension method you are using, GeneratedExtensions.PostJsonAsync(this string url, object body, ...), works as follows:

    Creates a FlurlRequest and sends an asynchronous POST request.
    url - This URL.
    body - An object representing the request body, which will be serialized to JSON.

    Since your jsonString is already serialized to JSON, it gets serialized a second time as a JSON string literal, causing the remote host to return the error you see.

    If for some reason you need to serialize the JSON manually, you can post it using Flurl.Http.Content.CapturedJsonContent:

    var result = await urlApi.
        WithTimeout(TimeSpan.FromSeconds(timeout)).
        PostAsync(new CapturedJsonContent(jsonString)).
        ReceiveString();