我有一个已订阅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)
我看到了另一个问题,建议不再使用Message
或BrokeredMessage
对象,而改用byte[]
(并编写自己的编码来解决该问题),但这没为我工作。看来运行时仍在尝试并无法对消息执行某些操作,直到消息到达我的函数。
如何避免这个问题?
由于我尚未找到如何解决此问题的方法,因此我将保留这个问题-但是,我现在看到了如何在实例中解决此问题。我一直在努力处理的消息是AzureDevOps ServiceHooks发送的消息。如果我进入设置(在创建或编辑时),请在此处找到服务挂钩-> https://.visualstudio.com//_settings/serviceHooks
我错过了一个勾号框。为了使Azure功能能够处理该消息,需要选中此复选框。即您要作为非序列化字符串发送。这一定是因为位于我的函数和队列之间的任何客户端都无法处理.Net序列化消息。
Tl; Dr->如果您遇到此问题,请确保选中上面的这个选项
GitHub Issue跟踪问题
答案 0 :(得分:2)
问题在于,在决定是否对其进行解码时,Functions库正在查看消息类型,而不是函数中指定的类型。由于Devops将消息发送为application / json类型,因此该库正在尝试,并且无法使用UTF8对其进行解码。
目前,选择“发送为非序列化字符串”是有效的解决方法。可以在Github上跟踪该问题: https://github.com/Azure/azure-webjobs-sdk/issues/2234
相关代码(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")