I am fairly new to messaging and I have decided for a prototype that I am building to use EasyNetQ (RabbitMQ .Net).
I have created the Publisher and Subscriber and all seems to work well. I have the Publisher in my Web Services application catching all commands that are being sent to the DB. I have the Subscriber in a Console App picking up the messages.
However when the Subscriber picks up the Command objects, it throws the error:
A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.
In my prototype I have a Command class like such:
[Serializable]
public class Command
{
private Type _type;
private string _method;
private object[] _params;
public Command(){
}
public Command(Type type, string method, params object[] Params)
{
_type = type;
_method = method;
_params = Params;
}
public Command(Type type, string method, params object[] Params)
{
_type = type;
_method = method;
_params = Params;
}
public Type Type { get { return _type; } }
public string Method { get { return _method; } }
public object[] Params { get { return _params; } }
}
I am passing this command object to the Publisher:
public void Publish(Command message){
using(var publishChannel = RabbitManager.Instance.OpenPublishChannel()){
publishChannel.Publish(message);
}
}
The subscriber picks up the message:
public void SubscribeCommand(){
RabbitManager.Instance.Subscribe<Command>("my_subscription_id", msg => Console.WriteLine(msg.Method));
}
When I run this and the Command objects are processed by the Subscriber I get the error:
ERROR: Exception thrown by subscription calback.
Exchange: 'Entities_Command:BL'
Routing Key: ''
Redelivered: 'False'
Message:{"Type":"BL.DataAccess.XXX, BL, Version=1.2.0.0, Culture=neutral, PublicKeyToken=xxx","Method":"GET","Params":[1,true,3]}
BasicProperties:
ContentType=NULL, ContentEncoding=NULL, Headers=[], DeliveryMode=2, Priority=0, CorrelationId=8aa21f39-4020-4904-b90d-4cb123d3cac0, ReplyTo=NULL, Expiration=NULL, MessageId=NULL, Timestamp=0,Type=Entities_Command:BL, UserId=NULL, AppId=NULL, ClusterId=NULL
Exception: Newtonsoft.Json.JsonSerializationException: Unable to find a constructor to use for type Entities.Command. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute. Path 'Type', line 1, position 8. at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, String id, Boolean& createdFromNonDefaultConstructor) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType) at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings) at EasyNetQ.JsonSerializer.BytesToMessage[T](Byte[] bytes) at EasyNetQ.RabbitAdvancedBus.<>c_DisplayClass5`1.b_4(Byte[] body, MessageProperties properties, MessageReceivedInfo messageRecievedInfo) at EasyNetQ.Consumer.HandlerRunner.InvokeUserMessageHandler(ConsumerExecution Context context)
I have a default constructor in the Command class but I am still not sure why this is happening.
I have tried passing through just a Object type (rather than Command) which works fine.
Can someone explain what I am doing wrong here?