Graphql-dotnet: Error: The JSON value could not be converted to System.Collections.Generic.IEnumerable`1[Newtonsoft.Json.Linq.JToken]. Path: $.variables | LineNumber: 0 | BytePositionInLine: 116.

Created on 28 Nov 2019  路  29Comments  路  Source: graphql-dotnet/graphql-dotnet

Summary

Error running when I try to send variables

Example:

graphql-error

Json Error Complete

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "|dbaac12a-46633a6f98c669bc.",
  "errors": {
    "$.variables": [
      "The JSON value could not be converted to System.Collections.Generic.IEnumerable`1[Newtonsoft.Json.Linq.JToken]. Path: $.variables | LineNumber: 0 | BytePositionInLine: 84."
    ]
  }
}

Relevant information

I noticed that there is no request in the controller, I think it is in the middleware!

Environment (if relevant)

  • Visual Studio 2019
  • Last Version GrapQL
  • .NET Core

#

Class Map

public class StateMapType : ObjectGraphType<State>
{
      public StateMapType()
      {
         Name = "state";
         Field(x => x.Id).Name("id");
         Field(x => x.Uf).Name("uf");
         Field<ListGraphType<CountryMapType>>().Name("country");
      }
}

GraphQLQuery

Field<ListGraphType<StateMapType>>(
           name: "states",
           arguments: new QueryArguments(
             new QueryArgument<BooleanGraphType>() { Name = "load", DefaultValue = false }
           ),
           resolve: context =>
           {
              bool load = context.GetArgument<bool>("load");
              IQueryable<State> query = DatabaseAccess.State.AsQueryable();
              if (load)
              {
                 query = query.Include(x => x.Country);
              }
              return query.AsNoTracking().ToList();
       }
 );

What could it be?

Note: I'm developing a package and it already worked the Query part, but this part of passing variables I can't make it work

https://www.nuget.org/packages/Canducci.GraphQLQuery/

Most helpful comment

@fulviocanducci - Like @joemcbride and @sungam3r mentioned earlier, Gql.Net is not having the problem. The problem is with the Controller's model binder. You're using a .Net Core 3.x project, which uses Micrsoft's System.Text.Json by default instead of Newtonsoft. It can't deserialize a JObject (and it also can't serialize Gql.Net's ExecutionResult).

A quick/simple way to confirm this is to change your controller from this:

public async Task<IActionResult> Post([FromBody]GraphQLQuery query)
{
    // original code...
}

to this:

public async Task<IActionResult> Post([FromBody] System.Text.Json.JsonElement rawQuery)
{
    string rawJson = rawQuery.ToString();
    var query = JsonConvert.DeserializeObject<GraphQLQuery>(rawJson);
    // original code...
}

All 29 comments

Can you show any server logs?

Last Version GrapQL

2.4.0 or latest 3.0.0-preview ?

@sungam3r

Test on both versions 2.4.0 e 3.0.0-preview !!!

Same Error ...

@sungam3r this:

