I have troubles consuming messages that contain IEnumerable properties.
The following error is recorded by JSON deserializer while retrieving a message from the queue:
MassTransit.Transports.Endpoint [Unrecognized message loopback://localhost/queue:e0170000-6eea-80c1-a100-08d1ec9d3485]
System.Runtime.Serialization.SerializationException: Failed to deserialize the message ---> Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.IEnumerable`1[ComTrade.Travel.MyWay.MyWayAppTest.External.MassTransitIssuesTests+SomeClass]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
I haven't found anything similar being noticed yet by anyone, so I guess I must be doing something wrong. Could you please point me in the right direction?
If I change the message contract to use generic List instead of an IEnumerable, the deserialization works as expected. However, I don't want to be forced to change the entire domain model just to enable passing it through the message queue.
Here is the entire sample code to reproduce the problem:
/// <summary>
/// The mass transit issues tests.
/// </summary>
[TestFixture]
public class MassTransitIssuesTests
{
/// <summary>
/// Test the serialization of a property containing an enumerable list.
/// </summary>
[Test]
public void DeserializeEnumerables()
{
var bus = ServiceBusFactory.New(sbc =>
{
sbc.ReceiveFrom("loopback://localhost/queue");
sbc.UseLog4Net();
sbc.Subscribe(subs =>
{
subs.Handler<TestRequest>((cxt, msg) =>
{
cxt.Respond(new TestResponse { Text = "RESP" + msg.Text });
});
});
});
Assert.IsNotNull(bus);
try
{
bus.PublishRequest(
new TestRequest { Text = "whatever", ListOfSomeClasses = new List<SomeClass>(new[] { new SomeClass { Value = "Some value" }, }) },
x =>
{
x.Handle<TestResponse>(message => Console.WriteLine(message.Text));
x.SetTimeout(new TimeSpan(0, 0, 10));
});
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
bus.Dispose();
}
}
/// <summary>
/// Basic test request message.
/// </summary>
public class TestRequest
{
/// <summary>
/// Gets or sets the text.
/// </summary>
public string Text { get; set; }
/// <summary>
/// Gets or sets the list of some classes.
/// </summary>
public IEnumerable<SomeClass> ListOfSomeClasses { get; set; }
}
/// <summary>
/// Basic test response message.
/// </summary>
public class TestResponse
{
/// <summary>
/// Gets or sets the text.
/// </summary>
public string Text { get; set; }
}
/// <summary>
/// The some class.
/// </summary>
public class SomeClass
{
/// <summary>
/// Gets or sets the value.
/// </summary>
public string Value { get; set; }
}
}
Thanks in advance!
Regards,
Thomas