AddTraxGraphQL

Registers the Trax GraphQL schema and services using HotChocolate. This adds the query type, mutation type, and all type extensions needed to serve the Trax GraphQL API.

Signatures

AddTraxGraphQL

public static IServiceCollection AddTraxGraphQL(this IServiceCollection services)
public static IServiceCollection AddTraxGraphQL(
    this IServiceCollection services,
    Func<TraxGraphQLBuilder, TraxGraphQLBuilder> configure)
Parameter Type Required Description
services IServiceCollection Yes The service collection
configure Func<TraxGraphQLBuilder, TraxGraphQLBuilder> No Optional builder for registering DbContext-based query models, custom type modules, filter/sort overrides, and schema configuration.

Returns: IServiceCollection for continued chaining.

The parameterless overload calls the builder overload with an identity function. Use the builder overload to configure the schema:

builder.Services.AddTraxGraphQL(graphql => graphql
    .AddDbContext<GameDbContext>()
    .AddFilterType<Player, PlayerFilterInputType>()
    .AddSortType<Player, PlayerSortInputType>()
    .AddTypeModule<RelationshipTypeModule>()
    .AddTypeExtension<PlayerStatsExtension>()
    .AddTypeExtensions(typeof(PlayerStatsExtension).Assembly)
    .ConfigureSchema(schema => schema
        .ModifyCostOptions(o => { o.MaxFieldCost = 50000; })
    )
);

Builder Methods

Method Description
AddDbContext<TDbContext>() Registers a DbContext whose DbSet<T> entities marked with [TraxQueryModel] are exposed as GraphQL queries. See query models.
AddTypeModule<TTypeModule>() Registers an additional HotChocolate TypeModule on the Trax schema. Use this to add custom resolvers, DataLoader-backed relationship fields, or ObjectTypeExtensions on entities already registered by [TraxQueryModel]. The module is registered as a singleton in DI.
AddFilterType<TEntity, TFilter>() Overrides the auto-generated FilterInputType for a specific entity. TFilter must extend FilterInputType<TEntity>. See custom filter and sort types.
AddSortType<TEntity, TSort>() Overrides the auto-generated SortInputType for a specific entity. TSort must extend SortInputType<TEntity>. See custom filter and sort types.
AddTypeExtension<T>() Registers a single HotChocolate type extension class (e.g., a class decorated with [ExtendObjectType]) on the Trax schema. T must be a class. Use this for explicit per-type registration.
AddTypeExtensions(params Assembly[]) Scans the given assemblies for all non-abstract classes decorated with [ExtendObjectType] and registers them on the Trax schema. Mirrors the AddMediator assembly-scanning pattern: add a new type extension class and it’s auto-discovered.
ConfigureSchema(Action<IRequestExecutorBuilder>) Applies arbitrary configuration to the underlying HotChocolate IRequestExecutorBuilder. Use this for settings that Trax doesn’t expose directly (cost analysis options, custom conventions, error handling, etc.). Callbacks run after all standard Trax configuration.

All builder methods return the builder for fluent chaining.

UseTraxGraphQL

public static WebApplication UseTraxGraphQL(
    this WebApplication app,
    string routePrefix = "/trax/graphql",
    Action<IEndpointConventionBuilder>? configure = null
)
Parameter Type Required Default Description
app WebApplication Yes N/A The built application
routePrefix string No "/trax/graphql" The URL path where the GraphQL endpoint is mapped
configure Action<IEndpointConventionBuilder>? No null Optional callback to apply endpoint conventions (authorization, rate limiting, CORS) to the GraphQL endpoint.

Returns: WebApplication for continued chaining.

UseTraxGraphQL calls app.UseWebSockets() internally to enable the WebSocket transport required for GraphQL subscriptions.

What It Registers

AddTraxGraphQL calls AddTraxApi() internally (shared API services), then configures HotChocolate:

  • Named GraphQL server via AddGraphQLServer("trax"), using a named schema so it coexists with your own HotChocolate schemas in the same application
  • Query type: RootQuery with grouped sub-types:
    • operations (OperationsQueries): always present. Predefined operational queries: health status, registered trains discovery, manifests, manifest, manifestGroups, executions, execution
    • discover (DiscoverQueries): present when trains annotated with [TraxQuery] are registered, or when entities annotated with [TraxQueryModel] are discovered via AddDbContext<T>(). Contains auto-generated typed query fields for each query train, and paginated/filterable/sortable fields for each query model.
  • Mutation type: RootMutation with grouped sub-types:
    • operations (OperationsMutations): always present. triggerManifest, disableManifest, enableManifest, cancelManifest, triggerGroup, cancelGroup, triggerManifestDelayed
    • dispatch (DispatchMutations): only present when trains annotated with [TraxMutation] are registered. Auto-generated typed mutations with strongly-typed input objects derived from each train’s input record. Each train gets a single mutation field (e.g. banPlayer) with an optional mode: ExecutionMode parameter when both Run and Queue operations are enabled (the default).
  • Subscription type: LifecycleSubscriptions, providing real-time lifecycle events via WebSocket (onTrainStarted, onTrainCompleted, onTrainFailed, onTrainCancelled)
  • In-memory subscription transport: HotChocolate’s built-in pub/sub for delivering events to WebSocket clients
  • Error filter: TraxErrorFilter, which exposes actual exception messages for train-related errors instead of HotChocolate’s default “Unexpected Execution Error”. Exposed types: TrainException (code: TRAX_TRAIN_ERROR), TrainAuthorizationException (code: TRAX_AUTHORIZATION), InvalidOperationException (code: TRAX_INVALID_OPERATION). All other exception types retain the default masked message.
  • Lifecycle hook: GraphQLSubscriptionHook, automatically registered to publish train state transitions to the subscription transport

Prerequisites

AddTraxGraphQL depends on services registered by AddMediator() (provides ITrainDiscoveryService and ITrainExecutionService) and a configured data context (provides IDataContextProviderFactory). These are normally set up through AddTrax.

AddTraxGraphQL performs a runtime check that AddTrax() was called first. If the TraxMarker singleton is not found in the DI container, AddTraxGraphQL throws InvalidOperationException:

InvalidOperationException: AddTrax() must be called before AddTraxGraphQL().
Call services.AddTrax(...) in your service configuration before calling AddTraxGraphQL().

This makes sure the required Trax services are available before the GraphQL schema is built.

Example

var builder = WebApplication.CreateBuilder(args);

builder.Services
    .AddTrax(trax => trax
        .AddEffects(effects => effects
            .UsePostgres(builder.Configuration.GetConnectionString("TraxDatabase")!)
        )
        .AddMediator(ServiceLifetime.Scoped, typeof(Program).Assembly)
    )
    .AddTraxGraphQL();

var app = builder.Build();

app.UseTraxGraphQL(); // serves at /trax/graphql

app.Run();

To serve the endpoint at a different path:

app.UseTraxGraphQL(routePrefix: "/api/graphql");

With authorization:

app.UseTraxGraphQL(configure: endpoint => endpoint
    .RequireAuthorization("AdminPolicy"));

Package

dotnet add package Trax.Api.GraphQL

Back to top

Trax - A .NET framework for Railway Oriented Programming with Effects, Scheduling, and more