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 type in the schema.

C#
// Types/CreateBookInput.cs
public class CreateBookInput
{
public string Title { get; set; }
public string Author { get; set; }
}
// Types/BookMutations.cs
[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#
// Types/CreateBookInput.cs
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#
// Types/UserFilterInput.cs
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#
// Types/UserProfileInput.cs
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#
// Types/UpdateBookInput.cs
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#
// Types/PetInput.cs
[OneOf]
public class PetInput
{
public CatInput? Cat { get; set; }
public DogInput? Dog { get; set; }
}
// Types/CatInput.cs
public class CatInput
{
public string Name { get; set; }
public int NumberOfLives { get; set; }
}
// Types/DogInput.cs
public class DogInput
{
public string Name { get; set; }
public bool WagsTail { get; set; }
}
// Types/PetMutations.cs
[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

Last updated on April 13, 2026 by Michael Staib