Table of Contents

Getting Started

Installation

Add the BareWire packages to your project:

dotnet add package BareWire.Abstractions
dotnet add package BareWire
dotnet add package BareWire.Serialization.Json
dotnet add package BareWire.Transport.RabbitMQ

Define a Message

Messages are plain C# records — no base class or attributes required. Use past tense for events and imperative for commands:

// Event (something that happened)
public record MessageSent(Guid Id, string Content, DateTime SentAt);

// Command (something you want to happen)
public record ProcessPayment(Guid OrderId, decimal Amount);

Create a Consumer

Implement IConsumer<T> to handle messages. Consumers are sealed by convention and receive dependencies via constructor injection:

public sealed class MessageConsumer : IConsumer<MessageSent>
{
    private readonly SampleDbContext _db;
    private readonly ILogger<MessageConsumer> _logger;

    public MessageConsumer(SampleDbContext db, ILogger<MessageConsumer> logger)
    {
        _db = db;
        _logger = logger;
    }

    public async Task ConsumeAsync(ConsumeContext<MessageSent> context)
    {
        _logger.LogInformation("Received: {Content}", context.Message.Content);

        _db.ReceivedMessages.Add(new ReceivedMessage
        {
            Id = context.Message.Id,
            Content = context.Message.Content,
            ReceivedAt = DateTime.UtcNow
        });

        await _db.SaveChangesAsync(context.CancellationToken);
    }
}

See: samples/BareWire.Samples.BasicPublishConsume/Consumers/MessageConsumer.cs

Configure the Bus

Register BareWire in your DI container with the RabbitMQ transport. Topology is manual by default — you declare exchanges, queues, and bindings explicitly:

var builder = WebApplication.CreateBuilder(args);

// Register JSON serializer (raw-first, no envelope)
builder.AddBareWireJsonSerializer();

// Configure BareWire with RabbitMQ
builder.Services.AddBareWire(cfg =>
{
    cfg.UseRabbitMQ(rmq =>
    {
        // Declare topology explicitly
        rmq.ConfigureTopology(topology =>
        {
            topology.DeclareExchange("messages", ExchangeType.Fanout, durable: true);
            topology.DeclareQueue("messages", durable: true);
            topology.BindExchangeToQueue("messages", "messages");
        });

        // Register consumer on an endpoint
        rmq.ReceiveEndpoint("messages", e =>
        {
            e.PrefetchCount = 16;
            e.Consumer<MessageConsumer, MessageSent>();
        });
    });
});

See: samples/BareWire.Samples.BasicPublishConsume/Program.cs

Publish a Message

Inject IPublishEndpoint (or IBus) and call PublishAsync:

app.MapPost("/messages", async (
    MessageRequest request,
    IPublishEndpoint bus,
    CancellationToken ct) =>
{
    var message = new MessageSent(Guid.NewGuid(), request.Content, DateTime.UtcNow);
    await bus.PublishAsync(message, ct);
    return Results.Accepted(value: new { message.Id });
});

Run with Aspire

The simplest way to run any sample is via the Aspire AppHost, which provisions RabbitMQ and PostgreSQL automatically:

dotnet run --project samples/BareWire.Samples.AppHost/

See: samples/BareWire.Samples.AppHost/Program.cs

Next Steps