c# - GraphQL 模型在 System.Text.Json.JsonException 中挣扎

标签 c# graphql graphql-dotnet

我创建了一个新的 .NET Core 项目并安装了 GraphQL、GraphiQL 和 GraphQL.SystemTextJson 包。
运行应用程序时,这就是我得到的
enter image description here
除了异常消息之外,GraphiQL 无法找到架构文档。
首先,我有两个实体,用户和任务。

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

public sealed class Task
{
    public Guid Id { get; set; }
}
并且它们都有自己的表示图类型
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.");
    }
}
我创建了包含客户端可以执行的所有“操作”的查询
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);
    }
}
并为架构注册该查询
public sealed class GraphQLSchema : GraphQL.Types.Schema
{
    public GraphQLSchema(GraphQLQuery graphQLQuery, IServiceProvider serviceProvider) : base(serviceProvider)
    {
        Query = graphQLQuery;
    }
}
在启动文件中ConfigureServices在调用 services.AddControllers() 之前,我添加了此代码以注册所有必需的服务
serviceCollection
        .AddSingleton<IDocumentExecuter, DocumentExecuter>()
        .AddSingleton<IDocumentWriter, DocumentWriter>()
        .AddSingleton<ISchema, GraphQLSchema>()
        .AddSingleton<GraphQLQuery>()
并在 Configure我调用的方法 app.UseGraphiQl()首先。
对应的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; }
}
最后我实现了 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);
    }
}
有人知道这里出了什么问题吗?我看不到循环依赖等问题。

运行应用程序时 graphQlRequest包含以下值
  • 操作名称:自省(introspection)查询
  • 查询:

  • .
    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
                  }
                }
              }
            }
          }
        }
      }
    }
    

    我现在迁移到 .NET 5 并收到此错误
    enter image description here

    我添加了一个复制存储库
    https://github.com/olaf-svenson/graphql-net-reproduction

    最佳答案

    您在 .Net 5 中的错误与未注册的图形类型有关。如果您在调试设置中启用所有异常并禁用“仅我的代码”,您将看到此错误

    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()
    
    添加 UserTypeTaskType to DI 容器解决了这个错误。
    现在,您原来的问题是:您应该使用 IDocumentWriter要编写响应,您不能只是序列化 executionResult通过返回 Ok(executionResult) .
    使用此代码编写响应(从官方 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);
    }
    
    已更新 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);
        }
    }
    

    关于c# - GraphQL 模型在 System.Text.Json.JsonException 中挣扎,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65509530/

    相关文章:

    graphql - Quarkus SmallRye Graphql-客户端突变查询

    reactjs - Apollo 客户端 v3 不使用 useQuery 缓存查询结果

    python - 在 Django 2.2 中为 GRAPHENE 设置 'SCHEMA' 导入模块时出现问题

    c# - GraphQL + Autofac

    c# - SQL语法错误

    c# - SQL连接性能问题

    c# - 带有 List<Dictionary<string, string>> | 的 GraphQL.NET 突变JSON字符串

    c# - 调试时停止 Visual Studio 启动当前选择/打开的 HTML 页面

    c# - 使用 OData 查询字符串时抛出 MissingManifestResourceException