-
Notifications
You must be signed in to change notification settings - Fork 12
Cookbook and Scenarios
This page provides practical, recipe-style solutions for common scenarios you might encounter when building applications with LiteBus.
Problem: You need to process the same command differently based on where the request came from. For example, a command from a public API needs stricter validation than one from an internal admin tool.
Solution: Use handler tags to create context-specific pipelines.
Create a static class to hold your context tags. This avoids magic strings.
public static class RequestContexts
{
public const string PublicApi = "PublicAPI";
public const string AdminPortal = "AdminPortal";
}Apply the [HandlerTag] attribute to handlers that should only run in a specific context.
// This validator only runs for requests from the public API.
[HandlerTag(RequestContexts.PublicApi)]
public class StrictUserUpdateValidator : ICommandValidator<UpdateUserCommand>
{
public Task ValidateAsync(UpdateUserCommand command, CancellationToken cancellationToken)
{
// Public API cannot change a user's role.
if (command.Role != null)
{
throw new ValidationException("Role cannot be changed via the public API.");
}
return Task.CompletedTask;
}
}
// This handler is untagged, so it runs for ALL contexts.
public class CommonUserUpdateValidator : ICommandValidator<UpdateUserCommand>
{
public Task ValidateAsync(UpdateUserCommand command, CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(command.Email))
{
throw new ValidationException("Email is required.");
}
return Task.CompletedTask;
}
}When sending the command, specify the context tag.
// In your Public API controller:
[HttpPut("{id}")]
public async Task<IActionResult> UpdateUser(Guid id, UpdateUserCommand command)
{
// Send the command with the "PublicAPI" context.
// This will trigger both the StrictUserUpdateValidator and the CommonUserUpdateValidator.
await _commandMediator.SendAsync(command, RequestContexts.PublicApi);
return NoContent();
}
// In your Admin Portal controller:
[HttpPut("{id}")]
public async Task<IActionResult> UpdateUserFromAdmin(Guid id, UpdateUserCommand command)
{
// Send the command with the "AdminPortal" context.
// This will ONLY trigger the CommonUserUpdateValidator, as the strict validator is not tagged for this context.
await _commandMediator.SendAsync(command, RequestContexts.AdminPortal);
return NoContent();
}Result: You have successfully implemented different validation rules for the same command without if/else logic in your handlers, keeping them clean and focused.
(More recipes can be added here over time, such as "Implementing a Saga," "Cross-cutting Caching," etc.)