Skip to content

Commands

Opening an account or adding a cart line should not require a handwritten HTTP client and repeated endpoint boilerplate. In Arc, a command carries the input for an operation and can handle itself. Arc supplies the endpoint, command result, and generated TypeScript proxy.

Arc is a standalone CQRS framework. Your handler can call application services backed by any suitable storage; it does not have to return an event or use Chronicle.

POST

Client

Arc endpoint

Authorization then validation

Provide and Handle

Response processing

CommandResult

This is a declaration fragment using the shared CartLineId, Sku, and Quantity concepts and fully implemented ICartService from the model-bound command example:

using Cratis.Arc.Commands.ModelBound;
[Command]
public record AddItemToCart(Sku Sku, Quantity Quantity)
{
public CartLineId Handle(ICartService carts) => carts.AddItem(Sku, Quantity);
}

Arc discovers the public instance Handle() on the [Command] record. It resolves ICartService from the command scope, waits for the operation, and places the CartLineId in the response. Follow the linked example for the service implementation, registration, and an execution checkpoint.

Choose the return shape that fits the operation:

  • void or Task — no response value. A task is awaited; this is not fire-and-forget execution.
  • A value or Task<T> — an unhandled value becomes the typed response.
  • An operation or CommandOperations — declare one or many server-side actions, with optional compensation.
  • A tuple — combine one response with command operations and other values consumed by response value handlers.
  • Cratis.Monads.Result<TSuccess, TError> — process the active alternative. A recognized validation value becomes a rejection; arbitrary error types are not automatically failures.

Use provided data when fetching handler input separately makes the operation clearer.

StyleChoose it when
Model-boundYou want input and behavior together with minimal endpoint boilerplate.
Controller-basedYou need MVC action control or are integrating existing controllers.

The model-bound pipeline and MVC action filters are different execution paths. Do not assume extensions or authorization attributes for one automatically govern the other.

Next concernRead
Validate inputValidation
Protect commandsModel-bound authorization
Check without invoking the handlerPre-flight validation
Execute from application codeCommand pipeline
Keep inline side effects out of the decisionCommand operations · Testing operations
Understand scalar and tuple responsesResponse value handlers · Examples
Carry cross-cutting dataCommand context
Extend executionFilters · Execution scopes

If your application uses event sourcing, Chronicle command integration adds returned-event handling. Its transactional command behavior belongs to that integration, not standalone Arc. You do not need it for service-backed commands or Guid responses.

The proxy generator generates the TypeScript command contract from the backend. After building the backend, use commands in React to submit it and inspect the result. Continue to queries to read the data your commands change.