RabbitMQ
EasyNetQ
HelloWorld Example
Object Transmission
Cross-Application Communication

HelloWorld example for sending an object over RabbitMQ via EasyNetQ between two different applications

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

To send an object between two different .NET applications with RabbitMQ and EasyNetQ, both applications need to agree on the message contract and connect to the same broker. One app publishes the object, and the other subscribes to that object type and processes incoming messages.

Define a Shared Message Contract

The publisher and consumer should reference the same message type, usually from a small shared class library. That avoids serialization mismatches and keeps routing consistent.

csharp
1namespace SharedMessages;
2
3public class HelloWorldMessage
4{
5    public string Text { get; set; } = "";
6    public DateTime SentAtUtc { get; set; }
7}

This contract should stay versioned and stable. Once multiple applications depend on it, changing the shape casually can break consumers.

Publisher Application

With current EasyNetQ versions, the bus is typically created from a service collection. The publisher resolves IPubSub and sends the message.

csharp
1using EasyNetQ;
2using Microsoft.Extensions.DependencyInjection;
3using SharedMessages;
4
5var services = new ServiceCollection();
6services.AddEasyNetQ("host=localhost");
7
8await using var provider = services.BuildServiceProvider();
9var pubSub = provider.GetRequiredService<IPubSub>();
10
11var message = new HelloWorldMessage
12{
13    Text = "Hello from publisher",
14    SentAtUtc = DateTime.UtcNow
15};
16
17await pubSub.PublishAsync(message);
18Console.WriteLine("Published");

That is enough for a simple publish-subscribe example when RabbitMQ is running locally.

Consumer Application

The receiving application also connects to the same broker and subscribes to the same message type with a stable subscription identifier.

csharp
1using EasyNetQ;
2using Microsoft.Extensions.DependencyInjection;
3using SharedMessages;
4
5var services = new ServiceCollection();
6services.AddEasyNetQ("host=localhost");
7
8await using var provider = services.BuildServiceProvider();
9var pubSub = provider.GetRequiredService<IPubSub>();
10
11await pubSub.SubscribeAsync<HelloWorldMessage>(
12    "hello-world-consumer",
13    async message =>
14    {
15        Console.WriteLine($"Received: {message.Text} at {message.SentAtUtc:O}");
16        await Task.CompletedTask;
17    });
18
19Console.WriteLine("Listening. Press Enter to exit.");
20Console.ReadLine();

The subscription ID matters because EasyNetQ uses it to manage the queue binding for that subscriber.

Run the Example Across Two Applications

The flow is:

  1. start RabbitMQ
  2. run the consumer app
  3. run the publisher app
  4. observe the object arriving in the consumer

If the consumer is not running yet, RabbitMQ and EasyNetQ behavior depends on the exchange and queue configuration created by the subscription side. For a first example, start the consumer first so the queue exists and the wiring is easy to reason about.

Keep Serialization and Contracts Simple

For cross-application messaging, simple DTO-style messages work best:

  • primitive fields
  • timestamps
  • identifiers
  • small nested objects only when necessary

Avoid sending domain entities with behavior, database connections, or framework-heavy types. A message contract should be portable and serialization-friendly.

Add Basic Operational Safety

Even a Hello World example should point toward production-safe habits:

  • use a dedicated shared contract assembly
  • keep subscription IDs stable
  • log publish and receive failures
  • think about versioning before changing message fields

That turns a demo into something you can evolve without rewriting from scratch later.

Common Pitfalls

  • Defining the message class differently in the publisher and consumer projects.
  • Using different broker connection strings across the two applications.
  • Changing the message contract without coordinating both sides.
  • Forgetting that the subscription ID influences queue identity and consumer behavior.
  • Treating demo code as production-ready without adding error handling and versioning discipline.

Summary

  • Share one message contract between the two applications.
  • Publish the object through EasyNetQ from the sender application.
  • Subscribe to the same message type in the receiver application.
  • Use a stable subscription ID and the same RabbitMQ broker configuration on both sides.
  • Keep the message DTO simple so cross-application serialization stays reliable.

Course illustration
Course illustration

All Rights Reserved.