Skip to content

Request/Reply

RPC-style messaging where you send a request and await a correlated response.

Basic Usage

csharp
// Inject the typed sender for the request message
var response = await sender.RequestAsync<OrderStatusResponse>(
    new GetOrderStatus(orderId),
    ct);

Console.WriteLine($"Order status: {response.Status}");

With Timeout

csharp
var response = await sender.RequestAsync<OrderStatusResponse>(
    new GetOrderStatus(orderId),
    timeout: TimeSpan.FromSeconds(30),
    ct);

Handler Side

Reply from the handler using context.ReplyAsync<T>() or by injecting ReplyContext:

csharp
// Option 1: via MessageContext (simplest)
messaging.MapQueue<GetOrderStatus>("order-queries")
    .MapHandler(async (GetOrderStatus request, MessageContext context, IOrderRepository orders, CancellationToken ct) =>
    {
        var order = await orders.GetAsync(request.OrderId, ct);
        await context.ReplyAsync(new OrderStatusResponse(order.Status, order.LastUpdated), ct);
    });

// Option 2: via ReplyContext (throws if no ReplyTo address)
messaging.MapQueue<GetOrderStatus>("order-queries")
    .MapHandler(async (GetOrderStatus request, ReplyContext reply, IOrderRepository orders, CancellationToken ct) =>
    {
        var order = await orders.GetAsync(request.OrderId, ct);
        await reply.RespondAsync(new OrderStatusResponse(order.Status, order.LastUpdated), ct);
    });

Use context.CanReply to check whether a reply is expected before calling ReplyAsync.

Configuration

Configure a session-enabled reply queue:

csharp
var messaging = builder.Services.AddMessaging(options =>
{
    options.ReplyStrategy.ReplyQueue = "my-service-replies"; // Must be session-enabled
});

IMPORTANT

Azure Service Bus prerequisite: The reply queue must be created with RequiresSession = true. Request/reply uses session IDs to correlate responses back to the correct requester - each request generates a unique session ID, and the requester opens a session receiver filtered to that ID.

bicep
resource replyQueue 'Microsoft.ServiceBus/namespaces/queues@2022-10-01-preview' = {
  name: 'my-service-replies'
  properties: {
    requiresSession: true
    defaultMessageTimeToLive: 'PT5M' // Keep replies short-lived
  }
}

If the reply queue is not session-enabled, responses from different requesters will be interleaved and requests will time out or receive incorrect responses.

Each request uses a unique session ID. The requester opens a session receiver on the reply queue, and the responder sends the reply with that session ID. The session acquisition latency (~100ms) is negligible since you're already waiting for a response.