3

I'm looking for someone to point out the obvious blunder here.

A .NET Core in C# application makes an HTTP call to another such application. Some processing is performed, and a response is sent thus:

 Response response = new Response(input)
        {
            stuff = processedStuff;
        };
        responseMessage = JsonConvert.SerializeObject(response);
        return new OkObjectResult(responseMessage);

This all looks good and responseMessage contains valid JSON (according to an online JSON checker I found).

At the other end, this is received thus:

Response returned = new Response();
var response = await client.SendAsync(request);
                if (response.IsSuccessStatusCode)
                {
                    var json = await response.Content.ReadAsStringAsync();
                    returned = JsonConvert.DeserializeObject<Response>(json);
                }

This fails with an Error converting value *the JSON string* to "Response" at line 1

Response is the same class file in both applications. What never obvious and apparently invisible mistake am I making here?

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
Eddy
  • 63
  • 5

4 Answers4

5

The invisible mistake you are making is double-serializing the result. The contract of OkObjectResult is that it will automatically serialize the result object to the negotiated content type (e.g. JSON or XML) and return an OK status. You are serializing the object first and then passing the serialized string to OkObjectResult so it ends up getting serialized twice.

responseMessage = JsonConvert.SerializeObject(response);   // serialize to JSON
return new OkObjectResult(responseMessage);                // implicit serialization here

Possible solutions:

  1. Allow the implicit serialization to do its thing (recommended):

    return new OkObjectResult(response);   // implicit serialization of response object
    
  2. Use a ContentResult instead (good if you need special serialization handling):

    responseMessage = JsonConvert.SerializeObject(response);   // serialize to JSON
    return new ContentResult()
    {
        Content = responseMessage,
        ContentType = "application/json",
        StatusCode = 200
    };
    
  3. Deserialize twice on the receiving end (use as a last resort, i.e. you don't control the server):

    var doubleSerializedJson = await response.Content.ReadAsStringAsync();
    var json = JsonConvert.DeserializeObject<string>(doubleSerializedJson);
    returned = JsonConvert.DeserializeObject<Response>(json);
    
Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
0

check if the returned string is not wrapped in OkObjectResult object.

Mina
  • 11
  • 2
0

As far as I know, you don't need the serialization and deserialization, the framework already takes care of everything. If you need to, you could always deserialize to either an anonymous type or cast it from object. https://www.newtonsoft.com/json/help/html/DeserializeAnonymousType.htm

I would also help if you could share the response class, since it's most likely part of the problem.

Arthur Bruel
  • 678
  • 3
  • 12
0

As someone old enough to remember when the Simpsons started, I can only answer in the traditional manner:

D'oh!

Using implicit serialization as described by the kind responder above resolved the issue.

Eddy
  • 63
  • 5