In a distributed system built around bounded contexts, services cannot share a database or call each other’s internal application layer directly. They communicate through an integration bus — a durable message broker that decouples the sender from all consumers. TheDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/jordiaragonzaragoza/JordiAragonZaragoza.SharedKernel/llms.txt
Use this file to discover all available pages before exploring further.
JordiAragonZaragoza.SharedKernel.Presentation.Integration package wires up MassTransit over RabbitMQ as the integration bus. It provides strongly-typed producer buses for publishing events, sending commands, and executing request/response queries across service boundaries, as well as base consumer classes and a dynamic consumer-registration mechanism so each bounded context only subscribes to the messages it cares about.
Packages
Presentation.Integration
MassTransit wiring, producer buses, consumer base classes, and DI registration. Referenced by your service host.
Presentation.Integration.Contracts
Consumer interfaces (
IIntegrationEventHandler<T>, IIntegrationCommandHandler<T>) and IBaseIntegrationMessageHandler<T>. Safe to reference from domain or application contract assemblies.Full Setup Flow
Add RabbitMQ configuration to appsettings.json
The library reads its configuration from the
MassTransit:IntegrationBus section. At minimum you must supply the RabbitMQ connection URL.Register consumers (optional, per-service)
Before calling
AddSharedKernelPresentationIntegrationBusRegistrations, register a MassTransitIntegrationBusConsumersRegistrationConfigurator that wires up the consumers your service needs.Register the integration bus
Call
AddSharedKernelPresentationIntegrationBusRegistrations with the logical name of your service. This name is used as the RabbitMQ connection name for observability.Configuration
MassTransitIntegrationBusOptions
Bound from the MassTransit:IntegrationBus configuration section. The RabbitMq property is required and validated at startup.
| Property | Required | Default | Description |
|---|---|---|---|
RabbitMq | ✅ | — | RabbitMQ connection options (see below). |
MaximumConcurrencyLevel | ❌ | null | Caps concurrent message processing per consumer. null uses MassTransit’s default. |
NumberOfRetries | ❌ | 2 | Number of delivery retries before a message moves to the error queue. |
RabbitMqOptions
| Property | Required | Description |
|---|---|---|
Url | ✅ | Full AMQP URI, e.g. amqp://user:pass@rabbitmq-host:5672 |
DI Registration
MassTransitDependencyInjection.AddSharedKernelPresentationIntegrationBusRegistrations
- Binds and validates
MassTransitIntegrationBusOptionsfrom configuration. - Registers a default
MassTransitIntegrationBusConsumersRegistrationConfigurator(no-op) if one was not already added. - Calls
AddMassTransit<IIntegrationBus>to create a named bus (IIntegrationBus) separate from any in-process bus (IBus) your application layer may already have — this is MassTransit’s MultiBus pattern. - Configures RabbitMQ as the transport using the URL from options, sets the connection name to
targetHostName, and applies kebab-case endpoint naming. - Runs the caller-supplied consumer configuration via
MassTransitIntegrationBusConsumersRegistrationConfigurator.
The bus starts automatically because
AutoStart = true is set on the RabbitMQ factory configurator.IIntegrationBus
A marker interface that extends MassTransit’s IBus. It is required for the MultiBus pattern so MassTransit can inject the correct bus instance when multiple buses are registered in one host.
IIntegrationBus directly. Instead inject IIntegrationEventBus, IIntegrationCommandBus, or IIntegrationQueryBus from your application layer.
Producer Buses
MassTransitIntegrationEventBus
Implements IIntegrationEventBus. Publishes an integration event to all subscribers via MassTransit’s IPublishEndpoint, stamps DateDispatchedOnUtc, and logs at Debug level on success and Error level on failure.
MassTransitIntegrationCommandBus
Implements IIntegrationCommandBus. Uses MassTransit’s request-client pattern to send a command and await a Result (or Result<TResponse>) reply.
MassTransitIntegrationQueryBus
Implements IIntegrationQueryBus. Uses the MassTransit request-client to send a query and await a Result<TResponse> reply.
Consumer Interfaces
IBaseIntegrationMessageHandler<TIntegrationMessage>
The lowest-level contract: a single HandleAsync method that must be implemented for any message type.
IIntegrationEventHandler<TEvent>
Combines IBaseIntegrationMessageHandler<TEvent> with MassTransit’s IConsumer<TEvent> so the type is both a domain-level handler and a registered MassTransit consumer.
IIntegrationCommandHandler<TCommand>
Same pattern for integration commands.
BaseIntegrationEventHandler<TEvent>
An abstract class that implements IIntegrationEventHandler<TEvent>. It handles the MassTransit Consume contract by unwrapping the ConsumeContext<TEvent> and delegating to the abstract HandleAsync method that you implement.
HandleAsync:
MassTransitIntegrationBusConsumersRegistrationConfigurator
Carries an Action<IBusRegistrationConfigurator> delegate that is applied during bus setup. This avoids registering all consumers from all assemblies on every bus — each service host provides only the consumers it needs.
Register the
MassTransitIntegrationBusConsumersRegistrationConfigurator singleton before calling AddSharedKernelPresentationIntegrationBusRegistrations. The DI setup reads it from the service provider during bus configuration.End-to-End Example
The following example shows a complete cross-service flow: the Orders service publishes anOrderCreatedIntegrationEvent and the Inventory service consumes it.
1. Define the integration event (shared contracts assembly)
2. Publish from the Orders service
3. Consume in the Inventory service
4. Wire up the Inventory service Program.cs
Architecture Notes
Why a separate IIntegrationBus and not the default IBus?
Why a separate IIntegrationBus and not the default IBus?
SharedKernel follows MassTransit’s MultiBus pattern. Your application layer may already use an in-process MassTransit bus (bound to
IBus) for dispatching domain events. The integration bus is a separate RabbitMQ-backed bus bound to IIntegrationBus. Using Bind<IIntegrationBus, T> in the producer constructors ensures MassTransit resolves the correct publish endpoint and client factory for the integration bus, not the in-process bus.Why integration commands are discouraged
Why integration commands are discouraged
The
IIntegrationCommandHandler interface documentation explicitly warns: a bounded context should not consume commands from another bounded context to enforce state changes. Commands imply ownership and intent. Sending a command from Service A to Service B means Service A is dictating what Service B must do — creating tight behavioral coupling. Prefer publishing an event from Service A and letting Service B react to it autonomously.