使用Microsoft.Azure.ServiceBus 2.0.0接收队列消息出现编码异常
嘿,这个问题我之前也踩过坑!核心原因是新旧ServiceBus SDK对消息Body的处理逻辑完全不一样,导致你直接用UTF8转字符串得到了乱码。
问题根源拆解
你用的旧版WindowsAzure.ServiceBus 4.1.6里的BrokeredMessage(旧版的消息类是这个),默认会把你传入的对象用BinaryFormatter序列化后放到Body里——哪怕你想传的是XML文本,只要直接把包含XML的对象丢给它,它就会自动序列化整个对象,而不是直接存XML的字节。
而新版Microsoft.Azure.ServiceBus 2.0.0的ServiceBusMessage拿到的Body是原始的序列化字节,这些字节根本不是纯UTF8的XML,而是BinaryFormatter序列化后的二进制数据,所以直接转字符串肯定会出现意外字符。
两种解决方案,看你需求选
方案1:接收端适配旧版的序列化逻辑
如果发送端代码暂时没法改,那接收端需要用BinaryFormatter反序列化Body字节,还原出原来的对象,再提取XML内容:
// 接收端代码(Microsoft.Azure.ServiceBus 2.0.0) using (var memoryStream = new MemoryStream(serviceBusMessage.Body)) { var formatter = new BinaryFormatter(); // 注意:接收端必须有发送端那个Message类的完整定义,包括序列化特性 var originalMsg = (Message)formatter.Deserialize(memoryStream); // 假设originalMsg里有你要的XML内容,比如叫XmlContent属性 string validXml = originalMsg.XmlContent; // 现在就可以正常处理XML了 }
⚠️ 小提示:如果发送端的Message类结构有变更,或者接收端的类定义和发送端不一致,BinaryFormatter会反序列化失败,这种方式适合发送端代码暂时不能动的场景。
方案2:修改发送端,直接发送纯XML字节
如果能改发送端代码,这是更稳妥的方式——直接把XML转成UTF8字节传给BrokeredMessage,避免自动序列化:
// 旧版WindowsAzure.ServiceBus 4.1.6发送端修改后的代码 private void SendToProcessingQueue(Guid accountId, Message msg) { string queueName = msg.MessageType.ToLower(); var client = CreateQueueClient(queueName); // 把XML内容直接转成UTF8字节 byte[] xmlBytes = Encoding.UTF8.GetBytes(msg.YourXmlProperty); // 用MemoryStream包装,第二个参数false表示不接管流,避免自动序列化 var brokeredMsg = new BrokeredMessage(new MemoryStream(xmlBytes), false); client.Send(brokeredMsg); }
这样修改后,接收端直接用Encoding.UTF8.GetString(serviceBusMessage.Body)就能拿到正常的XML了,完全不用额外处理。
额外情况处理
如果发送端之前是用BrokeredMessage的字符串构造函数(比如new BrokeredMessage(xmlString)),那它默认用的是DataContractSerializer序列化字符串,这时候接收端需要用DataContractSerializer来反序列化,而不是BinaryFormatter:
using (var stream = new MemoryStream(serviceBusMessage.Body)) { var serializer = new DataContractSerializer(typeof(string)); string xmlContent = (string)serializer.ReadObject(stream); }
总之,核心就是对齐发送端和接收端的序列化/反序列化方式,新旧SDK的消息处理逻辑差异很大,一定要注意这点!
内容的提问来源于stack exchange,提问作者Eivind Gussiås Løkseth

