Building Blocks Shared Library
Relevant source files
The following files were used as context for generating this wiki page:
- BuildingBlocks/BuildingBlocks.Application/BuildingBlocksServiceCollectionExtensions.cs
- BuildingBlocks/BuildingBlocks.Enumerations/ErrorCode.cs
- BuildingBlocks/BuildingBlocks.Infrastructure.Auth/AuthExtensions.cs
- BuildingBlocks/BuildingBlocks.Tests/TestBase.cs
- BuildingBlocks/BuildingBlocks.Tests/EfCoreUnitOfWorkTests.cs
- claude.md
The Building Blocks Shared Library serves as the foundational infrastructure for the DDD & Event-Driven Architecture learning project. It provides reusable components, base classes, and cross-cutting concerns that are utilized across multiple bounded contexts, such as Scheduling and Billing.
The library is designed to enforce tactical Domain-Driven Design (DDD) patterns and maintain consistency in how services are registered, how authentication is handled, and how integration tests are structured. It encapsulates shared logic for persistence (EF Core), messaging (MassTransit/Wolverine), and security (OIDC/IdentityServer).
Sources: claude.md:5-18, claude.md:129-140
Application Layer and Pipeline Behaviors
The library provides a centralized way to register MediatR handlers and FluentValidation validators for each bounded context. It also defines a specific execution order for MediatR pipeline behaviors to ensure cross-cutting concerns like logging and transactions are handled consistently.
The diagram shows the registration order of MediatR pipeline behaviors. Transactions are wrapped around all other behaviors to ensure validators with database access run within the same transaction scope.
Key Service Registration Methods
| Method | Description |
|---|---|
AddBoundedContext | Registers MediatR handlers and FluentValidation validators for a specific assembly. Also sets FluentValidation global defaults. |
AddDefaultPipelineBehaviors | Registers the standard execution pipeline: Transaction -> Logging -> Validation -> Performance -> UnhandledException. |
Sources: BuildingBlocks/BuildingBlocks.Application/BuildingBlocksServiceCollectionExtensions.cs:23-53
Authentication and Security
The library implements a robust security infrastructure based on the BFF (Backend for Frontend) pattern. It utilizes Cookie Authentication combined with OpenID Connect (OIDC) to secure Web APIs without exposing tokens to the frontend application.
OIDC Configuration Flow
The AddOidcCookieAuth extension method configures how the application interacts with an Identity Provider (e.g., Duende IdentityServer).
The sequence illustrates the OIDC Authorization Code flow managed by the Building Blocks library.
Shared Data Protection
To allow cookies to be decrypted across different microservices (e.g., Scheduling and Billing), the library configures a shared Data Protection provider. This requires a consistent application name (DDD.WebApis) and a shared key storage path.
Sources: BuildingBlocks/BuildingBlocks.Infrastructure.Auth/AuthExtensions.cs:25-50, BuildingBlocks/BuildingBlocks.Infrastructure.Auth/AuthExtensions.cs:175-185
Domain Modeling and Enumerations
Shared domain concepts are enforced through base classes. The SmartEnum implementation (via Ardalis.SmartEnum) is used to create strongly-typed constants for error codes and statuses.
Error Code Structure
Custom error codes are automatically prefixed with ERR_ for consistency across the system.
| Error Code | Message |
|---|---|
ERR_NOT_FOUND | The requested resource was not found |
ERR_UNAUTHORIZED | Authentication is required |
ERR_FORBIDDEN | You do not have permission to perform this action |
ERR_VALIDATION_FAILED | One or more validation errors occurred |
Sources: BuildingBlocks/BuildingBlocks.Enumerations/ErrorCode.cs:24-60
Persistence and Unit of Work
The library provides a specialized implementation of the Unit of Work pattern using EF Core. This implementation specifically addresses nested transaction scenarios, which are common when one command handler calls another domain service.
Nested Transaction Logic
The EfCoreUnitOfWork tracks transaction depth. A physical database commit only occurs when the depth returns to zero, ensuring that inner scopes do not prematurely commit an outer transaction.
Visual representation of the depth-based transaction management in EfCoreUnitOfWork.
Sources: BuildingBlocks/BuildingBlocks.Tests/EfCoreUnitOfWorkTests.cs:55-140
Testing Infrastructure
The BuildingBlocks.Tests namespace contains base classes that facilitate integration testing with isolated environments.
TestBase Properties
The TestBase<TContext> class provides a standardized environment for testing bounded contexts:
- Isolation: Uses SQLite in-memory databases.
- Transaction Management: Automatically starts a transaction in
TestInitializeand rolls it back inTestCleanup. - Service Access: Provides protected access to
IMediator,IValidator, and theIUnitOfWork.
Sources: BuildingBlocks/BuildingBlocks.Tests/TestBase.cs:26-77
Conclusion
The Building Blocks Shared Library is the backbone of the project's architecture, centralizing the implementation of DDD patterns and infrastructure concerns. By providing standardized pipeline behaviors, a resilient Unit of Work, and unified authentication extensions, it ensures that individual microservices remain focused on their specific business logic while adhering to a consistent system design.