Skip to content

Query Proxy Generation

The proxy generator creates TypeScript query classes that provide type-safe query execution with React hook integration.

Queries can be implemented using two approaches, both of which are supported by the proxy generator:

  • Controller-based: Queries in ASP.NET Core controllers using [HttpGet] attributes
  • Model-bound: Simplified approach where a type represents the query directly

For detailed information on implementing queries, see the Queries documentation.

The generator supports three types of queries:

TypeDescriptionUse Case
Single modelReturns a single objectFetching a specific entity by ID
EnumerableReturns an array of objectsListing or searching entities
ObservableReal-time updates via WebSocketsLive data feeds, dashboards

The generator discovers controller-based queries by looking for:

  • Methods marked with [HttpGet]
  • Return types that indicate the query type:
    • Single object → Single model query
    • IEnumerable<T>, List<T>, etc. → Enumerable query
    • IObservable<T> → Observable query

See Controller-based Queries for implementation details.

The generator discovers model-bound queries by finding types that:

  • Are decorated with the [ReadModel] attribute
  • Have static methods that constitute query operations

Each static method on the read model becomes a separate query. The method name becomes the query name, and method parameters (excluding injected dependencies) become the query parameters in the generated TypeScript.

See Model-bound Queries for implementation details.

Generated query classes provide:

  • Type-safe parameter handling through an interface
  • React hooks for integration (useQuery or useObservableQuery)
  • The proper route based on the configuration

For each query, the generator creates:

  1. Parameters Interface: An IQueryNameParameters interface (if the query has parameters)
  2. Query Class: Extends QueryFor<TResult> or ObservableQueryFor<TResult>
  3. Route: The HTTP route derived from the controller route or model-bound configuration

Depending on the query type, the generated class extends:

Query TypeBase Class
Single modelQueryFor<TModel>
EnumerableQueryFor<TModel[]>
ObservableObservableQueryFor<TModel>

To exclude specific controller-based queries from proxy generation, mark them with the [AspNetResult] attribute. This is useful when you want to handle the response manually or when the query returns a non-standard result.

The generated route is affected by the CratisProxiesSkipQueryNameInRoute configuration option:

  • When false (default): The query type name is included in the route
  • When true: The query type name is excluded from the route

Automatic Conflict Detection: When CratisProxiesSkipQueryNameInRoute is true, the proxy generator automatically detects if multiple query methods exist in the same namespace (after skipping segments). If a conflict is detected, the query name is automatically included in the route to prevent route collisions. This behavior is consistent with the runtime endpoint mapping.

For example:

  • Single query in namespace: Route is clean without type name (e.g., /api/products)
  • Multiple queries in same namespace: Type names are added automatically (e.g., /api/products/get-all, /api/products/get-by-category)

See Configuration for more details on route configuration options.

The generated query proxies integrate with React through the use() static method, which returns a query result object containing:

  • data: The query result (typed according to the return type)
  • isLoading: Loading state indicator
  • error: Any error that occurred
  • Additional state depending on query type

For observable queries, the result also includes connection state information.

For frontend usage patterns, see the @cratis/arc documentation.