使用 azure 逻辑应用程序将消息作为字符串发送到 azure 服务总线
Sending message to azure service bus as a string using azure logic app
我正在使用逻辑应用操作 "Send Message" 向服务总线主题发送消息。在控制台应用程序中读取它时,如果我这样做:
SubscriptionClient subClient = SubscriptionClient.CreateFromConnectionString(connstr, topicName, subscriptionName);
OnMessageOptions options = new OnMessageOptions();
options.AutoComplete = true;
options.MaxConcurrentCalls = 1;
subClient.OnMessage((message) => {
string sjson = null;
try
{
sjson = message.GetBody<string>();
Console.WriteLine(sjson);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}, options);
它抛出以下异常:
System.Runtime.Serialization.SerializationException: There was an error deserializing the object of type System.String. The input source is not correctly formatted.
---> System.Xml.XmlException: The input source is not correctly formatted.
at System.Xml.XmlExceptionHelper.ThrowXmlException(XmlDictionaryReader reader, String res, String arg1, String arg2, String arg3)
at System.Xml.XmlBufferReader.ReadValue(XmlBinaryNodeType nodeType, ValueHandle value)at System.Xml.XmlBinaryReader.ReadNode()
at System.Xml.XmlBinaryReader.Read()
at System.Xml.XmlBaseReader.IsStartElement()
at System.Xml.XmlBaseReader.IsStartElement(XmlDictionaryString localName, XmlDictionaryString namespaceUri)
at System.Runtime.Serialization.XmlReaderDelegator.IsStartElement(XmlDictionaryString localname, XmlDictionaryString ns)
at System.Runtime.Serialization.XmlObjectSerializer.IsRootElement(XmlReaderDelegator reader, DataContract contract, XmlDictionaryString name, XmlDictionaryString ns)
at System.Runtime.Serialization.DataContractSerializer.InternalIsStartObject(XmlReaderDelegator reader)
at System.Runtime.Serialization.DataContractSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)--- End of inner exception stack trace ---at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)at System.Runtime.Serialization.DataContractSerializer.ReadObject(XmlDictionaryReader reader, Boolean verifyObjectName)
at Microsoft.ServiceBus.Messaging.DataContractBinarySerializer.ReadObject(XmlDictionaryReader reader, Boolean verifyObjectName)
at System.Runtime.Serialization.XmlObjectSerializer.ReadObject(XmlReader reader, Boolean verifyObjectName)at System.Runtime.Serialization.XmlObjectSerializer.InternalReadObject(XmlReaderDelegator reader, Boolean verifyObjectName)
at System.Runtime.Serialization.XmlObjectSerializer.InternalReadObject(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)at System.Runtime.Serialization.XmlObjectSerializer.ReadObject(XmlDictionaryReader reader)at Microsoft.ServiceBus.Messaging.DataContractBinarySerializer.ReadObject(Stream stream)
at Microsoft.ServiceBus.Messaging.BrokeredMessage.GetBody[T](XmlObjectSerializer serializer)
at Microsoft.ServiceBus.Messaging.BrokeredMessage.GetBody[T]()
事实证明,Logic App 将消息作为 Stream 而不是字符串发送,这就是抛出异常的原因。因为,如果我这样做,控制台应用程序能够读取消息:
SubscriptionClient subClient = SubscriptionClient.CreateFromConnectionString(connstr, topicName, subscriptionName);
OnMessageOptions options = new OnMessageOptions();
options.AutoComplete = true;
options.MaxConcurrentCalls = 1;
subClient.OnMessage((message) => {
Stream stream;
StreamReader reader;
string messageJson;
try
{
stream = message.GetBody<Stream>();
reader = new StreamReader(stream);
messageJson = reader.ReadToEnd();
Console.WriteLine(messageJson);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}, options);
所以,我的问题是,有没有办法让逻辑应用程序以字符串而不是流的形式发送消息?还是 Logic App 的限制?
我已经尝试将 "application/json"、"System.String" 和 "text/plain" 作为 Logic App 操作中消息的内容类型,但它不起作用。
逻辑应用程序服务总线连接器目前仅将数据作为字节流转储到服务总线。根据 Azure 逻辑应用程序的当前设计,不可能将消息作为字符串发送
遗憾的是,无法更改 body 的传送方式。为了解决这个问题,我们用一个辅助方法更新了我们的侦听器,该方法试图找出 body 是哪种类型并相应地提取:
private static JObject GetBody(BrokeredMessage brokeredMessage)
{
string objAsJson;
object objIsStream;
brokeredMessage.Properties.TryGetValue("isStream", out objIsStream);
bool bIsStream = objIsStream != null ? (bool)objIsStream : brokeredMessage.DeliveryCount % 2 == 0; // Default delivery method is String; Retry String as Stream if it fails
if (bIsStream)
{
// Azure Functions and Logic Apps send messages as Stream
// Service Bus Explorer defaults to Stream but can send as String
Stream stream = brokeredMessage.GetBody<Stream>();
StreamReader reader = new StreamReader(stream);
objAsJson = reader.ReadToEnd();
}
else
{
// Our services send messages as String
objAsJson = brokeredMessage.GetBody<string>();
}
return JObject.Parse(objAsJson);
}
我正在使用逻辑应用操作 "Send Message" 向服务总线主题发送消息。在控制台应用程序中读取它时,如果我这样做:
SubscriptionClient subClient = SubscriptionClient.CreateFromConnectionString(connstr, topicName, subscriptionName);
OnMessageOptions options = new OnMessageOptions();
options.AutoComplete = true;
options.MaxConcurrentCalls = 1;
subClient.OnMessage((message) => {
string sjson = null;
try
{
sjson = message.GetBody<string>();
Console.WriteLine(sjson);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}, options);
它抛出以下异常:
System.Runtime.Serialization.SerializationException: There was an error deserializing the object of type System.String. The input source is not correctly formatted.
---> System.Xml.XmlException: The input source is not correctly formatted.
at System.Xml.XmlExceptionHelper.ThrowXmlException(XmlDictionaryReader reader, String res, String arg1, String arg2, String arg3)
at System.Xml.XmlBufferReader.ReadValue(XmlBinaryNodeType nodeType, ValueHandle value)at System.Xml.XmlBinaryReader.ReadNode()
at System.Xml.XmlBinaryReader.Read()
at System.Xml.XmlBaseReader.IsStartElement()
at System.Xml.XmlBaseReader.IsStartElement(XmlDictionaryString localName, XmlDictionaryString namespaceUri)
at System.Runtime.Serialization.XmlReaderDelegator.IsStartElement(XmlDictionaryString localname, XmlDictionaryString ns)
at System.Runtime.Serialization.XmlObjectSerializer.IsRootElement(XmlReaderDelegator reader, DataContract contract, XmlDictionaryString name, XmlDictionaryString ns)
at System.Runtime.Serialization.DataContractSerializer.InternalIsStartObject(XmlReaderDelegator reader)
at System.Runtime.Serialization.DataContractSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)--- End of inner exception stack trace ---at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)at System.Runtime.Serialization.DataContractSerializer.ReadObject(XmlDictionaryReader reader, Boolean verifyObjectName)
at Microsoft.ServiceBus.Messaging.DataContractBinarySerializer.ReadObject(XmlDictionaryReader reader, Boolean verifyObjectName)
at System.Runtime.Serialization.XmlObjectSerializer.ReadObject(XmlReader reader, Boolean verifyObjectName)at System.Runtime.Serialization.XmlObjectSerializer.InternalReadObject(XmlReaderDelegator reader, Boolean verifyObjectName)
at System.Runtime.Serialization.XmlObjectSerializer.InternalReadObject(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)at System.Runtime.Serialization.XmlObjectSerializer.ReadObject(XmlDictionaryReader reader)at Microsoft.ServiceBus.Messaging.DataContractBinarySerializer.ReadObject(Stream stream)
at Microsoft.ServiceBus.Messaging.BrokeredMessage.GetBody[T](XmlObjectSerializer serializer)
at Microsoft.ServiceBus.Messaging.BrokeredMessage.GetBody[T]()
事实证明,Logic App 将消息作为 Stream 而不是字符串发送,这就是抛出异常的原因。因为,如果我这样做,控制台应用程序能够读取消息:
SubscriptionClient subClient = SubscriptionClient.CreateFromConnectionString(connstr, topicName, subscriptionName);
OnMessageOptions options = new OnMessageOptions();
options.AutoComplete = true;
options.MaxConcurrentCalls = 1;
subClient.OnMessage((message) => {
Stream stream;
StreamReader reader;
string messageJson;
try
{
stream = message.GetBody<Stream>();
reader = new StreamReader(stream);
messageJson = reader.ReadToEnd();
Console.WriteLine(messageJson);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}, options);
所以,我的问题是,有没有办法让逻辑应用程序以字符串而不是流的形式发送消息?还是 Logic App 的限制?
我已经尝试将 "application/json"、"System.String" 和 "text/plain" 作为 Logic App 操作中消息的内容类型,但它不起作用。
逻辑应用程序服务总线连接器目前仅将数据作为字节流转储到服务总线。根据 Azure 逻辑应用程序的当前设计,不可能将消息作为字符串发送
遗憾的是,无法更改 body 的传送方式。为了解决这个问题,我们用一个辅助方法更新了我们的侦听器,该方法试图找出 body 是哪种类型并相应地提取:
private static JObject GetBody(BrokeredMessage brokeredMessage)
{
string objAsJson;
object objIsStream;
brokeredMessage.Properties.TryGetValue("isStream", out objIsStream);
bool bIsStream = objIsStream != null ? (bool)objIsStream : brokeredMessage.DeliveryCount % 2 == 0; // Default delivery method is String; Retry String as Stream if it fails
if (bIsStream)
{
// Azure Functions and Logic Apps send messages as Stream
// Service Bus Explorer defaults to Stream but can send as String
Stream stream = brokeredMessage.GetBody<Stream>();
StreamReader reader = new StreamReader(stream);
objAsJson = reader.ReadToEnd();
}
else
{
// Our services send messages as String
objAsJson = brokeredMessage.GetBody<string>();
}
return JObject.Parse(objAsJson);
}