Okay so I have a problem with using MassTransit and it's deserialization.
We're publishing messages into a specific queue with RabbitMQ, which should then be further processed by our background services using MassTransit.
The string coming in through the queue looks as following
{
"routingKey": "article.put",
"responseQueue": {
"exchange": "testexchange_gateway",
"responseRoutingKey": "gatewayResponseQueue",
"vhost": "testvhost"
},
"deviceProperties": {
"deviceType": "DESKTOP",
"deviceSize": {
"width": 10,
"height": 10
},
"javascriptEnabled": false
},
"action": "PUT",
"transactionId": "62b6174d-04b7-4937-b617-4d04b70937b0",
"contentType": "application/json",
"body": "Testmessage published while running"
}
With the Contract looking like
```
public interface IMessage
{
string routingKey { get; set; }
ResponseQueue responseQueue { get; set; }
DeviceProperties deviceProperties { get; set; }
string action { get; set; }
string transactionId { get; set; }
string contentType { get; set; }
string body { get; set; }
}
public interface ResponseQueue
{
string exchange { get; set; }
string responseRoutingKey { get; set; }
string vhost { get; set; }
}
public interface DeviceProperties
{
string deviceType { get; set; }
DeviceSize deviceSize { get; set; }
bool javascriptEnabled { get; set; }
}
public interface DeviceSize
{
int width { get; set; }
int height { get; set; }
}
My problem now is, whenever I want to consume that message using MassTransit, I will get an error in my _error queue:
MT-Fault-ExceptionType: | System.ArgumentNullException
-- | --
Value cannot be null.聽Parameter name: source
at System.Linq.Enumerable.ToArrayTSource聽at MassTransit.Serialization.JsonConsumeContext..ctor(JsonSerializer deserializer, IObjectTypeDeserializer objectTypeDeserializer, ReceiveContext receiveContext, MessageEnvelope envelope)聽at MassTransit.Serialization.JsonMessageDeserializer.MassTransit.IMessageDeserializer.Deserialize(ReceiveContext receiveContext)
which I don't quite understand, as all values needed should be right there.
My consumer:
class ArticleGetConsumer : IConsumer
{
public Task Consume(ConsumeContext
{
var routingKey = context.Message.routingKey;
return Task.FromResult(0);
}
}
```
You need to wrap that message in an envelope. The format is detailed in the interoperability documentation:
http://masstransit-project.com/MassTransit/advanced/interoperability.html
Should look like this:
{
"destinationAddress": "rabbitmq://localhost/input_queue",
"headers": {},
"messageType": [
"urn:message:YourProject.Messages:IMessage"
],
"message": {
"routingKey": "article.put",
"responseQueue": {
"exchange": "testexchange_gateway",
"responseRoutingKey": "gatewayResponseQueue",
"vhost": "testvhost"
},
"deviceProperties": {
"deviceType": "DESKTOP",
"deviceSize": {
"width": 10,
"height": 10
},
"javascriptEnabled": false
},
"action": "PUT",
"transactionId": "62b6174d-04b7-4937-b617-4d04b70937b0",
"contentType": "application/json",
"body": "Testmessage published while running"
}
}
Thanks for the quick answer, will try this tomorrow and report back!
Okay so about the envelope, I get what it is for and why it's needed but, and I have searched thouroughly (and only found people saying that you need to wrap it in an envelope rather than how to do it), I can't seem to figure out as to how to properly wrap it. I could just set together the string manually but I don't think that's how it's meant to be, there has to be an easier way to do this.
How would I go about wraping it up?
Just look at how MT does it, throw the object into a wrapper object (envelope) before serializing it to JSON from your message producer: https://github.com/MassTransit/MassTransit/blob/develop/src/MassTransit/Serialization/JsonMessageSerializer.cs#L97
@kninib12 did you get it working?
Hello,
My issue is the same. The messages are published by python code which publishes the plain application level message with no mass transit specific attributes in the json.
Is there a way to still consume the messages from the queue, if published by a non mass transit type client? I get a serialization error :
StackTrace: | at System.Linq.Enumerable.ToArray[TSource](IEnumerable1 source)聽at MassTransit.Serialization.JsonConsumeContext..ctor(JsonSerializer deserializer, IObjectTypeDeserializer objectTypeDeserializer, ReceiveContext receiveContext, MessageEnvelope envelope)聽at MassTransit.Serialization.JsonMessageDeserializer.MassTransit.IMessageDeserializer.Deserialize(ReceiveContext receiveContext)
Thanks a lot
Yes, you can write your own deserializer - there isn't anything to fix in MT with this issue.
Yes, that would be one solution. We have decided to rather port the python components to c#.
I am having the same issue.
I am trying to receive the message from rabbitmq were other application pushes data.
The data example is:
{"database":"test","table":"maxwell","type":"insert","ts":1582193439,"xid":6534,"commit":true,"data":{"id":1,"daemon":"Stanislaw Lem"}}
However I only see this error:
System.Runtime.Serialization.SerializationException: An exception occurred while deserializing the message envelope
---> System.ArgumentNullException: Value cannot be null. (Parameter 'source')
at System.Linq.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument)
at System.Linq.Enumerable.ToArrayTSource
at GreenPipes.Filters.RescueFilter2.GreenPipes.IFilter<TContext>.Send(TContext context, IPipe1 next)
The contract looks like this:
public class DatabaseChangeDto: IDatabaseChangeContract { public string Database { get; set; } public string Table { get; set; } public string Type { get; set; } public DateTime Ts { get; set; } public long Xid { get; set; } public bool Commit { get; set; } public object Data { get; set; } }
You need to wrap that message in an envelope. The format is detailed in the interoperability documentation:
http://masstransit-project.com/MassTransit/advanced/interoperability.html
Updated URL
https://masstransit-project.com/architecture/interoperability.html
Most helpful comment
Should look like this: