0

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


Деталь

Товар успешно добавлен в CloudQueue используя AddMessageAsync метод:

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

И появляется на очереди как ожидаемом JSON представления моего объекта (из Послания Предварительный просмотр текста в облачном проводнике):

{"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 объект ... но не кажется, что это то, что я контролирую.

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


Version Info

Microsoft.Azure.Webjobs 1.1.1

WindowsAzure.Storage 6.2.2 предпросмотр

DNX 4,5.1

фон

Troy Hunt - Web Job primer

MSDN - How to... article

ответ

1

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

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

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

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

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

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); 
    } 
+0

thanks @zaid. Оба ваших предложения избегают ошибки. Использование «CloudQueueMessage» позволило бы мне также получить доступ к свойствам сообщения (например, «InsertionTime») и должно быть допустимым. На ссылке, указанной в MSDN: «Помимо строки, параметр может быть байтовым массивом, объектом CloudQueueMessage или определяемым вами POCO». – richaux

+0

@richaux, эти свойства могут быть добавлены к параметрам метода. Вы отправляете очередь CloudQueueMessage на стороне отправителя, но вы получаете контент и метаданные параметров метода в конце получателя, см. Раздел «Получить метаданные очереди или очереди сообщений» в указанном выше URL-адресе Azure. Я уточню свой ответ, чтобы показать, что для полноты. –

+0

спасибо за пример. Нашел еще один фон в [github docs] (https://github.com/Azure/azure-webjobs-sdk-extensions/wiki/Binding-Attributes). – richaux

Смежные вопросы