views:

120

answers:

2

Hi Guys,

for the context setting, I am exchanging messages between my nServiceBus client and nSerivceBus server. its is the namespace xyz.Messages and and a class, Message : IMessage

I have more messages that are in the other dlls, like xyz.Messages.Domain1, xyz.Messages.Domain2, xyz.Messages.Domain3. and messages that derive form that base message, Message.

I have the endpoints defined as like :

 at client
<UnicastBusConfig>
 <MessageEndpointMappings>
    <add Messages="xyz.Messages" Endpoint="xyzServerQueue" />
    <add Messages="xyz.Messages.Domain1" Endpoint="xyzServerQueue" />
    <add Messages="xyz.Messages.Domain2" Endpoint="xyzServerQueue" />
  </MessageEndpointMappings>
</UnicastBusConfig>

at Server

<UnicastBusConfig>
 <MessageEndpointMappings>
   <add Messages="xyz.Messages" Endpoint="xyzClientQueue" />
   <add Messages="xyz.Messages.Domain1" Endpoint="xyzClientQueue" />
   <add Messages="xyz.Messages.Domain2" Endpoint="xyzClientQueue" />
 </MessageEndpointMappings>
</UnicastBusConfig>

and the bus initialized as

        IBus serviceBus = Configure.With()
            .SpringBuilder()
            .XmlSerializer()
            .MsmqTransport()
            .UnicastBus()
            .LoadMessageHandlers()
            .CreateBus()
            .Start();

now when i try sending instance of Message type or any type derived types of Message, it successfully sends the message over and at the server, i get the proper type.

eg.

Message message= new Message();
Bus.Send(message); // works fine, transfers Message type
message = new MessageDerived1();
Bus.Send(message); // works fine, transfers MessageDerived1 type
message = new MessageDerived2();
Bus.Send(message); // works fine, transfers MessageDerived2 type

My problem arises when any type, say MessageDerived1, contains a member variable of type Message, and when i assign it to a derived type, the type is not properly transferred over the wire. It transfers only as Message type, not the derived type.

public class MessageDerived2 : Message
{
  public Message message;
}

MessageDerived2 messageDerived2= new MessageDerived2();
messageDerived2.message = new MessageDerived1();
message = messageDerived2;
Bus.Send(message); // incorrect behaviour, transfers MessageDerived2 correctly, but looses type of  MessageDerived2.Message (it deserializes as Message type, instead of MessageDerived1)

any help is strongly appreciated.

Thanks TJ

+1  A: 

The NServiceBus XmlSerializer does not support this - see the thread at http://tech.groups.yahoo.com/group/nservicebus/message/6549

BinarySerializer will work, or you can implement a custom message serialiser. In my opinion DataContractSerializer should be available out of the box for serialisation scenarios that XmlSerializer doesn't handle.

Note that by doing this you'll probably lose the NSB message versioning support - if this is important to you, I'd suggest rethinking your message design.

Sam
+1  A: 

Here is Udi's reply

First of all, it is highly unusual to have the client queues appear in the server's config. I'd recommend removing that.

Second, I assume that you're not using the generic host as you're manually initializing the bus - that's fine, just wanted to check. Also, are you using the same code for both client and server side initialization? That isn't particularly recommended. At the very least, the server side should be transactional (unless you're going down some idempotent messaging route).

Third, what you're trying to do should work just fine if you use the Binary Serializer. The reason is the assumption of tighter coupling and less of a need for explicit message contracts. The XML Serializer, on the other hand, is built to enforce more explicit message schema - therefore not supporting those kinds of derived types.

The scenarios where you might want to use derived types in your messages (queries, straight data manipulation, etc) are usually the areas where you shouldn't be using messaging to begin with.

Hope that helps in some way.

-- Udi Dahan

Tiju John