[Question] Inspect given properties while working with complex variables for a mutation
I'm currently struggling while working with variabels for mutations, when arguments are a complex type. My problem is, that I get a deserialized type of Note in the example below but not a list of properties which are defined in the argument value (example call 1). I really think this is possible in any way and I have just a "simple" missunderstanding.
When not using a variable and passing the struct directly into the argument, it is very easy for me to read which properties are given (example call 2), just by inspecting context.Arguments.
I created this simple example to demonstrate my problem.
Classes
public class Note
{
public string Id { get; set; }
public string Title { get; set; }
public string Body { get; set; }
}
public class NoteGraphType: ObjectGraphType<Note>
{
public NoteGraphType()
{
Name = $"Note";
Field(typeof(StringGraphType), "Id");
Field(typeof(StringGraphType), "Title");
Field(typeof(StringGraphType), "Body");
}
}
public class InputNoteGraphType : InputObjectGraphType<Note>
{
public InputNoteGraphType()
{
Name = $"InputNote";
Field(typeof(StringGraphType), "Id");
Field(typeof(StringGraphType), "Title");
Field(typeof(StringGraphType), "Body");
}
}
Mutation
Field<NoteGraphType>("upsertNote",
arguments: new QueryArguments(
new QueryArgument<NonNullGraphType<InputNoteGraphType>> { Name = "input" }
),
resolve: context => {
var argumentVar = context.Variables.FirstOrDefault(x => x.Name == "input").Value;
// How to resolve which properties of the variable are given? Here: ["title", "body"]
// store.UpsertNote(argumentVar, propertyList);
return argumentVar;
});
// example call 1
mutation upsertNote($input: InputNote!) {
upsertNote(input: $input) {
id
}
}
Example call 1
mutation upsertNote($input: InputNote!) {
upsertNote(input: $input) {
id
}
}
# Variables
# {
# "input": {
# "title": "Test note",
# "body": "Hello World"
# }
# }
Example call 2
mutation upsertNote {
upsertNote(input: { title: "Test note", body: "Hello World" }) {
id
}
}
Try look into context.Arguments dictionary first.
In context.Arguments is also "just" the deserialized Note instance
Then context.Inputs.
Then
context.Inputs.
context is IResolveFieldContext and has no property Inputs
What version do you use?
What version do you use?
5.2.0
@Shane32 We have ExecutionOptions.Inputs and use it in ValidationContext to fill variables (parse/map discrete inputs into variables) but then no initial inputs available from resolver.
Trying to read the "initial inputs" would be a pain anyway. The input might be a literal and not contained within the variables, or it might be nested within another object. Then answer is easy with ParseDictionary, as this is exactly what the method was designed for:
Option 1
Add this code to your input graph type:
public override object ParseDictionary(IDictionary<string, object?> value)
=> value;
Then within your resolver, pull the raw dictionary like this:
var args = context.GetArgument<IDictionary<string, object>>("argument");
Option 2
public class Note
{
public string Id { get; set; }
public bool HasId { get; set; }
public string Title { get; set; }
public bool HasTitle { get; set; }
public string Body { get; set; }
public bool HasBody { get; set; }
}
//within input graph type
public override object ParseDictionary(IDictionary<string, object?> value)
{
var note = new Note();
note.HasId = value.TryGetValue("id", out var obj);
if (note.HasId) note.Id = (string)obj;
//repeat for title and body
return note;
}
//within resolver
var arg = context.GetArgument<Note>("arg");
if (arg.HasId) ...
Note
If you nest complex types, you might need to use the second option. Well, not necessarily. I guess it would depend on your needs.
@Sascha-Lindtner Were you able to solve your issue?
Sorry for my late answer. I created a fix. But all the other solutions did not work. As long as I created my InputTypes via InputObjectGraphType, I'm not able to see which fields are given. Now all my InputTypes a inherited by InputObjectGraphType instead and its fine.