GraphQL using .NET Boxed: Mutations
This post is going to continue my exploration of GraphQL using the .NET Boxed template as a jumping off point. The code I am starting with can be found here. Check out GraphQL using .NET Boxed: Queries from last week for an exploration of queries.
Mutations are GraphQL’s way of allowing a client to request changes to the data on the server-side.
Starting Point
As we discovered last week, MainSchema
 is the central point to finding how GraphQL is set up in this template. Just for reference here is the full class.
public class MainSchema : Schema { public MainSchema( QueryObject query, MutationObject mutation, SubscriptionObject subscription, IDependencyResolver resolver) : base(resolver) { this.Query = resolver.Resolve<QueryObject>(); this.Mutation = mutation; this.Subscription = subscription; } }
We are interested in the Mutation
 property which is being assigned a MutationObject
.
Mutation Object
The following is the full MutationObject
 class which defines what mutations are allowed for which objects on this server and what happens when a mutation request is received.
public class MutationObject : ObjectGraphType<object> { public MutationObject(IHumanRepository humanRepository) { this.Name = "Mutation"; this.Description = "The mutation type for updates to our data."; this.FieldAsync<HumanObject, Human>( "createHuman", "Create a new human.", arguments: new QueryArguments( new QueryArgument<NonNullGraphType<HumanInputObject>>() { Name = "human", Description = "The human you want to create.", }), resolve: context => { var human = context.GetArgument<Human>("human"); return humanRepository.AddHuman(human, context.CancellationToken); }); } }
This is very similar to have the QueryObject
 from last week was set up. The first big difference is in the QueryArguments
. The mutation is taking a HumanInputObject
 class instead of an ID. If you look at the query argument you will also see that this argument isn’t allowed to be null.
new QueryArgument<NonNullGraphType<HumanInputObject>>()
What is the HumanInputObject
 class? It is an InputObjectGraphType
 and defines the shape of what the mutation query argument looks like. As you can see in the following it provides a name, description, and list of fields.
public class HumanInputObject : InputObjectGraphType { public HumanInputObject() { this.Name = "HumanInput"; this.Description = "A humanoid creature from Star Wars."; this.Field<NonNullGraphType<StringGraphType>>(nameof(Human.Name)); this.Field<StringGraphType>(nameof(Human.HomePlanet)); this.Field<ListGraphType<EpisodeEnumeration>>(nameof(Human.AppearsIn), "Which movie they appear in."); } }
Also, note that the fields are using nameof
 on the properties of the Human
 class to make sure the names match which will prevent any problems with the mapping between the 3 different human classes this project is working with. Here is an example of the field definition pulled out from the above sample.
this.Field<NonNullGraphType<StringGraphType>>(nameof(Human.Name));
Another thing to make note of is that even at the field level you can set if a field is allowed to be null or not on top of setting the type of the field.
Back over in the MutationObject
 let’s look at the resolve
 inside of the FieldAsync
 call.
resolve: context => { var human = context.GetArgument<Human>("human"); return humanRepository.AddHuman(human, context.CancellationToken); });
This is pulling the human
 query argument and it is being translated into an instance of the Human
 class and then sent to the repository to be saved.
Wrapping Up
That covers the basic exploration of mutations. I’m thinking about looking at subscriptions.
The associated sample code can be found here.
GraphQL using .NET Boxed: Mutations Read More »