简体   繁体   English

GraphQL 模型苦苦挣扎于 System.Text.Json.JsonException

[英]GraphQL models struggling with System.Text.Json.JsonException

I created a new .NET Core project and installed the packages GraphQL, GraphiQL and GraphQL.SystemTextJson.我创建了一个新的 .NET 核心项目并安装了包 GraphQL、GraphiQL 和 GraphQL.SystemTextJson。

When running the application this is what I get运行应用程序时,这就是我得到的

在此处输入图像描述

Besides the exception message GraphiQL wasn't able to find a schema documentation.除了异常消息 GraphiQL 无法找到架构文档。

First of all I have two entities, users and tasks.首先,我有两个实体,用户和任务。

public sealed class User
{
    public Guid Id { get; set; }
}

public sealed class Task
{
    public Guid Id { get; set; }
}

and both of them have their representing graph type并且他们都有自己的代表图类型

public sealed class UserType : ObjectGraphType<User>
{
    public UserType()
    {
        Name = nameof(User);
        Field(user => user.Id).Description("The user id.");
    }
}

public sealed class TaskType : ObjectGraphType<Task>
{
    public TaskType()
    {
        Name = nameof(Task);
        Field(task => task.Id).Description("The task id.");
    }
}

I created the query holding all the "actions" the client can execute我创建了包含客户端可以执行的所有“操作”的查询

public sealed class GraphQLQuery : ObjectGraphType
{
    private readonly List<User> _users = new List<User>();
    private readonly List<Task> _tasks = new List<Task>();

    public GraphQLQuery()
    {
        Field<ListGraphType<UserType>>(
            "users",
            "Returns a collection of users.",
            resolve: context => _users);

        Field<ListGraphType<TaskType>>(
            "tasks",
            "Returns a collection of tasks.",
            resolve: context => _tasks);
    }
}

and register that query for the schema并为模式注册该查询

public sealed class GraphQLSchema : GraphQL.Types.Schema
{
    public GraphQLSchema(GraphQLQuery graphQLQuery, IServiceProvider serviceProvider) : base(serviceProvider)
    {
        Query = graphQLQuery;
    }
}

In the startup file in the ConfigureServices I added this code to register all the required services before calling services.AddControllers()ConfigureServices的启动文件中,我添加了此代码以在调用services.AddControllers()之前注册所有必需的服务

serviceCollection
        .AddSingleton<IDocumentExecuter, DocumentExecuter>()
        .AddSingleton<IDocumentWriter, DocumentWriter>()
        .AddSingleton<ISchema, GraphQLSchema>()
        .AddSingleton<GraphQLQuery>()

and in the Configure method I call app.UseGraphiQl() at first.Configure方法中,我首先调用app.UseGraphiQl()

The corresponding GraphQL request DTO对应的GraphQL请求DTO

public sealed class GraphQLRequest
{
    public string OperationName { get; set; }
    public string Query { get; set; }

    [JsonConverter(typeof(ObjectDictionaryConverter))]
    public Dictionary<string, object> Variables { get; set; }
}

Lastly I implemented the API controller最后我实现了 API controller

[ApiController]
[Route("[controller]")]
public sealed class GraphQLController : Controller
{
    private readonly ISchema _schema;
    private readonly IDocumentExecuter _documentExecuter;

    public GraphQLController(ISchema schema, IDocumentExecuter documentExecuter)
    {
        _schema = schema;
        _documentExecuter = documentExecuter;
    }

    public async Task<IActionResult> Post([FromBody] GraphQLRequest graphQlRequest)
    {
        ExecutionOptions executionOptions = new ExecutionOptions()
        {
            Schema = _schema,
            Query = graphQlRequest.Query,
            Inputs = graphQlRequest.Variables?.ToInputs()
        };

        ExecutionResult executionResult = await _documentExecuter.ExecuteAsync(executionOptions);

        if (executionResult.Errors != null)
            return BadRequest(executionResult);

        return Ok(executionResult);
    }
}

Does someone know what's wrong here?有人知道这里有什么问题吗? I can't see problems like circular dependency etc.我看不到循环依赖等问题。


When running the application the graphQlRequest contains the following values运行应用程序时, graphQlRequest包含以下值

  • OperationName: IntrospectionQuery操作名称:IntrospectionQuery
  • Query:询问:

