Azure WebJob ProcessQueueMessage не может прочитать CloudQueueMessage

Таким образом, у меня есть веб-задание Azure, связанное с CloudQueue через механизм ProcessQueueMessage пакета SDK WebJobs с использованием типа параметра CloudQueueMessage. Это дает мне FunctionInvocationException при запуске через QueueTrigger.


Подробно

Элемент успешно добавлен в CloudQueue с помощью метода AddMessageAsync:

await queue.AddMessageAsync(new CloudQueueMessage(JsonConvert.SerializeObject(myObject)));

И отображается в очереди как ожидаемое JSON-представление моего объекта (из предварительного просмотра текста сообщения в Cloud Explorer):

{"EmailAddress":"[email protected]",
 "Subject":"Test",
 "TemplateId":"00-00-00-00-00",
 "Model":{"PropertyName1":"Test1","PropertyName2":"Test2"}
 }

Однако при срабатывании метода ProcessQueueMessage:

public static async void ProcessQueueMessage(
    [QueueTrigger(queueName)] CloudQueueMessage message, TextWriter log)

... Я получаю FunctionInvocationException:

Microsoft.Azure.WebJobs.Host.FunctionInvocationException: Exception while executing function: Functions.ProcessQueueMessage ---> System.InvalidOperationException: Exception binding parameter 'message' ---> System.ArgumentNullException: String reference not set to an instance of a String.
 Parameter name: s
 at System.Text.Encoding.GetBytes(String s)
 at Microsoft.WindowsAzure.Storage.Queue.CloudQueueMessage.get_AsBytes() in c:\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\Common\Queue\CloudQueueMessage.Common.cs:line 146
 at Microsoft.Azure.WebJobs.Host.PropertyHelper.CallPropertyGetter[TDeclaringType,TValue](Func`2 getter, Object this)
 at Microsoft.Azure.WebJobs.Host.PropertyHelper.GetValue(Object instance)
 at Microsoft.Azure.WebJobs.Host.Bindings.BindingDataProvider.GetBindingData(Object value)
 at Microsoft.Azure.WebJobs.Host.Queues.Triggers.UserTypeArgumentBindingProvider.UserTypeArgumentBinding.BindAsync(IStorageQueueMessage value, ValueBindingContext context)
 at Microsoft.Azure.WebJobs.Host.Queues.Triggers.QueueTriggerBinding.<BindAsync>d__0.MoveNext()
 --- End of stack trace from previous location where exception was thrown ---
 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
 at Microsoft.Azure.WebJobs.Host.Triggers.TriggeredFunctionBinding`1.<BindCoreAsync>d__7.MoveNext()
 --- End of inner exception stack trace ---
 at Microsoft.Azure.WebJobs.Host.Executors.DelayedException.Throw()
 at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.<ExecuteWithWatchersAsync>d__31.MoveNext()
 --- End of stack trace from previous location where exception was thrown

Похоже, это наводит на мысль, что параметр message не может прочитать JSON в объекте CloudQueueMessage ... но не похоже, что это то, что я контролирую.

Есть ли у кого-нибудь предложения относительно того, почему это может происходить?


Информация о версии

Microsoft.Azure.Webjobs 1.1.1

WindowsAzure.Storage 6.2.2-предварительная версия

DNX 4.5.1

Фон

Трой Хант - учебник по работе в Интернете

MSDN - Как ... статью


person richaux    schedule 03.03.2016    source источник


Ответы (1)


измените свой ProcessQueueMessage, чтобы он принял строку (которую вы фактически передаете CloudQueuMessage), затем возьмите ее и десериализуйте в свой объект:

public static async void ProcessQueueMessage(
    [QueueTrigger(queueName)] string message, TextWriter log)
{
   JsonConvert.DeserializeObject<YourObjectType>(json);
}

Или лучше, если это объект POCO, тогда все, что вам нужно сделать, это использовать вместо этого:

public static async void ProcessQueueMessage
(
   [QueueTrigger(queueName)] YourObjectType message, 
   TextWriter log
)
{      //....    }

Обновление: Хотя было бы неплохо получить все это в объекте CloudQueueMessage, но для получения свойств, которые отправляются в CloudQueueMessage, вы можете добавить следующие параметры в метод веб-задания:

public static async void ProcessQueueMessage(
        [QueueTrigger(queueName)] string logMessage, 
        DateTimeOffset expirationTime,
        DateTimeOffset insertionTime,
        DateTimeOffset nextVisibleTime,
        string id,
        string popReceipt,
        int dequeueCount,
        string queueTrigger,
        CloudStorageAccount cloudStorageAccount,
        TextWriter logger)
    {
        logger.WriteLine(
            "logMessage={0}\n" +
        "expirationTime={1}\ninsertionTime={2}\n" +
            "nextVisibleTime={3}\n" +
            "id={4}\npopReceipt={5}\ndequeueCount={6}\n" +
            "queue endpoint={7} queueTrigger={8}",
            logMessage, expirationTime,
            insertionTime,
            nextVisibleTime, id,
            popReceipt, dequeueCount,
            cloudStorageAccount.QueueEndpoint,
            queueTrigger);
    }
person zaid safadi    schedule 03.03.2016
comment
спасибо @zaid. Оба ваших предложения позволяют избежать ошибки. Использование CloudQueueMessage позволит мне также получить доступ к свойствам сообщения (например, InsertionTime) и должно быть действительным. Из указанной ссылки MSDN: Помимо строки, параметром может быть массив байтов, объект CloudQueueMessage или POCO, который вы определяете. - person richaux; 04.03.2016
comment
@richaux, эти свойства можно добавить к параметрам метода. Вы помещаете CloudQueueMessage в очередь на стороне отправителя, но получаете содержимое и метаданные в параметрах метода на стороне получателя, см. Раздел Получение очереди или метаданных сообщения очереди в указанном выше URL-адресе документа Azure. Я обновлю свой ответ, чтобы показать это для полноты. - person zaid safadi; 04.03.2016
comment
спасибо за пример. Нашел дополнительную информацию в документации github. - person richaux; 04.03.2016
comment
Обратите внимание, что CloudQueueMessage не входит в список поддерживаемых типов привязки ввода (см. здесь), он поддерживается только как исходящая привязка. Я думаю, что это может / должно быть привязка ввода, но не сейчас. - person mathewc; 05.03.2016
comment
спасибо @mathewc - tbh Я не обнаружил, что Quick Ref проясняет ситуацию :) В нем CloudQueueMessage указан как опция для QueueTrigger привязки вверху страницы, и в примере в разделе 2.1 он тоже используется. статья Tom D, на которую ссылается Quick Ref, также содержит CloudQueueMessage в качестве варианта (но без примера). Это не проблема: параметры POCO и строки подходят для моих текущих нужд. - person richaux; 08.03.2016
comment
Да, хороший момент, извините за недоразумение. Если вы считаете, что у нас есть ошибка, зарегистрируйте проблему в нашем общедоступном репозитории: github.com / Azure / azure-webjobs-sdk / issues - person mathewc; 08.03.2016