Manage topics with the C# SDK
Build a pub/sub messaging workflow with the Simple Message Queue (formerly MNS) SDK for C#: create topics and queues, subscribe, publish, consume messages, and clean up resources.
Prerequisites
-
An Alibaba Cloud account or a RAM user with the required permissions
-
An AccessKey pair. To create one:
-
Alibaba Cloud account: Go to the AccessKey Management page.
-
RAM user: Log on to the RAM console.
-
-
The endpoint for your region. Log on to the SMQ console to view available endpoints. Endpoints vary by region. For details, see Get endpoints.
Store your AccessKey pair securely. Do not hard-code credentials in source files committed to version control.
Set up the environment
-
Download the latest C# SDK, extract the package, and add the folder to Visual Studio as a solution.
-
The solution contains four projects. Right-click AliyunSDK_MNS and select Rebuild to generate
Aliyun.MNS.dllin the bin directory. Note: SetAliyun.MNS.dllas the reference for the other three projects. -
In the AliyunSDK_MNS_Sample project, open
SyncTopicOperations.cs:-
Set AliyunSDK_MNS_Sample as the startup project and SyncTopicOperations as the startup object.
-
Specify your AccessKey ID, AccessKey secret, and endpoint.
-
Create a topic
Create a topic with CreateTopicRequest. The default topic name is TestCSharpTopic.
// Create a topic. You can also specify other topic parameters.
var createTopicRequest = new CreateTopicRequest
{
TopicName = _topicName
};
Topic topic = null;
try
{
topic = client.CreateTopic(createTopicRequest);
Console.WriteLine("Create topic successfully, topic name: {0}", topic.TopicName);
}
catch (MNSException me)
{
// The operation fails if a network error occurs or the topic name already exists.
// Use CatchException or catch TopicAlreadyExistException to handle the failure.
Console.WriteLine("CreateTopic Failed! ErrorCode: " + me.ErrorCode);
}
catch (Exception ex)
{
Console.WriteLine("Create topic failed, exception info: " + ex.Message);
return;
}
Create a queue
If you have not created a queue, you must first create one. The default queue name is myqueue. You can modify the code to specify a different queue name.
// 1. Specify the properties for the queue. For more information about queue properties, see Queue.
var createQueueRequest = new CreateQueueRequest
{
QueueName = _queueName,
Attributes =
{
// VisibilityTimeout is the most important property. The default value is 30 seconds.
VisibilityTimeout = 30,
MaximumMessageSize = 40960,
MessageRetentionPeriod = 345600,
// PollingWaitSeconds is the timeout period for long polling.
PollingWaitSeconds = 30
}
};
try
{
// 2. Create the queue. If you do not need to specify queue properties, you can call client.CreateQueue(_queueName).
var queue = client.CreateQueue(createQueueRequest);
Console.WriteLine("Create queue successfully, queue name: {0}", queue.QueueName);
}
catch (MNSException me)
{
// 3. If an error occurs when you create the queue, you can handle the error based on the error code. You can also catch exceptions such as QueueAlreadyExistException to handle them separately.
Console.WriteLine("CreateQueue Failed! ErrorCode: " + me.ErrorCode);
}
catch (Exception ex)
{
Console.WriteLine("Create queue failed, exception info: " + ex.Message);
}
Create a subscription
Subscribe the queue to the topic. The subscription endpoint follows the format acs:mns:{region}:{accountId}:queues/{queueName}.
string region = "";
string accountId = "";
string queueName = "TestQueue";
try
{
// The second parameter specifies the endpoint that receives messages.
SubscribeResponse res = topic.Subscribe(_subscriptionName,
"acs:mns:" + region + ":" + accountId + ":queues/" + queueName);
Console.WriteLine("Subscribe succeed");
}
catch (MNSException me)
{
// The operation fails if a network error occurs or the subscription name already exists.
Console.WriteLine("Subscribe Failed! ErrorCode: " + me.ErrorCode);
}
catch (Exception ex)
{
Console.WriteLine("Subscribe failed, exception info: " + ex.Message);
}
Replace region, accountId, and queueName with your actual values.
Publish a message
Publish a message to the topic. The topic delivers it to all subscribed endpoints.
try
{
var response = topic.PublishMessage("message here </asdas\">");
Console.WriteLine("PublishMessage succeed! " + response.MessageId);
}
catch (MNSException me)
{
// The operation fails if a network error occurs.
Console.WriteLine("PublishMessage Failed! ErrorCode: " + me.ErrorCode);
}
catch (Exception ex)
{
Console.WriteLine("PublishMessage failed, exception info: " + ex.Message);
}
Receive and delete a message from the queue
After the topic delivers a message to the queue, receive and delete it.
Receive a message
Use long polling with WaitSeconds set to 30. The request blocks until a message arrives or the timeout expires. The maximum WaitSeconds value is 30.
try
{
// 1. Call the receiveMessage function.
// The receiveMessage function accepts the waitSeconds parameter. Set this parameter to 30.
// A waitSeconds value other than 0 indicates that this receiveMessage call is an HTTP long polling request. If no message exists in the queue, the request waits on the server until a message is available. The maximum wait time is the value of waitSeconds, up to a maximum of 30.
var receiveMessageResponse = nativeQueue.ReceiveMessage(30);
// 2. Get the receipt handle. This is a time-sensitive handle that you can use to set message properties and delete the message. For more information, see QueueMessage.
_receiptHandle = message.ReceiptHandle;
}
catch (MNSException me)
{
// 3. Similar to CreateQueue and SendMessage, an error can occur when you call ReceiveMessage. Catch the exception and handle it.
Console.WriteLine("ReceiveMessage Failed! ErrorCode: " + me.ErrorCode);
}
catch (Exception ex)
{
Console.WriteLine("ReceiveMessage failed, exception info: " + ex.Message);
}
// Add your logic to process the message here. This step is omitted in the sample.
// If an exception such as a program crash or freeze occurs, the message becomes visible again after the VisibilityTimeout period expires. This allows other processes to handle the message and prevents message loss.
// 4. After the message is processed, delete it from the queue.
try
{
// 5. Call deleteMessage.
var deleteMessageResponse = nativeQueue.DeleteMessage(_receiptHandle);
}
catch (MNSException me)
{
// 6. Catch the exception and handle it.
// If the receipt handle has expired, the error code is MessageNotExist. This indicates that the message cannot be found using this receipt handle.
// To prevent the receipt handle from expiring, make sure that the VisibilityTimeout value is long enough for the message to be processed. During message processing, you can also call the changeMessageVisibility function to extend the VisibilityTimeout period of the message.
Console.WriteLine("DeleteMessage Failed! ErrorCode: " + me.ErrorCode);
}
catch (Exception ex)
{
Console.WriteLine("Delete message failed, exception info: " + ex.Message);
}
Process and delete the message
After processing the message, delete it from the queue using the receipt handle. VisibilityTimeout controls how long a consumed message stays inactive. When it expires, the message becomes available to other clients again. This prevents message loss from unexpected exits.
Delete the topic
Delete the topic when it is no longer needed.
try
{
client.DeleteTopic(_topicName);
Console.WriteLine("Delete topic succeed");
}
catch (Exception ex)
{
Console.WriteLine("Delete topic failed, exception info: " + ex.Message);
}
Delete the queue
Delete the queue when it is no longer needed.
try
{
var deleteQueueResponse = client.DeleteQueue(deleteQueueRequest);
}
catch (MNSException me)
{
Console.WriteLine("DeleteQueue Failed! ErrorCode: " + me.ErrorCode);
}
catch (Exception ex)
{
Console.WriteLine("Delete queue failed, exception info: " + ex.Message);
}
Error handling
All operations can throw MNSException with an ErrorCode. Common errors:
| Error scenario | Cause | Resolution |
|---|---|---|
| Topic or queue creation fails | Network error or resource name already exists | Check network connectivity. Use a unique name or catch TopicAlreadyExistException. |
MessageNotExist on delete |
The receipt handle has expired | Increase VisibilityTimeout or call changeMessageVisibility() to extend it before the handle expires. |
| Subscription creation fails | Network error or subscription name already exists | Check network connectivity. Use a unique subscription name. |