Arguments
GraphQL arguments let clients pass values to individual fields. In Hot Chocolate, each parameter on a resolver method becomes a field argument in the schema, unless it is a recognized service type (like CancellationToken or a registered service).
GraphQL schema
type Query { user(id: ID!): User users(role: UserRole, limit: Int = 10): [User!]!}
Client query
{ user(id: "UHJvZHVjdAppMQ==") { name }}
Arguments are frequently provided through variables, which separate the static query structure from the dynamic runtime values:
query ($userId: ID!) { user(id: $userId) { name }}
Defining Arguments
Method parameters on a resolver become GraphQL arguments.
// Types/UserQueries.cs[QueryType]public static partial class UserQueries{ public static User? GetUser(string username, UserService users) => users.FindByName(username);}
The username parameter becomes a username: String! argument. The UserService parameter is recognized as a service and is not exposed in the schema.
Renaming Arguments
Use [GraphQLName] to change the argument name in the schema while keeping the C# parameter name unchanged.
// Types/UserQueries.cs[QueryType]public static partial class UserQueries{ public static User? GetUser( [GraphQLName("name")] string username, UserService users) => users.FindByName(username);}
This produces user(name: String!): User in the schema.
Optional Arguments
An argument is required when its C# type is non-nullable. Make an argument optional by using a nullable type.
// Types/ProductQueries.cs[QueryType]public static partial class ProductQueries{ public static List<Product> GetProducts(string? category, int? limit) { // Both arguments are optional // ... }}
This produces:
type Query { products(category: String, limit: Int): [Product!]!}
When using nullable reference types (recommended), string maps to String! and string? maps to String. See Non-Null for details.
Default Values
Use [DefaultValue] to assign a default to an argument. The default appears in the schema and is used when the client omits the argument.
// Types/ProductQueries.cs[QueryType]public static partial class ProductQueries{ public static List<Product> GetProducts( [DefaultValue(10)] int limit) { // ... }}
This produces products(limit: Int! = 10): [Product!]!.
C# default parameter values also work:
public static List<Product> GetProducts(int limit = 10)
The ID Attribute
The [ID] attribute marks a parameter as a GraphQL ID scalar. When combined with global object identification, it also deserializes the opaque global ID back to the underlying value.
// Types/ProductQueries.cs[QueryType]public static partial class ProductQueries{ public static Product? GetProduct([ID] int id, CatalogContext db) => db.Products.Find(id);}
To restrict the ID to a specific type (ensuring only IDs serialized for Product are accepted):
public static Product? GetProduct( [ID(nameof(Product))] int id, CatalogContext db) => db.Products.Find(id);
In v16, you can also use the generic form [ID<Product>] which infers the type name automatically.
Complex Arguments
When an argument needs multiple fields, use an input object type instead of multiple scalar arguments.
// Types/BookFilterInput.cspublic record BookFilterInput(string? Title, string? Author, int? Year);
// Types/BookQueries.cs[QueryType]public static partial class BookQueries{ public static List<Book> GetBooks(BookFilterInput filter, CatalogContext db) { // ... }}
This produces:
input BookFilterInput { title: String author: String year: Int}
type Query { books(filter: BookFilterInput!): [Book!]!}
Next Steps
- Need structured input? See Input Object Types.
- Need to understand nullability? See Non-Null.
- Need global IDs? See Relay.
- Need to set up resolvers? See Resolvers.