Pre-flight command validation
A form can ask whether a command is currently acceptable before attempting the change. Arc’s Validate operation returns a CommandResult from pre-flight checks, without running the command handler. It is early feedback, not a reservation or a guarantee that later execution will succeed.
Backend support
Section titled “Backend support”For model-bound commands, inject ICommandPipeline and call Validate. Both a scope-free form and a form accepting an existing IServiceProvider are available, with optional severity and cancellation overloads.
This complete caller uses the service-backed AddItemToCart definition and shared cart concepts. Configure its validators and authorization requirements separately:
using System.Threading.Tasks;using Cratis.Arc.Commands;
public class CartPreflight(ICommandPipeline pipeline){ public Task<CommandResult> Check(Sku sku, Quantity quantity) => pipeline.Validate(new AddItemToCart(sku, quantity));}Await the returned task and inspect IsSuccess for an overall verdict. IsValid alone ignores authorization and exception failures. With no validators, pre-flight does not discover arbitrary checks inside the cart service.
What runs
Section titled “What runs”The model-bound validation path finds the handler, builds context values, establishes a context, and runs command filters. Authorization filters run before ordinary filters, with short-circuiting on unsuccessful results. Applicable severity filtering then determines the remaining validation results.
It skips:
Provide()and handler argument resolution;Handle();- response value handlers;
- execution scopes’
BeginandCompletecallbacks.
Validators can still resolve dependencies and read services. Context providers, custom filters, validators, and their constructors are executable application code: Arc cannot guarantee that they are side-effect free or reveal no sensitive information. Design them for repeated pre-flight calls.
Model-bound endpoints
Section titled “Model-bound endpoints”Arc adds /validate alongside a model-bound command’s execute route. For example, if the mapped execute route is /api/carts/add-item-to-cart, validation is POST /api/carts/add-item-to-cart/validate with the same command payload. The base route depends on namespace/path configuration; it is not inferred from this example URL.
Both endpoints use model-bound command filters. Validation does not run business decisions that exist only in Provide(), Handle(), or a service invoked by them.
Controller-based commands
Section titled “Controller-based commands”With Arc’s MVC integration, [HttpPost] actions with attribute route selectors receive corresponding /validate selectors unless [AspNetResult] opts the action or controller out of command handling. Use a [FromBody] parameter for the command payload, as in the complete controller example.
CommandValidationRouteConvention adds the selector at startup. Requests still go through ASP.NET Core authorization, binding, and the action-filter pipeline; Arc’s CommandActionFilter recognizes the /validate path and skips action execution. These are MVC filters, not the model-bound ICommandFilter chain. Other application middleware and filters may still run.
For the shown controller route:
- Execute:
POST /api/carts/add - Validate:
POST /api/carts/add/validate
If a route is missing, confirm that Arc MVC integration is configured and that the action is recognized as a POST command with an attribute route. Do not assume every arbitrary MVC action receives validation endpoints.
Security and concurrency
Section titled “Security and concurrency”Use authorization verdicts, not overridable validation errors, for access control. Model-bound authorization failures and MVC authorization responses belong to their respective pipelines; do not assume identical HTTP challenge behavior.
Always inspect the result of the eventual Execute call too. State may change between requests, handler-only checks may reject the operation, or a service or execution scope may fail. Enforce concurrency-sensitive invariants in the operation that performs the change.
Frontend usage
Section titled “Frontend usage”Use core command validation or React command validation for pre-flight feedback. For warning confirmation, use an explicit warning-blocking first threshold as described in severity filtering.