0

I'm trying to update the content of an Azure Queue using the following code :

queue.UpdateMessage(new CloudQueueMessage(timestamp + "|" + encodedContent),TimeSpan.FromMinutes(0),MessageUpdateFields.Content, null, null);

However, I keep getting the following error "Value cannot be null. Parameter name: messageId". Tried searching through the internet but couldn't find anyone having this issue.

Note: It's mandatory for me to use Azure Queue.

dokyalashot
  • 105
  • 2
  • 18

2 Answers2

0

To update a message, you need to get the specific message first instead of creating a new message.

For more detailsChange the contents of a queued message

Jack Jia
  • 5,268
  • 1
  • 12
  • 14
  • If you’re a Microsoft partner, I recommend you visiting aka.ms/devchat for personalized support on Azure. It’s free and 24x5. – Jack Jia Oct 26 '18 at 06:20
  • Is there a way to do it using the messageId? My API already did a getMessage and sent the message to other application say X. Now this X wants to update the content of the message, so it makes call to this API to update the content. In this case if I do a GetMessage is there a guarantee that it will give me the same message? – dokyalashot Oct 26 '18 at 13:07
  • @AzureNewbie if you don't use message id, then no guarantee that it will give you the same message. You can refer to my answer below. – Ivan Glasenberg Oct 29 '18 at 10:25
0

Update:

You can pass message id and PopReceipt to your method:

        static void Main(string[] args)
        {

           CloudStorageAccount storageAccount = CloudStorageAccount.Parse(                
                     CloudConfigurationManager.GetSetting("StorageConnectionString"));

           // Create the queue client.
           CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();

           // Retrieve a reference to a container.
           CloudQueue queue = queueClient.GetQueueReference("myqueue0905");

           //Retrieve the cached approximate message count.
           queue.FetchAttributes();
           int? cachedMessageCount = queue.ApproximateMessageCount;

           //get the message id and PopReceipt, or you can pass them from your api call.
           string _id = "";
           string _popreceipt = "";

           if (cachedMessageCount != null)
           {

            foreach (CloudQueueMessage message in queue.GetMessages(cachedMessageCount.Value, TimeSpan.FromMinutes(3)))
            {
                 _id = message.Id;
                 _popreceipt = message.PopReceipt;

                 Console.WriteLine("the id is:" + _id);
                 Console.WriteLine("the pop receipt is:" + _popreceipt);

             }

            }

          //update queue message by using message id and PopReceipt
          var msg = new CloudQueueMessage(_id, _popreceipt);
          msg.SetMessageContent("a test messge 123456");
          queue.UpdateMessage(msg, TimeSpan.FromSeconds(120.0),
                            MessageUpdateFields.Content | MessageUpdateFields.Visibility);            

          Console.WriteLine("complete update");
          Console.ReadLine();
       }

In your case, assume you already know the message id, then you can update your message via the id.

We need to iterate all the queue messages using the message id, to fetch the correct message you want to update.

Code like below:

using Microsoft.Azure;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Queue;
using System;

namespace ConsoleApp11
{
    class Program
    {
        static void Main(string[] args)
        {
            //assume you know the message id
            string message_id = "3798f6b6-1541-4421-b8de-79a8294edf49";

            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
    CloudConfigurationManager.GetSetting("StorageConnectionString"));

            // Create the queue client.
            CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();

            // Retrieve a reference to a container.
            CloudQueue queue = queueClient.GetQueueReference("myqueue0905");

            //Retrieve the cached approximate message count.
            queue.FetchAttributes();
            int? cachedMessageCount = queue.ApproximateMessageCount;

            //if the queue is not null
            if (cachedMessageCount != null)
            {

                foreach (CloudQueueMessage message in queue.GetMessages(cachedMessageCount.Value))
                {
                    if (message.Id == message_id)
                    {
                        message.SetMessageContent("test updated content again");
                        queue.UpdateMessage(message, TimeSpan.FromSeconds(5.0),
                            MessageUpdateFields.Content | MessageUpdateFields.Visibility);
                    }
                }

            }

            Console.ReadLine();
        }

    }
}
Ivan Glasenberg
  • 29,865
  • 2
  • 44
  • 60
  • The problem with this is, when I do an initial GetMessage, I add an invisibility timeout for some time to avoid other programs from accessing that message from the queue. So if I do a get again, I will not retrieve the one that matches that messageId due to the lock on it. – dokyalashot Oct 29 '18 at 20:13
  • In that case, there are 2 methods: 1. use message id and popReceipt. 2. Use loop until it's visible. I have updated my answer with method 1. – Ivan Glasenberg Oct 30 '18 at 04:02
  • @AzureNewbie, if it solves your issue, please help mark it as answer. Thank you. – Ivan Glasenberg Oct 30 '18 at 23:04
  • Your solution worked like a charm. Thank you so much @Ivan Yang – dokyalashot Oct 30 '18 at 23:56