. .

query IntrospectionQuery {
  __schema {
    queryType { name }
    mutationType { name }
    subscriptionType { name }
    types {
      ...FullType
    }
    directives {
      name
      description
      locations
      args {
        ...InputValue
      }
    }
  }
}

fragment FullType on __Type {
  kind
  name
  description
  fields(includeDeprecated: true) {
    name
    description
    args {
      ...InputValue
    }
    type {
      ...TypeRef
    }
    isDeprecated
    deprecationReason
  }
  inputFields {
    ...InputValue
  }
  interfaces {
    ...TypeRef
  }
  enumValues(includeDeprecated: true) {
    name
    description
    isDeprecated
    deprecationReason
  }
  possibleTypes {
    ...TypeRef
  }
}

fragment InputValue on __InputValue {
  name
  description
  type { ...TypeRef }
  defaultValue
}

fragment TypeRef on __Type {
  kind
  name
  ofType {
    kind
    name
    ofType {
      kind
      name
      ofType {
        kind
        name
        ofType {
          kind
          name
          ofType {
            kind
            name
            ofType {
              kind
              name
              ofType {
                kind
                name
              }
            }
          }
        }
      }
    }
  }
}

I migrated to .NET 5 now and get this error instead我现在迁移到 .NET 5 并收到此错误

在此处输入图像描述


I added a reproduction repository我添加了一个复制存储库

https://github.com/olaf-svenson/graphql-net-reproduction https://github.com/olaf-svenson/graphql-net-reproduction

It's a classic for Json resolvers.这是 Json 解析器的经典之作。 if you have navigation properties or properties that reference eachother.如果您有导航属性或相互引用的属性。

Often this can be fixed by either returning a mapped result, or by adjusting the Json Serializer settings.通常可以通过返回映射结果或调整 Json 串行器设置来解决此问题。

I'm unsure whether this is fixed in.Net Core 3.1 but you can to the startup.cs add我不确定这是否已在.Net Core 3.1 中修复,但您可以在 startup.cs 添加

install Newtonsoft Json if you haven't already.如果您还没有安装Newtonsoft Json

services
  .AddControllers()
  .AddNewtonsoftJson(options =>
  {
      options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
  });

hope this resolves it.希望这能解决它。

here's some article about the issue.这里有一些关于这个问题的文章。

https://dotnetcoretutorials.com/2020/03/15/fixing-json-self-referencing-loop-exceptions/ https://dotnetcoretutorials.com/2020/03/15/fixing-json-self-referencing-loop-exceptions/

.net core 3 not having ReferenceLoopHandling in AddJsonOptions .net 核心 3 在 AddJsonOptions 中没有 ReferenceLoopHandling

Your error in.Net 5 related to unregistered graph types.您在.Net 5 中的错误与未注册的图形类型有关。 If you enable all exceptions and disable "Just My Code" in debug settings you will see this error如果您在调试设置中启用所有异常并禁用“仅我的代码”,您将看到此错误

System.InvalidOperationException: 'Required service for type API.GraphTypes.UserType not found'
This exception was originally thrown at this call stack:
    GraphQL.Utilities.ServiceProviderExtensions.GetRequiredService(System.IServiceProvider, System.Type) in ServiceProviderExtensions.cs
    GraphQL.Types.Schema.CreateTypesLookup.AnonymousMethod__68_1(System.Type) in Schema.cs
    GraphQL.Types.GraphTypesLookup.Create.AnonymousMethod__0(System.Type) in GraphTypesLookup.cs
    GraphQL.Types.GraphTypesLookup.AddTypeIfNotRegistered(System.Type, GraphQL.Types.TypeCollectionContext) in GraphTypesLookup.cs
    GraphQL.Types.GraphTypesLookup.HandleField(GraphQL.Types.IComplexGraphType, GraphQL.Types.FieldType, GraphQL.Types.TypeCollectionContext, bool) in GraphTypesLookup.cs
    GraphQL.Types.GraphTypesLookup.AddType(GraphQL.Types.IGraphType, GraphQL.Types.TypeCollectionContext) in GraphTypesLookup.cs
    GraphQL.Types.GraphTypesLookup.Create(System.Collections.Generic.IEnumerable<GraphQL.Types.IGraphType>, System.Collections.Generic.IEnumerable<GraphQL.Types.DirectiveGraphType>, System.Func<System.Type, GraphQL.Types.IGraphType>, GraphQL.Conversion.INameConverter, bool) in GraphTypesLookup.cs
    GraphQL.Types.Schema.CreateTypesLookup() in Schema.cs
    System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()

