Service Bus Explorer 时如何使用消息正文 C# 读取 重新提交消息时添加垃圾 http://schemas.microsoft.com/2003/10/Serialization -
How to Read with Message Body C# when Service Bus Explorer Adds junk http://schemas.microsoft.com/2003/10/Serialization when resubmitting messages -
我正在开发基于 Azure 服务总线和 Azure Functions 的系统。
我们的服务总线消息是基于文本的,通常 json 我们已经开始在我们的一些消息中看到有关文本中无效字符的错误。
这不会影响队列中的所有消息,我已经能够追溯到使用服务总线资源管理器重新提交正文类型为“字符串”的死信队列消息
在服务总线资源管理器中,消息显示完全正常:
然而,当从代码中读取消息时,正文是:
@06string083http://schemas.microsoft.com/2003/10/Serialization/�15嗨伙计,你好吗?
我希望能够处理以这种方式提交的消息,但是 none ReceivedMessage Class 上的消息有效。我在 Linqpad
中尝试了多种使用 C# 的方法
var client = new ServiceBusClient(connectionString);
var receiver = client.CreateReceiver(queueName, new ServiceBusReceiverOptions { ReceiveMode = ServiceBusReceiveMode.PeekLock});
string txtBody;
"Peek Messages".Dump();
var message = await receiver.PeekMessageAsync();
while (message != null)
{
Stream stream = message.Body.ToStream();
StreamReader reader = new StreamReader(stream,Encoding.UTF8);
txtBody = reader.ReadToEnd();
txtBody.Dump("Read with stream");
txtBody = Encoding.UTF8.GetString(message.Body.ToArray());
txtBody.Dump("Read with Byte[]");
message.Body.ToString().Dump("Read with toString");
message = await receiver.PeekMessageAsync();
}
只有当消息作为字符串重新提交时才会发生这种情况 - 作为流重新提交按预期工作。
在我看来,应该有一种检测此类消息的方法以及一种阅读它的替代方法。服务总线资源管理器显然正在以某种方式处理它。
Service Bus Explorer 基于旧版 SDK,它使用 DataContractSerializer
对消息负载进行编码。此方法已被弃用,并且未沿用到较新的 SDK 中。
Azure.Messaging.ServiceBus
不假设您的消息负载是如何序列化或编码的,仅返回原始字节。要与 Service Bus Explorer 中的负载交互,您需要使用等效的序列化程序来转换负载。
中找到这样做的示例
我正在添加自己的答案以帮助他人。
Jesse Squire 向我指出了服务总线互操作示例的正确方向,但该方法仅适用于消息已序列化并包含“序列化垃圾”的情况。
通过我的队列的绝大多数消息都是用新库生成的,并且是“干净的”。使用服务总线资源管理器或其他基于旧库的工具从 DQL“修复并重新提交”的消息中只有一小部分会导致问题。
我通过检查文本中的序列化标记解决了这个问题,如下所示。
string ReadMessageText(ServiceBusReceivedMessage message)
{
string msgText = message.Body.ToString();
if (msgText.StartsWith("@") && msgText.Contains(@"http://schemas.microsoft.com/2003/10/Serialization"))
{
var deserializer = new DataContractSerializer(typeof(string));
XmlDictionaryReader reader = XmlDictionaryReader.CreateBinaryReader(message.Body.ToStream(), XmlDictionaryReaderQuotas.Max);
// deserialize the XML envelope into a string
msgText = (string)deserializer.ReadObject(reader);
}
return msgText.Trim();
}
DataContractSerializer 需要 System.Runtime.Serialization,reader 需要 System.Xml。
我正在开发基于 Azure 服务总线和 Azure Functions 的系统。
我们的服务总线消息是基于文本的,通常 json 我们已经开始在我们的一些消息中看到有关文本中无效字符的错误。
这不会影响队列中的所有消息,我已经能够追溯到使用服务总线资源管理器重新提交正文类型为“字符串”的死信队列消息
在服务总线资源管理器中,消息显示完全正常:
然而,当从代码中读取消息时,正文是:
@06string083http://schemas.microsoft.com/2003/10/Serialization/�15嗨伙计,你好吗?
我希望能够处理以这种方式提交的消息,但是 none ReceivedMessage Class 上的消息有效。我在 Linqpad
中尝试了多种使用 C# 的方法var client = new ServiceBusClient(connectionString);
var receiver = client.CreateReceiver(queueName, new ServiceBusReceiverOptions { ReceiveMode = ServiceBusReceiveMode.PeekLock});
string txtBody;
"Peek Messages".Dump();
var message = await receiver.PeekMessageAsync();
while (message != null)
{
Stream stream = message.Body.ToStream();
StreamReader reader = new StreamReader(stream,Encoding.UTF8);
txtBody = reader.ReadToEnd();
txtBody.Dump("Read with stream");
txtBody = Encoding.UTF8.GetString(message.Body.ToArray());
txtBody.Dump("Read with Byte[]");
message.Body.ToString().Dump("Read with toString");
message = await receiver.PeekMessageAsync();
}
只有当消息作为字符串重新提交时才会发生这种情况 - 作为流重新提交按预期工作。
在我看来,应该有一种检测此类消息的方法以及一种阅读它的替代方法。服务总线资源管理器显然正在以某种方式处理它。
Service Bus Explorer 基于旧版 SDK,它使用 DataContractSerializer
对消息负载进行编码。此方法已被弃用,并且未沿用到较新的 SDK 中。
Azure.Messaging.ServiceBus
不假设您的消息负载是如何序列化或编码的,仅返回原始字节。要与 Service Bus Explorer 中的负载交互,您需要使用等效的序列化程序来转换负载。
我正在添加自己的答案以帮助他人。
Jesse Squire 向我指出了服务总线互操作示例的正确方向,但该方法仅适用于消息已序列化并包含“序列化垃圾”的情况。
通过我的队列的绝大多数消息都是用新库生成的,并且是“干净的”。使用服务总线资源管理器或其他基于旧库的工具从 DQL“修复并重新提交”的消息中只有一小部分会导致问题。
我通过检查文本中的序列化标记解决了这个问题,如下所示。
string ReadMessageText(ServiceBusReceivedMessage message)
{
string msgText = message.Body.ToString();
if (msgText.StartsWith("@") && msgText.Contains(@"http://schemas.microsoft.com/2003/10/Serialization"))
{
var deserializer = new DataContractSerializer(typeof(string));
XmlDictionaryReader reader = XmlDictionaryReader.CreateBinaryReader(message.Body.ToStream(), XmlDictionaryReaderQuotas.Max);
// deserialize the XML envelope into a string
msgText = (string)deserializer.ReadObject(reader);
}
return msgText.Trim();
}
DataContractSerializer 需要 System.Runtime.Serialization,reader 需要 System.Xml。