Input Object Types

GraphQL input object types let you pass structured data as arguments. While scalar arguments work for simple values, input types let you group related fields into a single object. Input types differ from output object types: their fields cannot have arguments and they use the input keyword in the schema.

GraphQL schema

GraphQL
input CreateBookInput {
  title: String!
  author: String!
}

type Mutation {
  createBook(input: CreateBookInput!): Book
}

Defining an Input Type#

Any C# class or record used as a resolver parameter (that is not a scalar, enum, or service) becomes an input object type in the schema.

C#
public class CreateBookInput
{
    public string Title { get; set; }
    public string Author { get; set; }
}

[MutationType]
public static partial class BookMutations
{
    public static async Task<Book> CreateBookAsync(
        CreateBookInput input,
        CatalogContext db,
        CancellationToken ct)
    {
        var book = new Book { Title = input.Title, Author = input.Author };
        db.Books.Add(book);
        await db.SaveChangesAsync(ct);
        return book;
    }
}

If a class used as an argument does not end in Input, Hot Chocolate appends Input to the type name in the schema automatically.

Using Records and Immutable Types#

Input types can use immutable classes or C# records. Hot Chocolate calls the constructor instead of setting properties. The rules are:

  1. Each constructor parameter type must match the corresponding property type.
  2. Each constructor parameter name must match the property name (with a lowercase first letter).
  3. All properties must have a matching constructor parameter.

Hot Chocolate validates input constructors at schema build time, so mismatches are caught early.

C#
public record CreateBookInput(string Title, string Author);

This record is equivalent to a class with a constructor and get-only properties.

Default Values#

The [DefaultValue] attribute assigns a default value to an input field. When the client omits the field, the default is used.

C#
public class UserFilterInput
{
    public string? Name { get; set; }

    [DefaultValue(true)]
    public bool IsActive { get; set; }
}

This produces:

GraphQL
input UserFilterInput {
  name: String
  isActive: Boolean! = true
}

Default values maintain backward compatibility. When you add a new field to an input type, providing a default value keeps existing queries working.

Default Values with GraphQL Syntax#

For complex defaults (objects or lists), use [DefaultValueSyntax] with GraphQL value literal syntax.

C#
public class UserProfileInput
{
    public string? Name { get; set; }

    [DefaultValueSyntax("{ notifications: true, theme: \"light\" }")]
    public Preferences? Preferences { get; set; }
}

In code-first, use the DefaultValueSyntax method:

C#
descriptor
    .Field(f => f.Preferences)
    .DefaultValueSyntax("{ notifications: true, theme: \"light\" }");

Optional Properties#

Use Optional<T> to distinguish between a field that was not provided and a field explicitly set to null. This is important for partial updates where you need to know whether the client intended to clear a value.

C#
public class UpdateBookInput
{
    [DefaultValue("")]
    public Optional<string> Title { get; set; }

    public string Author { get; set; }
}

When using Optional<T> on a non-nullable field, you must add [DefaultValue] to make the field optional in the schema.

Records work too:

C#
public record UpdateBookInput(
    [property: DefaultValue("")] Optional<string> Title,
    string Author);

OneOf Input Objects#

A @oneOf input type requires that exactly one field is set and non-null. This provides input polymorphism, letting a single argument accept different shapes of data.

GraphQL schema

GraphQL
input PetInput @oneOf {
  cat: CatInput
  dog: DogInput
}
C#
[OneOf]
public class PetInput
{
    public CatInput? Cat { get; set; }
    public DogInput? Dog { get; set; }
}

public class CatInput
{
    public string Name { get; set; }
    public int NumberOfLives { get; set; }
}

public class DogInput
{
    public string Name { get; set; }
    public bool WagsTail { get; set; }
}

[MutationType]
public static partial class PetMutations
{
    public static Pet CreatePet(PetInput input)
    {
        // ...
    }
}

All fields on a @oneOf input must be nullable. Hot Chocolate validates at runtime that exactly one field is provided.

Next Steps#

Edit this page on GitHub
Last updated on by Tobias Tengler