3

I work on a ASP.NET Web API and have added support for GraphQL requests with GraphQL for .NET . My queries are working as expected but I am now struggling to use the same logic with the mutations.

I have the following logic for my queries:

Field<ContactType>("contact", "This field returns the contact by Id",
            arguments: new QueryArguments(QA_ContactId),
            resolve: ctx => ContactResolvers.ContactDetails(ctx));

My resolver returns a ContactDomainEntity that is then resolved into a ContactType:

public class ContactType : ObjectGraphType<ContactDomainEntity>
{
    public ContactType()
    {
        Name = "Contact";
        Description = "Contact Type";

        Field(c => c.Id);
        Field(c => c.FirstName, nullable: true);

        Field<ListGraphType<AddressType>, IEnumerable<AddressDTO>>(Field_Addresses)
            .Description("Contact's addresses")
            .Resolve(ctx => LocationResolvers.ResolveAddresses(ctx));
    }
}

It all works really well and the address list is resolved with its own reslver (LocationResolvers.ResolveAddresses) which makes it reusable and helps with the separation of concerns.

Now I want to be able to edit a contact and was hoping to use the same logic where child-objects (like the list of addresses) would be handled by their own resolver. So I have created the following mutation:

Field<ContactType>("UpdateContact", "This field updates the Contact's details",
                arguments: new QueryArguments(QA_Input<Types.Input.ContactInputType>()),
                resolve: ctx => ContactResolvers.UpdateContact(ctx));

with the ContactInputType:

public class ContactInputType : InputObjectGraphType<ContactInputDTO>
{
    public ContactInputType()
    {
        Name = "UpdateContactInput";
        Description = "Update an existing contact";

        Field(c => c.Id);
        Field(c => c.FirstName, nullable: true);

        Field<ListGraphType<AddressInputType>, IEnumerable<AddressDTO>>("Addresses")
             .Description("Manage contact's addresses")
             .Resolve(ctx => LocationResolvers.ManageAddresses(ctx));
    }
}

(Note that I use DTOs to map the fields into an object which makes sense in my case but that is not related to my problem)

My issue is that only the resolver 'ContactResolvers.UpdateContact' gets called. The field resolver 'LocationResolvers.ManageAddresses' is never hit. If I replace the addresses field with the following:

Field(c => c.Addresses, nullable: true, type: typeof(ListGraphType<AddressInputType>));

my ContactInputDTO is correctly populated (i.e. its property 'Addresses' contains the right data) but it means I lose control on how the object properties are mapped and have to rely on them having the same name and cannot add additional logic that my resolver might have.


tl;dr How to use a field resolver with InputObjectGraphType? It works fine when returning an ObjectGraphType but I can't get it working on the receiving end.

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
webStuff
  • 1,468
  • 14
  • 22

0 Answers0