Reference

TypedRequest

Package Trax.Api.GraphQL.Client.TypedNamespace Trax.Api.GraphQL.Client.TypedSource TypedRequest.cs, Attributes.cs, TypedQueryGenerator.cs

Base class for a request whose GraphQL document is generated from the request type and its result type. The request carries [GraphQLOperation], its variables are properties marked [GraphQLArgument], and the result type carries [GraphQLType]. The generated query is validated and sent like any other IGraphQLClientRequest.

Signature

public abstract class TypedRequest<TResponse> : IGraphQLClientRequest<TResponse>
{
    public virtual string Query { get; }
    public virtual object? Variables { get; }
    public virtual JsonElement UnwrapDataElement(JsonElement data);
}
 
public sealed class GraphQLOperationAttribute : Attribute
{
    public GraphQLOperationAttribute(OperationType operationType);
    public OperationType OperationType { get; }
    public string? Name { get; init; }
    public string? RootField { get; init; }
    public string? Path { get; init; }
}
 
public enum OperationType { Query, Mutation }
 
public sealed class GraphQLTypeAttribute : Attribute
{
    public GraphQLTypeAttribute(string typeName);
    public string TypeName { get; }
}
 
public sealed class GraphQLArgumentAttribute : Attribute
{
    public GraphQLArgumentAttribute(string graphQLType);
    public string GraphQLType { get; }
    public string? VariableName { get; init; }
}
 
public sealed class GraphQLFieldAttribute : Attribute
{
    public GraphQLFieldAttribute(string fieldName);
    public string FieldName { get; }
}

Members

MemberDescription
QueryThe generated document, built on first access and cached per request type
VariablesA dictionary of every [GraphQLArgument] property's current value, keyed by variable name; null when there are none
UnwrapDataElement(data)Descends through the Path wrapper fields, then into the root field. A missing field or a non-object on the way throws GraphQLExecutionException naming the field, the request type and the JSON kind found
[GraphQLOperation(operationType)]On the request class. OperationType is Query or Mutation. Name is the operation name, default the class name without a trailing Request. RootField is the schema field, default the camel-cased operation name. Path is a dot-separated chain of wrapper fields above the root field, such as "discover.players"
[GraphQLType(typeName)]On the result class (or a list's element class), and on any nested class that gets its own selection. TypeName is not read by the generator; field presence is checked when the query is validated. Inherited
[GraphQLArgument(graphQLType)]On a request property. Declares $name: graphQLType and passes it to the root field as the argument of the same name. VariableName overrides the camel-cased property name
[GraphQLField(fieldName)]On a result property. Selects fieldName, aliased to the property's response key when they differ (displayName: name)

Behavior

  • The selection is every public instance property of the result type except indexers and those marked [JsonIgnore(Condition = JsonIgnoreCondition.Always)]. A property's response key is its [JsonPropertyName], else its camel-cased name.
  • A property whose type carries [GraphQLType], or is a non-BCL class with properties, gets a nested selection; a list property is treated as its element type. Strings, primitives, enums, structs and System.* classes are leaves.
  • Generation throws InvalidOperationException when the request has no [GraphQLOperation], the result type has no [GraphQLType], Path is empty or has an empty or whitespace segment, a result type refers back to itself through its properties, or a [GraphQLField] alias would be a [JsonPropertyName] that is not a valid GraphQL name.
  • Subscriptions are not generated. Fragments, unions, interfaces and directives are not generated.
  • The same types always produce the same query text.

Example

[GraphQLOperation(OperationType.Query, RootField = "player")]
public sealed class GetPlayerRequest : TypedRequest<PlayerProfile>
{
    [GraphQLArgument("String!")]
    public required string Id { get; init; }
}
 
[GraphQLType("Player")]
public sealed class PlayerProfile
{
    public string Id { get; init; } = "";
 
    [GraphQLField("name")]
    public string DisplayName { get; init; } = "";
 
    public int Level { get; init; }
}

The generated document:

query GetPlayer($id: String!) {
  player(id: $id) {
    id
    displayName: name
    level
  }
}

See also