0

I am learing GraphQL in .NET Core 6 and running into the issue with Mutation. I figured out how to use object in the Queries but getting following error on Mutation.

Error:

System.ArgumentOutOfRangeException: Input type 'UserInputType' can have fields only of input types: ScalarGraphType, EnumerationGraphType or IInputObjectGraphType. Field 'contact' has an output type. (Parameter 'fieldType') at GraphQL.Types.ComplexGraphType1.AddField(FieldType fieldType) in /_/src/GraphQL/Types/Composite/ComplexGraphType.cs:line 101 at GraphQL.Types.ComplexGraphType1.Field[TGraphType](String name, String description, QueryArguments arguments, Func`2 resolve, String deprecationReason) in /_/src/GraphQL/Types/Composite/ComplexGraphType.cs:line 186 at GraphQlProject.Type.UserInputType..ctor() in /Users/UserName/MyPlayground/GraphQlProject/GraphQlProject/Type/UserInputType.cs:line 11 at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean wrapExceptions)

Questions:

  • What am I doing wrong here?
  • Do I need to create separate ContactInputType (the way I did in Queries?. If yes, then what would be InputObjectGraphType for that? And how to use that inside UserInputType?
  • If I pass all four object separately then I do not see this error BUT I see contact object is null which looks obvious to me.
  • I see similar question posted here, Field resolver for InputObjectGraphType but no answer.

Model:

public class User
{
    public string id { get; set; }
    public bool isActive { get; set; }
    public Contact contact { get; set; }
}

public class Contact
{
    public string firstName { get; set; }
    public string lastName { get; set; }
    public string email { get; set; }
    public string phoneNumber { get; set; }
}

Query Logic (Working):

UserType.cs

public class UserType : ObjectGraphType<User>
{
    public UserType()
    {
        Field(x => x.id);
        Field(x => x.isActive);
        Field(
            name: "contact",
            type: typeof(ContactType),
            resolve: context => context.Source.contact
        );
    }
}

contactType.cs

public class ContactType : ObjectGraphType<Contact>
{
    public ContactType()
    {
        Field(x => x.firstName);
        Field(x => x.lastName);
        Field(x => x.email);
        Field(x => x.phoneNumber);
    }
}

userQuery.cs

public class UserQuery: ObjectGraphType
{
    public UserQuery(IUser userService)
    {
        Field<UserType>("user", 
            arguments: new QueryArguments(
                new QueryArgument<StringGraphType> { Name = "id"}, 
                new QueryArgument<StringGraphType> { Name = "userId"}
                ),
            resolve: _ => userService.GetUserById(
                _.GetArgument<string>("id"), 
                _.GetArgument<string>("userId")
                ));
    }
}

Mutation Logic (getting above error):

public class UserMutation : ObjectGraphType
{
    public UserMutation(IUser userService)
    {
        Field<UserType>("createUser",
            arguments: new QueryArguments(
                    new QueryArgument<UserInputType> { Name = "user" }
                ),
            resolve: _ => userService.AddUser(_.GetArgument<User>("user"))
            );
    }
}

UserInputType.cs

public class UserInputType : InputObjectGraphType
{
    public UserInputType()
    {
        Field<StringGraphType>("id");
        Field<BooleanGraphType>("isActive");
        Field<ObjectGraphType>("contact"); // getting error here.
    }
}
GThree
  • 2,708
  • 7
  • 34
  • 67

1 Answers1

0

I was able to resolve this by looking into the 2nd bullet point from Questions.

Do I need to create separate ContactInputType (the way I did in Queries?. If yes, then what would be InputObjectGraphType for that? And how to use that inside UserInputType?

Lesson Learned: You don't have to use SOMEGraphType all the time. Custom type can be used as well.

Fix:

  1. Add ContactInputType.cs as below
public class ContactInputType : InputObjectGraphType
{
    public ContactInputType()
    {
        Field<StringGraphType>("firstName");
        Field<StringGraphType>("lastName");
        Field<StringGraphType>("email");
        Field<StringGraphType>("phoneNumber");
    }
}
  1. Use that in UserInputType.cs as below:
public class UserInputType : InputObjectGraphType
{
    public UserInputType()
    {
        Field<StringGraphType>("id");
        Field<BooleanGraphType>("isActive");
        Field<ContactInputType>("contact");
    }
}
GThree
  • 2,708
  • 7
  • 34
  • 67