Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolver for objects derived from dictionaries/lists implicitly applies a list conversion #7919

Open
AlexanderInova opened this issue Jan 9, 2025 · 0 comments

Comments

@AlexanderInova
Copy link

AlexanderInova commented Jan 9, 2025

Product

Hot Chocolate

Version

14.2.0

Link to minimal reproduction

https://github.com/AlexanderInova/HotChocolateDictIssue

Steps to reproduce

  1. Create a class that derives from Dictionary<string, object>:
    public class Metadata : Dictionary<string, object>
    {
      // ...
    }
  2. Create a GraphQL object type for that class and specify some fields:
    [ObjectType]
    public sealed class MetadataType : ObjectType<Metadata>
    {
      protected override void Configure(IObjectTypeDescriptor<Metadata> descriptor)
      {
        descriptor
          .BindFieldsExplicitly();
    
        descriptor.Field("all")
          .Type<NonNullType<ListType<NonNullType<MetadataEntryType>>>>()
          .Resolve(ctx => ctx.Parent<Metadata>().Select(e => new MetadataEntry(e.Key, e.Value)));
    
        descriptor.Field("value")
          .Argument("key", a => a.Type<NonNullType<StringType>>())
          .Type<JsonType>()
          .Resolve(ctx => ctx.Parent<Metadata>().TryGetValue(ctx.ArgumentValue<string>("key"), out var value) ? value : null);
      }
    }
    
    public record MetadataEntry(string Key, object? Value);
    
    [ObjectType]
    public sealed class MetadataEntryType : ObjectType<MetadataEntry>
    {
      protected override void Configure(IObjectTypeDescriptor<MetadataEntry> descriptor)
      {
        // ...
      }
    }
  3. Try to access the new field:
    query {
      metadata {
        all {
          key
          value
        }
    
        key1: value(key: "key1")
        key2: value(key: "key2")
        key3: value(key: "key3")
      }
    }

What is expected?

The specified resolver is called once per Metadata object (in this example) and successfully receives the actual object (as Metadata in this example) by calling ctx.Parent<Metadata>().

It is not automatically resolved as a list, which would violate the specified schema.

What is actually happening?

The specified resolver is invoked for each element of the enumerable object and receives System.Collections.Generic.KeyValuePair`2[System.String,System.Object] (in this example) by calling ctx.Parent<Metadata>()

Relevant log output

Exception has occurred: CLR/HotChocolate.GraphQLException
An exception of type 'HotChocolate.GraphQLException' occurred in HotChocolate.Execution.dll but was not handled in user code: 'The resolver parent type of field `Metadata.value` is `System.Collections.Generic.KeyValuePair`2[System.String,System.Object]` but the resolver requested the type `HotChocolateIssue.Metadata`. The resolver was unable to cast the parent type to the requested type.'
   at HotChocolate.Execution.Processing.MiddlewareContext.Parent[T]()
   at HotChocolateIssue.MetadataType.<>c.<Configure>b__0_2(IResolverContext ctx) in /workspaces/HotChocolateDictIssue/HotChocolateIssue/MetadataType.cs:line 24
   at HotChocolate.Types.ResolveObjectFieldDescriptorExtensions.<>c__DisplayClass0_0.<Resolve>b__0(IResolverContext ctx)
   at HotChocolate.Types.Helpers.FieldMiddlewareCompiler.<>c__DisplayClass9_0.<<CreateResolverMiddleware>b__0>d.MoveNext()

Additional context

No response

@AlexanderInova AlexanderInova changed the title Resolver for objects derived from dictionaries/lists implicitly apply a list conversion Resolver for objects derived from dictionaries/lists implicitly applies a list conversion Jan 9, 2025
@michaelstaib michaelstaib added this to the HC-14.5.0 milestone Jan 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants