5

Using GraphQL for .NET, I would like to replace the collection of Foo with a new collection.

Given this server-side code:

public class Foo
{
    public Foo(string name)
    {
        Name = name;
    }

    public string Name { get; set; }
}

public class Root
{
    public Foo[] Foos { get; private set; }

    public Foo[] UpdateFoos(Foo[] foos)
    {
        Foos = foos;
        return Foos;
    }
}

public class MutationSchema : Schema
{
    public MutationSchema()
    {
        Query = new MutationQuery();
        Mutation = new MutationChange();
    }
}

public class FooType : ObjectGraphType
{
    public FooType()
    {
        Name = "IndividualFoo";
        Field<StringGraphType>("name");
    }
}

public class FoosType : ObjectGraphType<ListGraphType<FooType>>
{
    public FoosType()
    {
        Name = "ListOfFoo";
        Field<ListGraphType<FooType>>("foos");
    }
}

public class FoosInput : InputObjectGraphType
{
    public FoosInput()
    {
        Name = "InputForManyFoo";
        Field<ListGraphType<FooInput>>("foos");
        Field<ListGraphType<FooType>>("foosResult");
    }
}

public class FooInput : InputObjectGraphType
{
    public FooInput()
    {
        Name = "InputForSingleFoo";
        Field<StringGraphType>("name");
    }
}

public class MutationQuery : ObjectGraphType
{
    public MutationQuery()
    {
        Name = "Query";
        Field<FoosType>("queryAllFoos");
    }
}

public class MutationChange : ObjectGraphType
{
    public MutationChange()
    {
        Name = "Mutation";

        Field<FoosInput>(
            "updateAllFoos",
            arguments: new QueryArguments(
                new QueryArgument<FoosInput>
                {
                    Name = "updateFoosQueryArgument"
                }
            ),
            resolve: context =>
            {
                var root = context.Source as Root;
                var change = context.GetArgument<Foo[]>("updateFoosQueryArgument");
                // TODO: update collection e.g. return root.UpdateFoos(change);
                return change;
            }
        );
    }
}

When I run the mutation query:

mutation M {
    fooCollection: updateAllFoos(updateFoosQueryArgument: {
        foos: [
            {name: "First Foo"},
            {name: "Second Foo"}
        ]}) {
        foosResult
    }
}

Then I get the following error:

{GraphQL.Validation.ValidationError: Cannot query field "foosResult" on type "InputForManyFoo". Did you mean "foosResult"?}

I'm using the latest version of GraphQL for .NET at the time of writing.

What am I missing?


Working Example: How to mutate a list of custom objects in GraphQL for .NET

Daniel Robinson
  • 2,165
  • 17
  • 14

1 Answers1

8

My answer from Gitter.

Make an ObjectGraphType for the result. Notice that the “shape” of the object that is returned from resolve matches the “shape” of the graph type.

public class FoosResultType : ObjectGraphType
{
    public FoosResultType()
    {
        Field<ListGraphType<FooType>>("foosResult");
    }
}

public class FoosResult
{
    public IEnumerable<Foo> FoosResult { get;set; }
}

public class MutationChange : ObjectGraphType
{
    public MutationChange()
    {
        Name = "Mutation";

        Field<FoosResultType>(
            "updateAllFoos",
            arguments: new QueryArguments(
                new QueryArgument<ListGraphType<FooInput>>
                {
                    Name = "updateFoosQueryArgument"
                }
            ),
            resolve: context =>
            {
                var root = context.Source as Root;
                var change = context.GetArgument<List<Foo>>("updateFoosQueryArgument");
                // TODO: update collection e.g. return root.UpdateFoos(change);
                return new FoosResult { FoosResult = change };
            }
        );
    }
}

And updated mutation:

mutation M {
    fooCollection: updateAllFoos(updateFoosQueryArgument: [
          {name: "First Foo"},
          {name: "Second Foo"}
        ]) {
        foosResult {
          name
        }
    }
}
Daniel Robinson
  • 2,165
  • 17
  • 14
Joe McBride
  • 3,789
  • 2
  • 34
  • 38
  • Thanks very much for all your help Joe! I will revisit on Monday morning and make sure it works. It's past validation now but it falls over during execution on the GetArgument line. {GraphQL.Validation.ValidationError: Argument "updateFoosQueryArgument" has invalid value {foos: [{name: "First Foo"}, {name: "Second Foo"}]}. In field "foos": Unknown field.} – Daniel Robinson Dec 09 '16 at 04:22
  • I'll try alternatives to Foo[] (IEnumerable etc) – Daniel Robinson Dec 09 '16 at 05:20
  • I updated the mutation - I had forgotten to change `updateFoosQueryArgument` in the mutation to just be a list. – Joe McBride Dec 09 '16 at 15:34
  • 1
    An array doesn't work - changed context.GetArgument("updateFoosQueryArgument"); to context.GetArgument>("updateFoosQueryArgument"); – Daniel Robinson Dec 12 '16 at 00:41