问题
I am sending a message to a service bus topic using the logic app action "Send Message". When reading it in a console application, if i do this:
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);
It throws the following exception:
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]()
It turns out that the Logic App sends the message as a Stream instead of a string, that's why the exception is being thrown. Because, the console application is able to read the message if I do this:
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);
So, my question is, is there a way to make the logic app send the message as a string instead of a stream? Or is it a limitation of the Logic App?
I have tried with both "application/json", "System.String" and "text/plain" as content type of the message in Logic App action, it does not work.
回答1:
Unfortunately, it isn't possible to change how the body gets delivered. To address this, we updated our listener with a helper method that attempts to figure out which type the body is and extract accordingly:
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);
}
回答2:
Logic apps Service Bus connector dumps the data to service bus only as byte stream currently. It is not possible as per current design of Azure Logic Apps to send the message as a string
来源:https://stackoverflow.com/questions/48338448/sending-message-to-azure-service-bus-as-a-string-using-azure-logic-app