--- title: "Azure Service Bus transport" description: "The BabelQueue.AzureServiceBus transport — a canonical-envelope publisher and a URN-routed consumer over Azure.Messaging.ServiceBus, on the framework-agnostic core." source: https://babelqueue.com/docs/babelqueue-dotnet/1.x/azure-service-bus/ updated: 2026-06-14T00:00:00.000Z --- # Azure Service Bus transport `BabelQueue.AzureServiceBus` is an Azure Service Bus transport on the .NET core. It sends the [canonical envelope](/docs/spec/1.x/envelope/) as the `Body` with the [§4 native projection](/docs/spec/1.x/broker-bindings/#azure-service-bus), and consumes by routing each message to a handler by URN — so a message it produces is consumed by any other BabelQueue SDK, and vice-versa. ## Install ```bash dotnet add package BabelQueue.AzureServiceBus ``` Requirements: **.NET 8**. It pulls `BabelQueue.Core` and `Azure.Messaging.ServiceBus` transitively. ## Produce ```csharp using Azure.Messaging.ServiceBus; using BabelQueue.AzureServiceBus; await using var client = new ServiceBusClient(""); // or a namespace + TokenCredential var sender = client.CreateSender("orders"); var id = await new AsbPublisher(sender) .PublishAsync("urn:babel:orders:created", new Dictionary { ["order_id"] = 1042 }); ``` `PublishAsync` returns the message `meta.id`; pass a `traceId` to continue a trace, or a `delay` (`TimeSpan`) to schedule native delayed delivery (`ScheduledEnqueueTime`). ## Consume ```csharp var receiver = client.CreateReceiver("orders"); // PeekLock var handlers = new Dictionary { ["urn:babel:orders:created"] = (envelope, message, ct) => { // envelope.Data, envelope.TraceId, envelope.Attempts ... return Task.CompletedTask; }, }; var consumer = new AsbConsumer(receiver, handlers, new AsbConsumerOptions { OnError = (err, env, msg) => Console.Error.WriteLine(err), }); await consumer.RunAsync(cancellationToken); ``` A throwing handler `Abandon`s the message — the broker redelivers it and increments `DeliveryCount` (at-least-once); at `MaxDeliveryCount` it auto-moves to the native dead-letter sub-queue. Auth is a connection string or the fully-qualified namespace + a `TokenCredential` (`DefaultAzureCredential`). ## Contract mapping (§4) | Envelope | Azure Service Bus | | :--- | :--- | | body | `Body` (byte-identical across SDKs) | | `job` (URN) | `Subject` | | `trace_id` | `CorrelationId` | | `meta.id` | `MessageId` | | `meta.schema_version` | `ApplicationProperties["bq-schema-version"]` | | `meta.lang` | `ApplicationProperties["bq-source-lang"]` | | `meta.created_at` | `ApplicationProperties["bq-created-at"]` (ms) | | `attempts` | `max(body, DeliveryCount − 1)` | | reserve / ack / retry | PeekLock → `Complete` / `Abandon` | `ServiceBusSender` / `ServiceBusReceiver` are mockable, so the unit tests use Moq + `ServiceBusModelFactory` — no Azure, no network. The envelope is unchanged (`schema_version` stays `1`); Azure Service Bus is purely additive.