This sample demonstrates the basics of sending and receiving messages with the IBM MQ transport. A send-only Sender endpoint dispatches MyMessage commands to a Receiver endpoint, which processes each message with a simulated delay.
The sample includes:
- A Sender console application configured as a send-only endpoint that sends a user-specified number of messages
- A Receiver console application that processes incoming messages
- A Shared library containing the message contract
Prerequisites
The sample requires a running IBM MQ broker. A Docker Compose file is included:
docker compose up -d
This starts IBM MQ with queue manager QM1 on port 1414. The management console is available at https:/ (credentials: admin / passw0rd).
Running the sample
- Start the Receiver project first. It calls
EnableInstallers()on startup, which creates any missing queues automatically. - Start the Sender project.
- Enter a number in the Sender console and press Enter. That many
MyMessagecommands are sent to the Receiver. - The Receiver logs
Startwhen each message begins processing, then<data> End:after a simulated 200 ms delay.<data>
Code walk-through
Sender configuration
Both endpoints initialise an IBMMQTransport instance with the connection details for the local broker:
var ibmmq = new IBMMQTransport()
{
QueueManagerName = "QM1",
Host = "localhost",
Port = 1414,
Channel = "DEV.ADMIN.SVRCONN",
User = "admin",
Password = "passw0rd"
};
var endpointB = new EndpointConfiguration("DEV.SENDER");//upper case by convention for queues in IBM MQ
endpointB.SendFailedMessagesTo("error");
endpointB.UseTransport(ibmmq);
endpointB.UseSerialization<SystemJsonSerializer>();
// the Sender sends messages invoking SendOnly results and no receive infrastructure will be set up
endpointB.SendOnly();
builder.UseNServiceBus(endpointB);
The connection properties correspond to the Docker Compose defaults: queue manager QM1, host localhost, port 1414, channel DEV.. The Sender is also configured with SendOnly(), which prevents NServiceBus from creating an input queue for the Sender process.
Creating a message
The message being sent is the following record type, inheriting IMessage type from NServiceBus. This sample uses a record type but NServiceBus supports interfaces and classess as message types.
public record MyMessage(string Data) : IMessage;
Sending a message
var message = new MyMessage(Data: "MyData");
Console.WriteLine($"Sending message: {message}");
await instance.Send("DEV.RECEIVER", message);
Receiver configuration
var endpointB = new EndpointConfiguration("DEV.RECEIVER");
endpointB.UseTransport(ibmmq);
endpointB.UseSerialization<SystemJsonSerializer>();
endpointB.EnableInstallers();
// Delayed retries must be disabled as the IBM MQ transport does not support them
endpointB.Recoverability().Delayed(settings => settings.NumberOfRetries(0));
builder.UseNServiceBus(endpointB);
EnableInstallers() creates the DEV. queue on the broker if it does not already exist. Delayed retries are disabled so that any processing failures move messages directly to the error queue without cycling through retry delays.
Message handler
sealed class MyHandler : IHandleMessages<MyMessage>
{
public async Task Handle(MyMessage message, IMessageHandlerContext context)
{
Console.WriteLine($"Start {message.Data}");
await Task.Delay(200, context.CancellationToken);
Console.WriteLine($"End: {message.Data}");
}
}
MyHandler simulates a 200 ms processing delay. The CancellationToken from context. is forwarded to Task. so the handler responds promptly to endpoint shutdown.