When I use the following:
var deadLetterPath = SubscriptionClient.FormatDeadLetterPath(topicPath,subName);
var client = SubscriptionClient.CreateFromConnectionString(connectionString, deadLetterPath, subName);
I get an InvalidOperationException
Cannot directly create a client on a sub-queue. Create a client on the
main queue and use that to create receivers on the appropriate
sub-queue
Some parts of the azure documentation say to use SubscriptionClient.CreateReceiver to access a sub-queue but that method doesn't exist.
Does this approach work for you ?
MessagingFactory factory = MessagingFactory.CreateFromConnectionString(cnxString);
var deadLetterPath = SubscriptionClient.FormatDeadLetterPath(topicPath,subName);
var dlqReceiver = factory.CreateMessageReceiver(deadLetterPath, ReceiveMode.ReceiveAndDelete);
I haven't test it out here (in a meeting), but give it a try
cheers
There is a convention naming for Dead letter queue using Azure Service Bus:
- For Service Bus Queue: queuePath/$DeadLetterQueue
- For Service Bus Subscription: topicPath/subscriptionName/$DeadLetterQueue
So you can access your dead letter queues the same way you access your queues.
From @SamVanhoutte answer, you can see that the ServiceBus framework provides methods to format the dead letter queue name:
For Service Bus Queue: QueueClient.FormatDeadLetterPath(queuePath)
For Service Bus Subscription: SubscriptionClient.FormatDeadLetterPath(topicPath, subscriptionName)
I wrote two small methods to create a message receiver for queue and subscription where you can set if you want the deal letter queue or not:
/// <summary>
/// Create a new <see cref="MessageReceiver"/> object using the specified Service Bus Queue path.
/// </summary>
/// <param name="connectionString">The connection string to access the desired service namespace.</param>
/// <param name="queuePath">The Service Bus Queue path.</param>
/// <param name="isDeadLetter">True if the desired path is the deadletter queue.</param>
public static MessageReceiver CreateMessageReceiver(string connectionString, string queuePath,
bool isDeadLetter = false)
{
return MessagingFactory.CreateFromConnectionString(connectionString)
.CreateMessageReceiver(isDeadLetter
? QueueClient.FormatDeadLetterPath(queuePath)
: queuePath);
}
/// <summary>
/// Create a new <see cref="MessageReceiver"/> object using the specified Service Bus Topic Subscription path.
/// </summary>
/// <param name="connectionString">The connection string to access the desired service namespace.</param>
/// <param name="topicPath">The Service Bus Topic path.</param>
/// <param name="subscriptionName">The Service Bus Topic Subscription name.</param>
/// <param name="isDeadLetter">True if the desired path is the deadletter subqueue.</param>
public static MessageReceiver CreateMessageReceiver(string connectionString, string topicPath,
string subscriptionName, bool isDeadLetter = false)
{
return MessagingFactory.CreateFromConnectionString(connectionString)
.CreateMessageReceiver(isDeadLetter
? SubscriptionClient.FormatDeadLetterPath(topicPath, subscriptionName)
: SubscriptionClient.FormatSubscriptionPath(topicPath, subscriptionName));
}
If you are using Microsoft.Azure.ServiceBus
instead of Microsoft.ServiceBus
, it is slightly different.
var deadQueuePath = EntityNameHelper.FormatDeadLetterPath(your_queue_name);
var deadQueueReceiver = new MessageReceiver(connectionString, deadQueuePath);
As per EntityNameHelper
class in Microsoft.Azure.ServiceBus
namespace, for topics, use the subscription path instead of your_queue_name.
The name of the queue, or path of the subscription.
/// <summary>
/// Formats the dead letter path for either a queue, or a subscription.
/// </summary>
/// <param name="entityPath">The name of the queue, or path of the subscription.</param>
/// <returns>The path as a string of the dead letter entity.</returns>
public static string FormatDeadLetterPath(string entityPath)
{
return EntityNameHelper.FormatSubQueuePath(entityPath, EntityNameHelper.DeadLetterQueueName);
}