When trying to solve my issue with not receiving messages through RabbitMQ using Rebus, I tried playing with this sample: https://github.com/rebus-org/RebusSamples/tree/master/PubSubNative and found that the object, which is published from the publisher(pub) to the subscribers(subs), have to be the exact same shared object "StringMessage" for both subs and pub. It does not work when I create classes by the same name and properties in each project. I like it to not have the shared files but have their own classes - if it's possible?
Can't receive rebus rabbitMQ messages when the object which is published is not shared
59 Views Asked by Michael Winther At
2
There are 2 best solutions below
0

I Can Send messages to rebus using RabbitMQ Client only without rebus or shared message types from the sender. However on the receiving side I have all classes defined. And this usually one way.
I use this in .net 4.6 project windows forms application which just needs to send message.
I have this helper:
using System;
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;
using RabbitMQ.Client;
namespace CMIS.Helpers
{
public class RebusClient
{
public static void SendMessage<T>(string exchangeName, string queueName, string routingKey, Dictionary<string, object> headers, T message)
{
string[] qusvr = Context.Variables["QUSVR"].ToString().Split(':');
string hostName = qusvr[0];
string userName = qusvr[1];
string password = qusvr[2];
ConnectionFactory factory = new ConnectionFactory
{
HostName = hostName,
UserName = userName,
Password = password
};
using (IConnection connection = factory.CreateConnection("CMIS"))
{
using (IModel model = connection.CreateModel())
{
model.ExchangeDeclare(exchangeName, "direct", true, false, null);
model.QueueDeclare(queueName, true, false, false, null);
model.QueueBind(queueName, exchangeName, routingKey, null);
var messageBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(message));
IBasicProperties props = model.CreateBasicProperties();
props.Persistent = true;
props.ContentType = "text/plain";
props.DeliveryMode = 2;
props.Headers = headers;
model.BasicPublish(exchangeName, routingKey, props, messageBytes);
}
}
}
}
}
And then I can Send Message this way
string facilityCode = claimDetails["FacilityCode"].ToString();
int claimYear = claimDetails["ClaimYear"].ConvertTo<int>();
int claimMonth = claimDetails["ClaimMonth"].ConvertTo<int>();
string requestNo = string.Format("Queue-{0}-{1}{2}", facilityCode, claimYear, claimMonth < 10 ? $"0{claimMonth}" : claimMonth.ToString());
JObject message = new JObject(
new JProperty("$type", MessagingConstants.QueueUncapturedFolios),
new JProperty("RequestNo", requestNo),
new JProperty("FacilityCode", facilityCode),
new JProperty("ClaimYear", claimYear),
new JProperty("ClaimMonth", claimMonth)
);
Dictionary<string, object> headers = new Dictionary<string, object>
{
{ MessagingConstants.MessageTypeHeader, MessagingConstants.QueueUncapturedFolios },
{ MessagingConstants.ContentTypeHeader, MessagingConstants.ContentType }
};
RebusClient.SendMessage("RebusDirect", "online_claims_processing", "online_claims_processing", headers, message);
And here are the constants used
public static class MessagingConstants
{
public const string QueueDocuments = "NHIF.Shared.Messages.QueueDocuments,NHIF.Shared.Messages";
public const string QueueUncapturedFolios = "NHIF.Shared.Messages.QueueUncapturedFolios,NHIF.Shared.Messages";
public const string ProcessSkippedFolios = "NHIF.Shared.Messages.ProcessSkippedFolios,NHIF.Shared.Messages";
public const string CloseSubmissionWindow = "NHIF.Shared.Messages.CloseSubmissionWindow,NHIF.Shared.Messages";
public const string ContentType = "application/json;charset=utf-8";
public const string MessageTypeHeader = "rbs2-msg-type";
public const string ContentTypeHeader = "rbs2-content-type";
}
Although I might not be addressing your problem this way helps me evading sharing classes (Message Types) where there is no need for that. And in that way the message is serialized with all the headers and rebus will process them without any problem.
Raegards
Yes it's possible, but you'll have to circumvent the deserialization on the receiving end to somehow resolve the receiver's definition of
StringMessage
even though it's the sender'sStringMessage
that got serialized.You might want to check out the SharedNothing sample that demonstrates this particular thing.
The main part is the
CustomMessageDeserializer
that uses this dictionary to map from simple, assembly-qualified type names to the desired types.