0

I am trying to implement schema-first in Hot Chocolate and running into SchemaException

I have the below GraphQL Schema

type Query {      
  sites(skip: Int, take: Int): SitesResponse  
}

interface PagedResponse {
  hasNextPage: Boolean!
  hasPreviousPage: Boolean!
  totalCount: Int!
}

type SitesResponse implements PagedResponse {
  items: [Site]
}

type Site {
  siteNumber: String!
  siteName: String!
  siteType: String!
  divisionNumber: Int!
}

Startup

services
.AddGraphQLServer()
.AddDocumentFromFile("GraphQlSchema.graphql")
.AddResolver<RosterResolver>("Query")
.BindRuntimeType<PagedResponse<Site>>("SitesResponse")

Resolver

public class RosterResolver
    {
        public PagedResponse<Site> GetSites(int? skip, int? take)
        {
            return new PagedResponse<Site>
            {
                HasNextPage = false,
                HasPreviousPage = false,
                Items = new List<Site> { new Site { DivisionNumber = 1, SiteName = "test", SiteNumber = "1234", SiteType = "Test" } },
                TotalCount = 1
            };
        }

Result

HotChocolate.SchemaException: For more details look at the `Errors` property.

1. The field `hasNextPage` must be implement by object type `SitesResponse`. (HotChocolate.Types.ObjectType)
2. The field `hasPreviousPage` must be implement by object type `SitesResponse`. (HotChocolate.Types.ObjectType)
3. The field `totalCount` must be implement by object type `SitesResponse`. (HotChocolate.Types.ObjectType)

   at HotChocolate.Configuration.TypeInitializer.Initialize(Func`1 schemaResolver, IReadOnlySchemaOptions options)
   at HotChocolate.SchemaBuilder.Setup.InitializeTypes(SchemaBuilder builder, IDescriptorContext context, IReadOnlyList`1 types, LazySchema lazySchema)
   at HotChocolate.SchemaBuilder.Setup.Create(SchemaBuilder builder, LazySchema lazySchema, IDescriptorContext context)
   at HotChocolate.SchemaBuilder.Create(IDescriptorContext context)
   at HotChocolate.SchemaBuilder.HotChocolate.ISchemaBuilder.Create(IDescriptorContext context)
   at HotChocolate.Execution.RequestExecutorResolver.CreateSchemaAsync(NameString schemaName, RequestExecutorSetup options, RequestExecutorOptions executorOptions, IServiceProvider serviceProvider, TypeModuleChangeMonitor typeModuleChangeMonitor, CancellationToken cancellationToken)
   at HotChocolate.Execution.RequestExecutorResolver.CreateSchemaServicesAsync(NameString schemaName, RequestExecutorSetup options, CancellationToken cancellationToken)
   at HotChocolate.Execution.RequestExecutorResolver.GetRequestExecutorNoLockAsync(NameString schemaName, CancellationToken cancellationToken)
   at HotChocolate.Execution.RequestExecutorResolver.GetRequestExecutorAsync(NameString schemaName, CancellationToken cancellationToken)
   at HotChocolate.Execution.RequestExecutorProxy.GetRequestExecutorAsync(CancellationToken cancellationToken)
   at HotChocolate.AspNetCore.HttpPostMiddleware.HandleRequestAsync(HttpContext context, AllowedContentType contentType)
   at HotChocolate.AspNetCore.HttpPostMiddleware.InvokeAsync(HttpContext context)
   at HotChocolate.AspNetCore.WebSocketSubscriptionMiddleware.InvokeAsync(HttpContext context)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Is it possible to return a generic class PagedResponse? or do we need to implement a concrete class for each return type? ie: SitesResponse, Entity1Response, Entity2Response, etc etc

Ricky Gummadi
  • 4,559
  • 2
  • 41
  • 67

1 Answers1

1

The GraphQL spec states that the interface fields have to be repeated on the type.

interface PagedResponse {
  hasNextPage: Boolean!
  hasPreviousPage: Boolean!
  totalCount: Int!
}

type SitesResponse implements PagedResponse {
  hasNextPage: Boolean!
  hasPreviousPage: Boolean!
  totalCount: Int!
  items: [Site]
}

If you look at the schema exception it essentially just tells you that:

The field `hasNextPage` must be implement by object type `SitesResponse`. (HotChocolate.Types.ObjectType)

Interface Specification: https://spec.graphql.org/October2021/#sec-Interfaces

Type Validation Rule: https://spec.graphql.org/October2021/#sec-Objects.Type-Validation

  • Note, if you have interfaces that implement interfaces the same rule is true. On each interface level you need to repeat the fields: ```GraphQL Interface Foo { bar: String } interface Baz implements Foo { bar: String cux: String } ``` – Michael Ingmar Staib Nov 26 '21 at 13:26
  • Awesome thank you! that did it, just getting into GraphQL missed the part about how the interfaces are specified, great to know. Thank you for getting back with an answer and really appreciate your inputs in answering all the HotChoclate questions here and the ChilliCream platform, it is a well-designed framework. – Ricky Gummadi Nov 27 '21 at 00:00