Adding UserType and TaskType to DI container solves this error.UserTypeTaskType添加到 DI 容器可以解决此错误。

Now, your original problem: you should use IDocumentWriter to write the response, you can't just serialize executionResult by returning Ok(executionResult) .现在,您的原始问题:您应该使用IDocumentWriter来编写响应,您不能只通过返回Ok(executionResult)来序列化executionResult Use this code to write response (stolen from official graphql-dotnet/examples repo):使用此代码编写响应(从官方graphql-dotnet/examples repo 窃取):

private async Task WriteResponseAsync(HttpContext context, ExecutionResult result)
{
    context.Response.ContentType = "application/json";
    context.Response.StatusCode = result.Errors?.Any() == true ? (int)HttpStatusCode.BadRequest : (int)HttpStatusCode.OK;

    await _documentWriter.WriteAsync(context.Response.Body, result);
}

The updated GraphQLController.cs更新后的GraphQLController.cs

[ApiController]
[Route("[controller]")]
public sealed class GraphQLController : Controller
{
    private readonly ISchema _schema;
    private readonly IDocumentExecuter _documentExecuter;
    private readonly IDocumentWriter _documentWriter;

    public GraphQLController(ISchema schema, IDocumentExecuter documentExecuter, IDocumentWriter documentWriter)
    {
        _schema = schema;
        _documentExecuter = documentExecuter;
        _documentWriter = documentWriter;
    }

    public async Task Post([FromBody] GraphQLRequest graphQlRequest)
    {
        ExecutionOptions executionOptions = new ExecutionOptions()
        {
            Schema = _schema,
            Query = graphQlRequest.Query,
            Inputs = graphQlRequest.Variables?.ToInputs()
        };

        ExecutionResult executionResult = await _documentExecuter.ExecuteAsync(executionOptions);

        await WriteResponseAsync(HttpContext, executionResult);
    }

    private async Task WriteResponseAsync(HttpContext context, ExecutionResult result)
    {
        context.Response.ContentType = "application/json";
        context.Response.StatusCode = result.Errors?.Any() == true ? (int)HttpStatusCode.BadRequest : (int)HttpStatusCode.OK;
    
        await _documentWriter.WriteAsync(context.Response.Body, result);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 System.Text.Json.JsonException:无法将 Json 转换为 DataModel - System.Text.Json.JsonException: Unable to convert Json to DataModel System.Text.Json.JsonException:无法转换 JSON 值 - System.Text.Json.JsonException: The JSON value could not be converted System.Text.Json.JsonException:检测到可能的 object 循环 - System.Text.Json.JsonException: A possible object cycle was detected System.Text.Json.JsonException:&#39;检测到不支持的可能对象循环......&#39; - System.Text.Json.JsonException: 'A possible object cycle was detected which is not supported....' 应用程序运行时触发 System.Text.Json.JsonException 错误消息 - System.Text.Json.JsonException error message triggered when app is running SignalR 从 NewtonsoftJsonProtocol 切换到 JsonProtocol 抛出 System.Text.Json.JsonException: '{' is invalid after a value - SignalR switching from NewtonsoftJsonProtocol to JsonProtocol throws System.Text.Json.JsonException: '{' is invalid after a value System.Text.Json.JsonException:输入不包含任何 JSON 标记 - System.Text.Json.JsonException: The input does not contain any JSON tokens C# 循环引用。 System.Text.Json.JsonException:检测到可能的对象循环 .NET 5 - C# Circular reference. System.Text.Json.JsonException: A possible object cycle was detected .NET 5 如何解决 System.Text.Json.JsonException:在实体框架中检测到可能的 object 循环? - How to resolve System.Text.Json.JsonException: A possible object cycle was detected in Entity Framework? Azure CosmosDB + NetCore 3.1:System.Text.Json.JsonException:检测到可能的 object 循环不支持 - Azure CosmosDB + NetCore 3.1 : System.Text.Json.JsonException: A possible object cycle was detected which is not supported
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM