Skip to content

Commit b499630

Browse files
Add ability to bind to a string value body message. (Azure#20378)
* Add ability to bind to a string value body message. * PR FB
1 parent 9d86570 commit b499630

File tree

2 files changed

+69
-34
lines changed

2 files changed

+69
-34
lines changed

sdk/servicebus/Microsoft.Azure.WebJobs.Extensions.ServiceBus/src/Triggers/MessageToStringConverter.cs

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,71 +2,69 @@
22
// Licensed under the MIT License. See License.txt in the project root for license information.
33

44
using System;
5-
using System.Globalization;
65
using System.IO;
76
using System.Text;
8-
using System.Threading;
9-
using System.Threading.Tasks;
7+
using Azure.Core.Amqp;
108
using Azure.Messaging.ServiceBus;
119
using Microsoft.Azure.WebJobs.Extensions.ServiceBus.Triggers;
1210

1311
namespace Microsoft.Azure.WebJobs.ServiceBus.Triggers
1412
{
15-
internal class MessageToStringConverter : IAsyncConverter<ServiceBusReceivedMessage, string>
13+
internal class MessageToStringConverter : IConverter<ServiceBusReceivedMessage, string>
1614
{
17-
public async Task<string> ConvertAsync(ServiceBusReceivedMessage input, CancellationToken cancellationToken)
15+
public string Convert(ServiceBusReceivedMessage input)
1816
{
1917
if (input == null)
2018
{
2119
throw new ArgumentNullException(nameof(input));
2220
}
23-
if (input.Body == null)
24-
{
25-
return null;
26-
}
27-
28-
Stream stream = input.Body.ToStream();
2921

30-
TextReader reader = new StreamReader(stream, StrictEncodings.Utf8);
31-
try
22+
var body = input.GetRawAmqpMessage().Body;
23+
if (body.BodyType == AmqpMessageBodyType.Data)
3224
{
33-
cancellationToken.ThrowIfCancellationRequested();
25+
if (input.Body == null)
26+
{
27+
return null;
28+
}
29+
3430
try
3531
{
36-
return await reader.ReadToEndAsync().ConfigureAwait(false);
32+
return StrictEncodings.Utf8.GetString(input.Body.ToArray());
3733
}
3834
catch (DecoderFallbackException)
3935
{
4036
// we'll try again below
4137
}
4238

43-
// We may get here if the message is a string yet was DataContract-serialized when created. We'll
44-
// try to deserialize it here using GetBody<string>(). This may fail as well, in which case we'll
45-
// provide a decent error.
46-
39+
// We may get here if the message is a string yet was DataContract-serialized when created.
4740
try
4841
{
42+
using Stream stream = input.Body.ToStream();
4943
var serializer = DataContractBinarySerializer<string>.Instance;
5044
stream.Position = 0;
51-
return (string)serializer.ReadObject(stream);
45+
return (string) serializer.ReadObject(stream);
5246
}
5347
catch
5448
{
5549
// always possible to get a valid string from the message
5650
return input.Body.ToString();
5751
}
5852
}
59-
finally
53+
else if (body.BodyType == AmqpMessageBodyType.Value)
6054
{
61-
if (stream != null)
62-
{
63-
stream.Dispose();
64-
}
65-
if (reader != null)
55+
body.TryGetValue(out object value);
56+
if (value is string stringValue)
6657
{
67-
reader.Dispose();
58+
return stringValue;
6859
}
60+
61+
throw new NotSupportedException(
62+
$"A message with a body of type {value?.GetType()} cannot be bound to a string.");
63+
}
64+
else
65+
{
66+
throw new NotSupportedException("A sequence body message cannot be bound to a string.");
6967
}
7068
}
7169
}
72-
}
70+
}

sdk/servicebus/Microsoft.Azure.WebJobs.Extensions.ServiceBus/tests/MessageToStringConverterTests.cs

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
// Licensed under the MIT License. See License.txt in the project root for license information.
33

