# Input Object Types - Hot Chocolate

> Define GraphQL input object types in Hot Chocolate to pass structured arguments, with records, default values, optional properties, and @oneOf inputs.

Canonical source: https://chillicream.com/docs/hotchocolate/defining-a-schema/input-object-types

GraphQL input object types let you pass structured data as arguments. While [scalar arguments](https://chillicream.com/docs/hotchocolate/defining-a-schema/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

- **Need scalar arguments?** See [Arguments](https://chillicream.com/docs/hotchocolate/defining-a-schema/arguments).
- **Need to write mutations?** See [Mutations](https://chillicream.com/docs/hotchocolate/defining-a-schema/mutations).
- **Need to understand nullability?** See [Non-Null](https://chillicream.com/docs/hotchocolate/defining-a-schema/non-null).
- **Need to document input fields?** See [Documentation](https://chillicream.com/docs/hotchocolate/defining-a-schema/documentation).
[Edit this page on GitHub](https://github.com/ChilliCream/graphql-platform/edit/main/website/content/docs/hotchocolate/defining-a-schema/input-object-types.md)

Last updated on **June 30, 2026** by **Tobias Tengler**
