Azure函数-ServiceBusTrigger-异常绑定消息

时间:2019-06-06 16:49:20

标签: encoding .net-core azure-devops azure-functions azureservicebus

我有一个已订阅Azure Service Bus队列的Azure函数-但是,在该函数能够触发异常之前,运行时会在它到达我的任何代码之前引发异常。

Exception while executing function: <functionName>. Microsoft.Azure.WebJobs.Host: Exception binding parameter 'message'. System.Private.CoreLib: Unable to translate bytes [9A] at index 60 from specified code page to Unicode.

在这种情况下,我不受传入消息的控制(它实际上是从Azure DevOps订阅发送的),因此我需要能够使该函数更加灵活,以免引发此异常。

我的功能如下:

[FunctionName("FunctionName")]
public static async Task Run(
    [ServiceBusTrigger("Queue", Connection = "ConnectionString")] byte[] message)

我看到了另一个问题,建议不再使用MessageBrokeredMessage对象,而改用byte[](并编写自己的编码来解决该问题),但这没为我工作。看来运行时仍在尝试并无法对消息执行某些操作,直到消息到达我的函数。

如何避免这个问题?


由于我尚未找到如何解决此问题的方法,因此我将保留这个问题-但是,我现在看到了如何在实例中解决此问题。我一直在努力处理的消息是AzureDevOps ServiceHooks发送的消息。如果我进入设置(在创建或编辑时),请在此处找到服务挂钩-> https://.visualstudio.com//_settings/serviceHooks

我错过了一个勾号框。为了使Azure功能能够处理该消息,需要选中此复选框。即您要作为非序列化字符串发送。这一定是因为位于我的函数和队列之间的任何客户端都无法处理.Net序列化消息。

enter image description here

Tl; Dr->如果您遇到此问题,请确保选中上面的这个选项

GitHub Issue跟踪问题

2 个答案:

答案 0 :(得分:2)

问题在于,在决定是否对其进行解码时,Functions库正在查看消息类型,而不是函数中指定的类型。由于Devops将消息发送为application / json类型,因此该库正在尝试,并且无法使用UTF8对其进行解码。

目前,选择“发送为非序列化字符串”是有效的解决方法。可以在Github上跟踪该问题: https://github.com/Azure/azure-webjobs-sdk/issues/2234

enter image description here

相关代码(Microsoft.Azure.WebJobs.ServiceBus.Triggers.UserTypeArgumentBindingProvider)

 private static TInput GetBody(Message message, ValueBindingContext context)
        {
            if (message.ContentType == ContentTypes.ApplicationJson) //This is looking at the message type
            {
                string contents;

                contents = StrictEncodings.Utf8.GetString(message.Body);

                try
                {
                    return JsonConvert.DeserializeObject<TInput>(contents, Constants.JsonSerializerSettings);
                }
                catch (JsonException e)
                {
                    // Easy to have the queue payload not deserialize properly. So give a useful error. 
                    string msg = string.Format(
    @"Binding parameters to complex objects (such as '{0}') uses Json.NET serialization. 
    1. Bind the parameter type as 'string' instead of '{0}' to get the raw values and avoid JSON deserialization, or
    2. Change the queue payload to be valid json. The JSON parser failed: {1}
    ", typeof(TInput).Name, e.Message);
                    throw new InvalidOperationException(msg);
                }
            }
            else
            {
                return message.GetBody<TInput>();
            }
        }
    }

答案 1 :(得分:0)

在新世界中如此(.net 5 功能应用程序)。我们从 [FunctionName("FunctionName")] 移到 [Function("FunctionName")]

此外,您不能再使用“消息”或字节[]。只能是字符串!

 public async Task Run([ServiceBusTrigger(topicName, SubscriberName, Connection= %conn% )] string messageText, string id,  FunctionContext executionContext)

现在的魔力在于FunctionContext

您可以通过这种方式获取消息属性:

executionContext.BindingContext.BindingData.Where(x => x.Key =="UserProperties")