44
using System;
5+
using System.Collections.Generic;
56
using System.IO;
67
using System.Text;
78
using System.Threading;
89
using System.Threading.Tasks;
10+
using Azure.Core.Amqp;
911
using Microsoft.Azure.WebJobs.ServiceBus.Triggers;
1012
using NUnit.Framework;
1113
using Azure.Messaging.ServiceBus;
@@ -25,7 +27,7 @@ public class MessageToStringConverterTests
2527
[TestCase(null, TestJson)]
2628
[TestCase("application/xml", TestJson)]
2729
[TestCase(ContentTypes.TextPlain, null)]
28-
public async Task ConvertAsync_ReturnsExpectedResult_WithBinarySerializer(string contentType, string value)
30+
public void Convert_ReturnsExpectedResult_WithBinarySerializer(string contentType, string value)
2931
{
3032
byte[] bytes;
3133
using (MemoryStream ms = new MemoryStream())
@@ -37,7 +39,7 @@ public async Task ConvertAsync_ReturnsExpectedResult_WithBinarySerializer(string
3739
ServiceBusReceivedMessage message = ServiceBusModelFactory.ServiceBusReceivedMessage(body: new BinaryData(bytes), contentType: contentType);
3840

3941
MessageToStringConverter converter = new MessageToStringConverter();
40-
string result = await converter.ConvertAsync(message, CancellationToken.None);
42+
string result = converter.Convert(message);
4143

4244
Assert.AreEqual(value, result);
4345
}
@@ -50,14 +52,14 @@ public async Task ConvertAsync_ReturnsExpectedResult_WithBinarySerializer(string
5052
[TestCase("application/xml", TestJson)]
5153
[TestCase(ContentTypes.TextPlain, null)]
5254
[TestCase(ContentTypes.TextPlain, "")]
53-
public async Task ConvertAsync_ReturnsExpectedResult_WithSerializedString(string contentType, string value)
55+
public void Convert_ReturnsExpectedResult_WithSerializedString(string contentType, string value)
5456
{
5557
ServiceBusReceivedMessage message = ServiceBusModelFactory.ServiceBusReceivedMessage(
5658
body: value == null ? null : new BinaryData(value),
5759
contentType: contentType);
5860

5961
MessageToStringConverter converter = new MessageToStringConverter();
60-
string result = await converter.ConvertAsync(message, CancellationToken.None);
62+
string result = converter.Convert(message);
6163
// A received message will never have a null body as a body section is required when sending even if it
6264
// is empty. This was true in Track 1 as well, but in Track 1 the actual body property could be null when
6365
// constructing the message, but in practice it wouldn't be null when receiving.
@@ -72,7 +74,7 @@ public async Task ConvertAsync_ReturnsExpectedResult_WithSerializedString(string
7274
}
7375

7476
[Test]
75-
public async Task ConvertAsync_ReturnsExpectedResult_WithSerializedObject()
77+
public void Convert_ReturnsExpectedResult_WithSerializedObject()
7678
{
7779
byte[] bytes;
7880
using (MemoryStream ms = new MemoryStream())
@@ -84,10 +86,45 @@ public async Task ConvertAsync_ReturnsExpectedResult_WithSerializedObject()
8486
ServiceBusReceivedMessage message = ServiceBusModelFactory.ServiceBusReceivedMessage(body: new BinaryData(bytes));
8587

8688
MessageToStringConverter converter = new MessageToStringConverter();
87-
string result = await converter.ConvertAsync(message, CancellationToken.None);
89+
string result = converter.Convert(message);
8890
Assert.AreEqual(message.Body.ToString(), result);
8991
}
9092

93+
[Test]
94+
public void Convert_ValueBodyMessage_String()
95+
{
96+
ServiceBusReceivedMessage message = ServiceBusModelFactory.ServiceBusReceivedMessage();
97+
message.GetRawAmqpMessage().Body = AmqpMessageBody.FromValue("value");
98+
99+
MessageToStringConverter converter = new MessageToStringConverter();
100+
string result = converter.Convert(message);
101+
Assert.AreEqual("value", result);
102+
}
103+
104+
[Test]
105+
public void Convert_ValueBodyMessage_NonStringThrows()
106+
{
107+
ServiceBusReceivedMessage message = ServiceBusModelFactory.ServiceBusReceivedMessage();
108+
message.GetRawAmqpMessage().Body = AmqpMessageBody.FromValue(5);
109+
110+
MessageToStringConverter converter = new MessageToStringConverter();
111+
Assert.That(
112+
() => converter.Convert(message),
113+
Throws.InstanceOf<NotSupportedException>());
114+
}
115+
116+
[Test]
117+
public void Convert_SequenceBodyMessage_Throws()
118+
{
119+
ServiceBusReceivedMessage message = ServiceBusModelFactory.ServiceBusReceivedMessage();
120+
message.GetRawAmqpMessage().Body = AmqpMessageBody.FromSequence(new IList<object>[]{ new object[] {"sequence"}});
121+
122+
MessageToStringConverter converter = new MessageToStringConverter();
123+
Assert.That(
124+
() => converter.Convert(message),
125+
Throws.InstanceOf<NotSupportedException>());
126+
}
127+
91128
[Serializable]
92129
public class TestObject
93130
{

0 commit comments

Comments
 (0)