Skip to content

AspNetCore Expo Validation

SteffenBlake edited this page Sep 28, 2026 · 1 revision

Expo validation in ASP.NET Core

[ExpoSystemBundle] validates bound Partie requests before they reach your handlers. A failed request returns an Error containing Expo's field failures. With HTTP result mapping around validation, the response uses HTTP 400.

Install the integration

Install Brigade.Net.Expo and Brigade.Net.Expo.Engines.Domain in the model project. In the project that declares routes, add:

dotnet add package Brigade.Net.Partie.Extensions.Expo

Set up Partie's ASP.NET Core packages and generated routes as described in CQRS routing with Partie.

Register validation

[BrigadeGroup("/api/v1")]
[AspNetSystemBundle]
[PartieSystemBundle]
[ExpoSystemBundle]
public static partial class ApiRoutes
{
    ...
}

[ExpoSystemBundle] is in Brigade.Net.Partie.Extensions.Expo and contains ExpoValidationPartie<TRequest, TResult>. It matches both query and command requests implementing IExpoValidatable. Requests without that contract skip this validation step.

This order places HTTP mapping outside validation and validation inside the command unit of work. A validation failure skips later steps and the handler, returns through HTTP mapping, and causes command rollback. Steps registered before validation can already have run.

Use the bundle once at the intended scope. Registering [ExpoValidationPartie] again inside the same scope repeats the step. See ASP.NET Core bundles.

Validate the request and its payload

// CourseRegistrationCmd.cs
[Expo]
public sealed partial class CourseRegistrationCmd
{
    [FromPath]
    [IsGreaterThan(0)]
    public int CourseId { get; init; }

    [FromPayload]
    [IsRequired("A registration payload is required.")]
    public CourseRegistration? Body { get; init; }
}

CourseRegistration is defined in Validation models. Mark the outer request with [Expo] as well as its nested payload. The Partie step matches the request contract, then Expo cascades into the payload.

A malformed path or JSON body can fail during binding before Expo runs. Successfully bound input is then checked against the model rules. See Request binding.

Failure responses

An invalid payload email produces an error pointer such as /Body/StudentEmail. ExpoValidationPartie returns new Error(errors); the outer HTTP mapper chooses HTTP 400 because the error does not set a status explicitly. The serialized failure includes the field details.

Custom validation exceptions propagate rather than becoming ordinary field errors. Use returned messages for expected invalid input.

Runtime validation and API documentation are configured separately. Add Expo OpenAPI to publish constraints to consumers.

Clone this wiki locally