C4 Level 3 — API Layer Components
Internal structure of the REST API container: how a request flows from controller through the MediatR pipeline into the domain and back.
C4Component
title REST API — Component View
Container_Boundary(api, "REST API (.NET 8)") {
Component(middleware, "Middleware Pipeline", "ASP.NET Core", "GlobalException → RequestId → Localisation → Authentication → TenantResolution → TokenBlacklist → Authorization → RateLimiter → Idempotency → ETag")
Component(controllers, "Controllers (23)", "ASP.NET Core", "AuthController, BouquetsController, CartController, OrdersController, CustomerBouquetsController, VendorOrdersController, FavouritesController, SubscriptionsController, NotificationsController, ProfileController, SmartVasesController, AnalyticsController, AdminController, EmployeesController, PublicVendorsController, BouquetFeedbackController, StripeWebhookController, ...")
Component(behaviors, "MediatR Pipeline Behaviours", "MediatR", "ValidationBehavior (FluentValidation), LoggingBehavior, TenantValidationBehavior, CachingBehaviour")
Component(handlers, "Command/Query Handlers", "MediatR", "35+ handlers — one per command or query, scoped by domain")
Component(domain, "Domain Aggregates (14)", "DDD", "Vendor, Bouquet, SmartVase, Order, Cart, Customer, Employee, Favourite, Subscription, Notification, BouquetFeedback, DeviceRegistration, SavedAddress, User")
Component(repos, "Repository Implementations (14)", "EF Core", "One per aggregate — wraps DbContext, enforces tenant scope")
Component(infra, "Infrastructure Services", ".NET", "KeycloakAdminClient, StripeService, RedisCacheService, MqttDeviceCommunicationService, BouquetHub (SignalR), OutboxDispatcherService, EmailService, TwilioSmsVerificationService, QrCodeGeneratorService, NominatimGeocodingService")
Component(outbox, "Outbox Pattern", "EF Core + BackgroundService", "EfOutboxWriter (writes on commit) → OutboxDispatcherService (dispatches to InMemoryEventBus)")
}
ContainerDb(postgres, "PostgreSQL")
ContainerDb(redis, "Redis")
Rel(middleware, controllers, "Passes authenticated + tenant-scoped request")
Rel(controllers, behaviors, "ISender.Send(command/query)")
Rel(behaviors, handlers, "Validated + logged + cached request")
Rel(handlers, domain, "Domain methods, Result(T)")
Rel(handlers, repos, "IRepository(T) — read/write")
Rel(handlers, infra, "External service calls")
Rel(handlers, outbox, "EfOutboxWriter.Write() on domain events")
Rel(repos, postgres, "EF Core DbContext")
Rel(infra, redis, "RedisCacheService")
Rel(outbox, infra, "InMemoryEventBus.Publish()")
Request Lifecycle
sequenceDiagram
participant Client
participant MW as Middleware Pipeline
participant Ctrl as Controller
participant MediatR
participant Handler
participant Domain
participant Repo
participant DB as PostgreSQL
Client->>MW: HTTP Request
MW->>MW: GlobalException → RequestId → Localisation → Authentication → TenantResolution → TokenBlacklist → Authorization → Idempotency
MW->>Ctrl: Authenticated + tenant-scoped HttpContext
Ctrl->>MediatR: ISender.Send(command)
MediatR->>MediatR: ValidationBehavior (FluentValidation)
MediatR->>MediatR: LoggingBehavior
MediatR->>MediatR: TenantValidationBehavior
MediatR->>Handler: Handle(command, ct)
Handler->>Repo: GetByIdAsync / FindAsync
Repo->>DB: SELECT
DB-->>Repo: Entity
Repo-->>Handler: Aggregate
Handler->>Domain: aggregate.DoSomething()
Domain-->>Handler: Result(T)
Handler->>Repo: UnitOfWork.SaveChangesAsync()
Repo->>DB: INSERT/UPDATE + OutboxMessage
Handler-->>Ctrl: Result(T)
Ctrl-->>Client: HTTP 200/201/400/409