System.Text.Json.JsonException: A possible object cycle was detected which is not supported. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 32.
   at System.Text.Json.ThrowHelper.ThrowInvalidOperationException_SerializerCycleDetected(Int32 maxDepth)
   at System.Text.Json.JsonSerializer.Write(Utf8JsonWriter writer, Int32 originalWriterDepth, Int32 flushThreshold, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.JsonSerializer.WriteAsyncCore(Stream utf8Json, Object value, Type inputType, JsonSerializerOptions options, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
   at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|29_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

@sungam3r Other Example:

Example

{"query":"{state_find(id:$id){state{id,uf}}}","variables": "{\"id\":1}"}

Error:

{
    "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
    "title": "One or more validation errors occurred.",
    "status": 400,
    "traceId": "|1eca12b9-47b16751bde8dba1.",
    "errors": {
        "$.variables": [
            "The JSON value could not be converted to System.Collections.Generic.IEnumerable`1[Newtonsoft.Json.Linq.JToken]. Path: $.variables | LineNumber: 0 | BytePositionInLine: 90."
        ]
    }
}

Note:

I made several attempts but all unsuccessfully ...

It is worth remembering that passing or direct value in the functioning perfectly

Success Example

{"query":"{state_find(id:1){state{id,uf}}}"} //success 
                         ^
                         Ok !!!

You have not declared a variable.
https://graphql.org/learn/queries/#variables

@sungam3r this:

System.Text.Json.JsonException: A possible object cycle was detected which is not supported. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 32.
   at System.Text.Json.ThrowHelper.ThrowInvalidOperationException_SerializerCycleDetected(Int32 maxDepth)
   at System.Text.Json.JsonSerializer.Write(Utf8JsonWriter writer, Int32 originalWriterDepth, Int32 flushThreshold, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.JsonSerializer.WriteAsyncCore(Stream utf8Json, Object value, Type inputType, JsonSerializerOptions options, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
   at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|29_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

It seems that this is a different error, here another serializer is used.

You have not declared a variable.
https://graphql.org/learn/queries/#variables

Yes the variable was declared

@sungam3r this:

System.Text.Json.JsonException: A possible object cycle was detected which is not supported. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 32.
   at System.Text.Json.ThrowHelper.ThrowInvalidOperationException_SerializerCycleDetected(Int32 maxDepth)
   at System.Text.Json.JsonSerializer.Write(Utf8JsonWriter writer, Int32 originalWriterDepth, Int32 flushThreshold, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.JsonSerializer.WriteAsyncCore(Stream utf8Json, Object value, Type inputType, JsonSerializerOptions options, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
   at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|29_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

It seems that this is a different error, here another serializer is used.

So the test was done GraphiQL and Google PostMan and gives errors like that. By the time I move to variables already the problem rolls.

Is there an example somewhere on how to pass to variables?

{"query":"{state_find(id:$id){state{id,uf}}}","variables": "{"id":1}"}

Yes the variable was declared

No, this is a query without variable declaration.

Are you using system.text.json? It doesn't mix well with json.net. I don't think this project yet supports it unless you create a custom converter for the variables which is tricky as the system.text.json does not support dictionary of objects yet. My not so pretty converter can be found here https://github.com/pekkah/tanka-graphql/blob/master/src/graphql.server.links/DTOs/ObjectDictionaryConverter.cs

{"query":"{state_find(id:$id){state{id,uf}}}","variables": "{"id":1}"}

Yes the variable was declared

No, this is a query without variable declaration.

Are you using system.text.json? It doesn't mix well with json.net. I don't think this project yet supports it unless you create a custom converter for the variables which is tricky as the system.text.json does not support dictionary of objects yet. My not so pretty converter can be found here https://github.com/pekkah/tanka-graphql/blob/master/src/graphql.server.links/DTOs/ObjectDictionaryConverter.cs

This error comes from the Visual Studio log, so I didn't program it.

{"query":"{state_find(id:$id){state{id,uf}}}","variables": "{"id":1}"}

Yes the variable was declared

No, this is a query without variable declaration.

Have an example?

_In short: my package works without it perfectly, but even in the GraphiQL interface it works I want to understand why. I also did an example with NodeJS and the same problem happens_

@pekkah and @sungam3r

Example:

Sem t铆tulo

Example Link Site GraphQL

Change id: 1 to id: $id - it will be right. But honestly, I still don鈥檛 understand what was going on.

Change id: 1 to id: $id - it will be right. But honestly, I still don鈥檛 understand what was going on.

GraphiQL->

kio

Me neither!

If there are passing variables of this problem.

Try to send the same request via GraphQL Playground. Maybe you use old version of GraphiQL ?

Try to send the same request via GraphQL Playground. Maybe you use old version of GraphiQL ?

I tried and it didn't work either. Also did test on Google PostMan and the same error. "GraphiQL" is what comes in the package

Looking at the error, it is trying to create an IEnumerable<JToken>. You鈥檙e not passing a JSON array, you鈥檙e passing a Object (as you should). What does the code look like that is handling the HTTP request? Are you using the GraphQL-server project or did you write your own middleware/controller?

Looking at the error, it is trying to create an IEnumerable<JToken>. You鈥檙e not passing a JSON array, you鈥檙e passing a Object (as you should). What does the code look like that is handling the HTTP request? Are you using the GraphQL-server project or did you write your own middleware/controller?

@joemcbride

Package:

https://github.com/graphql-dotnet/graphql-dotnet

Documentation:

https://graphql-dotnet.github.io/

GraphiQL

https://graphql-dotnet.github.io/docs/getting-started/graphiql

Nothing but that.

The test is done in GraphIQL as it is in the link

In short: nothing but what the package offers me and its documentation.

Understood?

No, I don鈥檛 understand, because this project does not provide a MVC Controller or Middleware to use, so you would need to write that yourself (which appears to be where this error is coming from). This error does not look like an error due to this project but your own code.

So please post a screenshot of the csproj file so we can see the exact nuget packages you鈥檙e using and the code you wrote to handle the HTTP request.

No, I don鈥檛 understand, because this project does not provide a MVC Controller or Middleware to use, so you would need to write that yourself (which appears to be where this error is coming from). This error does not look like an error due to this project but your own code.

So please post a screenshot of the csproj file so we can see the exact nuget packages you鈥檙e using and the code you wrote to handle the HTTP request.

Code:
What is in the documentation

using GraphiQl; 

public void Configure(
    IApplicationBuilder app, 
    IWebHostEnvironment env, 
    ILoggerFactory loggerFactory
)
{
     loggerFactory.AddFile("C:/Temp/logs/myapp-{Date}.txt");
     if (env.IsDevelopment())
     {
        app.UseDeveloperExceptionPage();
     }
     app.UseCors(options =>
     {
        options.AllowAnyOrigin();
        options.AllowAnyMethod();
        options.AllowAnyHeader();
     });

     app.UseGraphiQl("/graphql");   //Add Configuration 
     app.UseRouting();
     app.UseAuthorization();
     app.UseEndpoints(endpoints =>
     {
        endpoints.MapControllers();
     });
}

no Controller:

Base:

using Newtonsoft.Json.Linq;
namespace QL.Support
{
  public sealed class GraphQLQuery
  {
    public string OperationName { get; set; }
    public string NamedQuery { get; set; }
    public string Query { get; set; }
    public JObject Variables { get; set; }
  }
}

#

public async Task<IActionResult> Post([FromBody]GraphQLQuery query)
{
    try
    {
        Inputs inputs = query.Variables.ToInputs();
        ExecutionResult result = null;
        using (Schema schema = new Schema())
        {
           schema.Query = new QueryTypes(DatabaseAccess);
           void options(ExecutionOptions x)
           {
              x.Schema = schema;
              x.Query = query.Query;
              x.OperationName = query.OperationName;
              x.Inputs = inputs;
           }
           DocumentExecuter documentExecuter = new DocumentExecuter();
           result = await documentExecuter.ExecuteAsync(options);
           if (result?.Errors?.Count > 0)
           {
              return BadRequest(result.Errors);
           }
        }
        return Ok(result?.Data);
    }
    catch (System.Exception ex)
    {
        return BadRequest(ex);
    }
}

Code Example: https://github.com/graphql-dotnet/examples/tree/master/src/AspNetCoreCustom

Everything is in the package documentation.

A valid point, it does not arrive at the controller. Only comes when you take variables

@joemcbride

Just remember that the problem occurs when you place variables and the problem occurs in GraphiQL and PostMan Test.

@fulviocanducci just in case you aren鈥檛 aware, I was the one that wrote those docs and the example. So no, you鈥檙e not using that example code. That example code uses middleware. You wrote a MVC controller. Your project is also using .NET Core 3.0 and the examples are still in 2.2.

Have you configured your project to use JSON.NET as described here?

https://stackoverflow.com/a/58020971/279764

Once you do that, you will also have to enable AllowSynchronousIO, as described here: #1116

This project does not yet support System.Text.Json.

Your controller is also not using IDocumentWriter, so it is not returning results according to the GraphQL spec.

@

Have you configured your project to use JSON.NET as described here?

https://stackoverflow.com/a/58020971/279764

Once you do that, you will also have to enable AllowSynchronousIO, as described here: #1116

This project does not yet support System.Text.Json.

Your controller is also not using IDocumentWriter, so it is not returning results according to the GraphQL spec.

I'm not using JSON.NET.

@joemcbride

just in case you aren鈥檛 aware, I was the one that wrote those docs and the example. So no, you鈥檙e not using that example code. That example code uses middleware. You wrote a MVC controller. Your project is also using .NET Core 3.0 and the examples are still in 2.2.

Have you configured your project to use JSON.NET as described here?

It's the same as middleware, and if it didn't work it wouldn't return that:

sbddd

If you had problem would not return the information!
retorno

What you in a middlweare I did in a controller is the same.

But, okay, I won't question it anymore.

What you in a middlweare I did in a controller is the same.

No, it鈥檚 not the same, and we have been trying to help you fix it. We can鈥檛 help you if you don鈥檛 want to be helped.

Closing as this is not a problem with this project.

@fulviocanducci - Like @joemcbride and @sungam3r mentioned earlier, Gql.Net is not having the problem. The problem is with the Controller's model binder. You're using a .Net Core 3.x project, which uses Micrsoft's System.Text.Json by default instead of Newtonsoft. It can't deserialize a JObject (and it also can't serialize Gql.Net's ExecutionResult).

A quick/simple way to confirm this is to change your controller from this:

public async Task<IActionResult> Post([FromBody]GraphQLQuery query)
{
    // original code...
}

to this:

public async Task<IActionResult> Post([FromBody] System.Text.Json.JsonElement rawQuery)
{
    string rawJson = rawQuery.ToString();
    var query = JsonConvert.DeserializeObject<GraphQLQuery>(rawJson);
    // original code...
}

Now both GraphQL-dotnet and server projects have System.Text.Json support. Serialization/deserialization parts were moved to external packages. See readme here and in the server project.

@fulviocanducci - Like @joemcbride and @sungam3r mentioned earlier, Gql.Net is not having the problem. The problem is with the Controller's model binder. You're using a .Net Core 3.x project, which uses Micrsoft's System.Text.Json by default instead of Newtonsoft. It can't deserialize a JObject (and it also can't serialize Gql.Net's ExecutionResult).

A quick/simple way to confirm this is to change your controller from this:

public async Task<IActionResult> Post([FromBody]GraphQLQuery query)
{
  // original code...
}

to this:

public async Task<IActionResult> Post([FromBody] System.Text.Json.JsonElement rawQuery)
{
  string rawJson = rawQuery.ToString();
  var query = JsonConvert.DeserializeObject<GraphQLQuery>(rawJson);
  // original code...
}

This is the best solution to this Issue Thanks, but is there are a way to handle the coming query as an strongly typed object

This question is not specific to this project, it is better to ask the authors of System.Text.Json serializer.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nvhoanganh picture nvhoanganh  路  34Comments

Shane32 picture Shane32  路  31Comments

shoe-diamente picture shoe-diamente  路  33Comments

roybs2 picture roybs2  路  20Comments

pekkah picture pekkah  路  52Comments