Repository navigation
Partie Handlers
A handler runs one application operation and returns Result<TResult>. Its contract names the request, result, and context types. Partie supplies the context and bound request to a static RunAsync method.
Use IQueryHandler<TQuery, TResult, TContext> for an operation that reads data. A context with [Inject] lets the handler call an application service registered with dependency injection:
// CourseSearchHandler.cs
public sealed record CourseSearchContext([Inject] ICourseCatalog Catalog);
public sealed class CourseSearchHandler :
IQueryHandler<CourseSearchQuery, CourseSearchResult, CourseSearchContext>
{
public static async Task<Result<CourseSearchResult>> RunAsync(
CourseSearchContext context,
CourseSearchQuery query,
CancellationToken cancellationToken
)
{
var course = await context.Catalog.FindAsync(query.CourseId, cancellationToken);
if (course is null)
{
return new NotFound("Course not found.");
}
return new CourseSearchResult(course.Id, course.Title);
}
}The example assumes ICourseCatalog.FindAsync returns a nullable course with Id and Title. Define the public response separately:
// CourseSearchResult.cs
public sealed record CourseSearchResult(int CourseId, string Title);See Requests for CourseSearchQuery.
Use ICommandHandler<TCommand, TResult, TContext> for an operation that changes application state. The method receives a UnitOfWork before its context:
// CourseCreateHandler.cs
public sealed record CourseCreateContext([Inject] ICourseCatalog Catalog);
public sealed class CourseCreateHandler :
ICommandHandler<CourseCreateCmd, int, CourseCreateContext>
{
public static async Task<Result<int>> RunAsync(
UnitOfWork unitOfWork,
CourseCreateContext context,
CourseCreateCmd command,
CancellationToken cancellationToken
)
{
var courseId = await context.Catalog.CreateAsync(
command.Body.Title,
command.Body.Capacity,
cancellationToken
);
return courseId;
}
}Here, CreateAsync is an application service method that returns the new ID. Register [PartieSystemBundle] to supply the unit of work. The service's changes participate in it only when the service uses an enlisted transactional resource. See Unit of work.
Use Unit as the context when the handler needs no supplied values. Use Unit as the result when a successful command returns no data:
return Unit.Default;The result carries completion without a response value. See Results for success and failure cases.
RunAsync must be static and non-generic, with the exact Task<Result<TResult>> return type. It may be public or an explicit static interface implementation. Use async when you need to await work; a synchronous implementation can return Task.FromResult<Result<TResult>>(value).
Pass the supplied cancellation token to database calls and other asynchronous services. Partie passes the invocation token through the pipeline. Exceptions and cancellation propagate through surrounding Parties and the framework; returning a failure is how you report an expected application outcome.
The handler is called through its static contract. Put runtime dependencies in Contexts rather than an instance constructor.
- 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