AI agents: use the documentation index at llms.txt to locate machine-readable pages. This section is indexed by https://docs.particular.net/transports/llms.txt. The markdown version of this page is served as plain text. An MCP server at /mcp serves the same content via the search_docs and read_doc tools; it is read-only and needs no credentials. Markdown versions of documentation pages are available by appending .md to the page URL. Directory URLs use index.md. They are served as text/plain because some retrieval backends reject text/markdown.

Azure Storage Queues Native Integration

This document describes how to consume messages from and send messages to non-NServiceBus endpoints via Azure Storage Queues in integration scenarios.

Sending native messages

Sending native messages can be accomplished by sending a message with a JSON-serialized payload using the QueueClient. Refer to the sample for more information.

Custom envelope unwrapper

Azure Storage Queues lacks native header support. NServiceBus solves this by wrapping headers and message body in a custom envelope structure. This envelope is serialized using the configured serializer for the endpoint before being sent.

Creating this envelope can cause unnecessary complexity if headers are not needed, as is the case in native integration scenarios. For this reason, NServiceBus.Transport.AzureStorageQueues 9.0 and above support configuring a custom envelope unwrapper.

The snippet below shows custom unwrapping logic that enables both NServiceBus formatted and plain serialized messages to be consumed.

var transport = new AzureStorageQueueTransport("connection string")
{
    MessageUnwrapper = queueMessage =>
    {
        //Determine whether the message is one expected by the standard program flow.
        // All other messages should be forwarded to the framework by returning null.
        //NOTE: More complex methods may be needed in some scenarios to determine
        // whether the message is of an expected type, but this check
        // should be kept as lightweight as possible. Deserialization of the message
        // body happens later in the pipeline.
        return queueMessage.MessageText.Contains("MyMessageIdFieldName") &&
               queueMessage.MessageText.Contains("MyMessageCustomPropertyFieldName")
        //this was a native message just return the body as is with no headers
        ? new MessageWrapper
        {
            Id = queueMessage.MessageId,
            Headers = [],
            Body = queueMessage.Body.ToArray()
        }
        : null;
    }
};

endpointConfiguration.UseTransport(transport);

List of Samples