Repository navigation
Getting Started Expo
Expo checks request data against rules on your model and reports which fields fail. Use [Expo] on a request model to generate its validation method.
It is highly recommended that you set up Partie first if you want automatic request binding and validation in the request pipeline.
Install these packages in the project that contains the models you want to validate:
dotnet add package Brigade.Net.Expo
dotnet add package Brigade.Net.Expo.Engines.DomainBrigade.Net.Expo provides the core classes for defining validation on models.
Brigade.Net.Expo.Engines.Domain source generates validation for models marked with [Expo].
For ASP.NET Core APIs, install the Partie integration packages in the project that defines your routes:
dotnet add package Brigade.Net.Partie.Extensions.Expo
dotnet add package Brigade.Net.Partie.Extensions.Expo.Engines.AspNetCoreBrigade.Net.Partie.Extensions.Expo adds automatic Expo validation to Partie routes. Invalid requests receive a Bad Request response before reaching your handlers.
Brigade.Net.Partie.Extensions.Expo.Engines.AspNetCore generates a helper that adds Expo’s validation rules to ASP.NET Core’s OpenAPI documents.
Add [ExpoValidationPartie] to a route group to reject invalid requests on its routes, automatically short circuiting them out into ProblemDetails schema responses with error code 400.
[BrigadeGroup("/api/v1")]
...
[ExpoValidationPartie]
public static partial class RoutingV1
{
...
}With both Parties registered, Expo validates each incoming request. Invalid requests receive HTTP 400 with a ProblemDetails-shaped body containing field errors; the handler does not run.
Add AddExpo() to include Expo constraints in generated OpenAPI schemas:
// Program.cs
// Add Expo validation metadata to generated OpenAPI schemas.
builder.Services.AddOpenApi(options => {
...
options.AddExpo()
...
});OpenAPI shows the constraints to API consumers. [ExpoValidationPartie] enforces them when requests arrive.
// The generator automatically creates the validate logic on any classes marked
[Expo]
public partial class CourseRegistrationCommand
{
// Partie reads the JSON body into this property.
[FromPayload]
[IsRequired("A registration payload is required.")]
public RegistrationPayload? Body { get; init; }
}
[Expo]
public partial class RegistrationPayload
{
// Reject a missing email, then check its format when present.
[IsRequired]
[StringMatchesEmail]
public string? StudentEmail { get; init; }
// Course codes need at least two characters.
[IsRequired]
[StringHasMinimumLength(2)]
public string? CourseCode { get; init; }
}Expo checks nested models too. Each failure identifies the invalid property with a JSON Pointer.
Without Partie, call TryValidate and choose how your application responds to invalid input:
var payload = new RegistrationPayload
{
StudentEmail = "student@example.edu",
CourseCode = "BIO101"
};
// TryValidate returns every failed rule for this object.
if (!payload.TryValidate(out var errors))
{
foreach (var error in errors)
{
Console.WriteLine($"{error.Pointer}: {error.Detail}");
}
}Check out installing the Mise system for Database ORM integration!
See the Expo guide for custom rules, generated property comparisons and regex rules, collections, nested validation, and error metadata. The repository’s example request shows Expo and Partie binding attributes on the same request model.
- Home
- Getting started
-
Package guides
- Partie
- Expo
-
Mise
- Database setup
- Table mappings
- Aliases
- Relationships
- Result rows
- SQL interpolation
- Queries
- Filtering
- Joins
- Aggregation
- Paging and ordering
- Subqueries
- Set operations
- Common table expressions
- Readers
- Streaming
- Writers
- Inserts
- Updates
- Deletes
- Returned rows
- Custom SQL and procedures
- Transactions
- Resource lifetimes
- Database dialects
- Diagnostics
- Integrations
- Recipes
- Reference
- Troubleshooting
- Development