Azure WebJob ProcessQueueMessage 无法读取 CloudQueueMessage

Azure WebJob ProcessQueueMessage fails to read CloudQueueMessage

总而言之,我有一个 Azure Web 作业通过 WebJobs SDK 的 ProcessQueueMessage 机制链接到 CloudQueue,使用 CloudQueueMessage 参数类型。当通过 QueueTrigger.

触发时,这给了我一个 FunctionInvocationException

详情

使用 AddMessageAsync 方法成功将项目添加到 CloudQueue

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

并作为我的对象的预期 JSON 表示出现在队列中(来自 Cloud Explorer 中的消息文本预览):

{"EmailAddress":"example@mail.com",
 "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

背景

Troy Hunt - Web Job primer

MSDN - How to... article

更改您的 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 中发送的属性,您可以将以下参数添加到 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);
    }