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
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.
// Types/CreateBookInput.cspublic 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:
- Each constructor parameter type must match the corresponding property type.
- Each constructor parameter name must match the property name (with a lowercase first letter).
- All properties must have a matching constructor parameter.
Hot Chocolate validates input constructors at schema build time, so mismatches are caught early.
// Types/CreateBookInput.cspublic 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.
// Types/UserFilterInput.cspublic class UserFilterInput{ public string? Name { get; set; }
[DefaultValue(true)] public bool IsActive { get; set; }}
This produces:
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.
// Types/UserProfileInput.cspublic class UserProfileInput{ public string? Name { get; set; }
[DefaultValueSyntax("{ notifications: true, theme: \"light\" }")] public Preferences? Preferences { get; set; }}
In code-first, use the DefaultValueSyntax method:
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.
// Types/UpdateBookInput.cspublic 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:
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
input PetInput @oneOf { cat: CatInput dog: DogInput}
// Types/PetInput.cs[OneOf]public class PetInput{ public CatInput? Cat { get; set; } public DogInput? Dog { get; set; }}
// Types/CatInput.cspublic class CatInput{ public string Name { get; set; } public int NumberOfLives { get; set; }}
// Types/DogInput.cspublic 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
- Need scalar arguments? See Arguments.
- Need to write mutations? See Mutations.
- Need to understand nullability? See Non-Null.
- Need to document input fields? See Documentation.