View pre-deserialized response from GraphQL query

View pre-deserialized response from GraphQL query


1

I have a simple GraphQL query that I’m making out to a server, and trying to use GraphQL.Client.Serializer.Newtonsoft to deserialize it. I’m getting a response, but the response does not make the NewtonsoftJsonSerializer happy. It complains:

This converter can only parse when the root element is a JSON Object.

Okay, fair enough. The response must not be what was expected. But how can I view the response to see what may be wrong? The GraphQLHttpClient.SendQueryAsync<>() method requires a type to try to deserialize to…which is the part that is failing. I don’t see a way to just get the text response so I can see what is wrong with it.

I’ve included sample code at the bottom, but the only real line of interest (I believe) is the last one:

var graphQLResponse = await graphQLClient.SendQueryAsync<object>(theRequest);

Is there some way to just get the text of the response?

var graphQLClient = new GraphQLHttpClient("https://<TheDomain>.com/graphql/api/v1", new NewtonsoftJsonSerializer());

graphQLClient.HttpClient.DefaultRequestHeaders.Add("Authorization", "Bearer <MyKey>");
graphQLClient.HttpClient.DefaultRequestHeaders.Add("Accept", "application/json");

var theRequest = new GraphQLRequest
{
    Query = "{ __schema { queryType { fields { name } } } }"
};

var graphQLResponse = await graphQLClient.SendQueryAsync<object>(theRequest);

Using Fiddler Everywhere, I was able to pull in the request and response, both of which seem superficially valid (I updated the query in the question to match the current query I’m passing in…a general schema query)

Request:

{
  "query": "{ __schema { queryType { fields { name } } } }"
}

Response:
(I’ve redacted the names of the endpoints and removed much of the repetition from the middle of the response. But the rest is unchanged, and looks superficially okay to me…in particular, it looks like valid JSON, so I’m unclear why the converter is complaining.)

{
  "errors": [],
  "data": {
    "__schema": {
      "queryType": {
        "fields": [
          {
            "name": "getData1"
          },
          {
            "name": "getData2"
          },
          ...
          <a bunch more here>
          ...
          {
            "name": "getData100"
          }
        ]
      }
    }
  },
  "extensions": null,
  "dataPresent": true
}

6

  • You can use a tool like Postman to make the same request. Alternatively, if you want to do it through code, you can use HttpClient, and ReadAsStringAsync to get the raw response. I am not sure how GraphQLHttpClient is working under the hood, but it does appear to be open source – github.com/graphql-dotnet/graphql-client.

    – ryanwebjackson

    Jan 27, 2022 at 19:35

  • @ryanwebjackson Interestingly, it works fine for me in Postman, so it's unlikely to be the server that's the issue. Presumably I'm doing something slightly wrong in the query code…but the fact that the server is apparently responding with something seems to indicate that it's getting a message of some kind. But without being able to read the response, I can't get an idea of what it's trying to tell me.

    – Beska

    Jan 27, 2022 at 20:35

  • I'm guessing there is something different in the headers. Compare every aspect of the request. You should be able to do the same request in postman as in code and vice versa. Make sure that postman is not using a proxy that you don't have configured via code, for example.

    – ryanwebjackson

    Jan 31, 2022 at 1:17

  • If necessary, sniff the outgoing traffic to know the details for sure. In fact, you can use an http traffic sniffer for the incoming response too. I'm guessing the response body is empty (not valid json).

    – ryanwebjackson

    Jan 31, 2022 at 1:19


  • 1

    @ryanwebjackson No proxy (or any other) difference that I've been able to spot yet, but I'll see if I can track down a traffic sniffer tomorrow to try to validate. If that allows me to read both my outgoing request, and the incoming response, I would think that between the two, the issue should be solvable.

    – Beska

    Jan 31, 2022 at 1:41

2 Answers
2


2


+100

After a few hit and trials and discussion with the O.P, it was found that while initializing GraphQLHttpClient with GraphQL.Client.Serializer.Newtonsoft, the serializer is not correctly doing the deserialization of the response despite the response being a valid JSON string.

After switching to GraphQL.Client.Serializer.SystemTextJson, the response is being correctly parsed as expected which suggests that there could be a bug in the GraphQL.Client.Serializer.Newtonsoft serializer

9

  • This doesn't work, as the first line throws an error in my case because the converter cannot parse the response. Unfortunately, without seeing the response, I can't see why the converter can't parse the response.

    – Beska

    Jan 30, 2022 at 23:23

  • @Beska Can you try to deserialize to a JObject during your SendQueryAsync: var graphQLResponse = await graphQLClient.SendQueryAsync<JObject>(theRequest); and see if NewtonsoftJsonSerializer does not throw an error?

    – Rahul Sharma

    Jan 31, 2022 at 12:20

  • This does not help. It seems to be failing before that stage…it doesn't care what type is in there (I put object in, since that should always be fine.) That said, I did try JObject, just to double check my sanity (since I'm missing something), and it gives the same error.

    – Beska

    Jan 31, 2022 at 18:22

  • @Beska Okay, now since you have the actual response back, you can deserialize the JSON to strongly typed Model classes: dotnetfiddle.net/WdmiA1 . Your call would be: await graphQLClient.SendQueryAsync<Root>(theRequest); . Now why is it not able to deserialize to an object using Newtonsoft I am not sure of. Have you tried to use GraphQL.Client.Serializer.SystemTextJson while initializing your graphQLClient and then tried to deserialize it to an object ?

    – Rahul Sharma

    Jan 31, 2022 at 19:12


  • 1

    I had NOT tried that. I just did…and it worked like a charm. Which leads me to believe that it's a bug in the NewtonSoft deserializer. Wow. Okay! Thank you! Please update your answer to include this information, and the bounty is yours. I appreciate your patience in working through this.

    – Beska

    Jan 31, 2022 at 20:58


0

I debugged the GraphQL.Client.Serializer.Newtonsoft.NewtonsoftJsonSerializer and discovered it throws when the extensions property (or generally any property of type GraphQL.Map) of a GraphQL response is null. I think this is an implementation bug.



Leave a Reply

Your email address will not be published. Required fields are marked *