Search code examples
c#msmqbinaryformatter

msmq using binaryformatter


I have a component that writes to a Queue (here's the code):

using (MessageQueueTransaction transaction = new MessageQueueTransaction())
            {
                transaction.Begin();
                using (var queue = new MessageQueue(@fullQueue, QueueAccessMode.Send))
                {
                    BinaryMessageFormatter formatter = new BinaryMessageFormatter();
                   // XmlMessageFormatter formatter = new XmlMessageFormatter(new Type[] { typeof(Testing) });

                    var testing = new Testing {myBody = string.Format("Hello {0}",Environment.UserName), myMessageText = "Header"};
                    var message = new Message
                    {
                        Body = testing,
                        Label = Environment.MachineName,
                        UseDeadLetterQueue = true,
                        Recoverable = true,
                        Formatter = formatter
                    };
                    queue.Send(message, MessageQueueTransactionType.Single);

                } 
                transaction.Commit(); 

            }

Now When I run the above 'Testing' is simply a Serializble object with 2 properties on it. If I look at the body of the text on the Queue it looks ok.

Now I have a separate component to read from the queue :

 BinaryMessageFormatter formatter = new BinaryMessageFormatter();
       // XmlMessageFormatter formatter = new XmlMessageFormatter(new Type[] { typeof(Testing) });
        MessageQueue msgQ = new MessageQueue(fullQueue, QueueAccessMode.Receive);

        try
        {

            using (TransactionScope transaction = new TransactionScope())
            {

                Message incoming = new Message { Formatter = formatter, AcknowledgeType = AcknowledgeTypes.FullReceive };

                incoming =  msgQ.Receive(new TimeSpan(0, 0, 3),MessageQueueTransactionType.Single);
               // var ttt = incoming.Body;
                MemoryStream mem = (MemoryStream) incoming.BodyStream;
                mem.Seek(0, SeekOrigin.Begin);
                IFormatter ifm = new BinaryFormatter();
                Testing tt = (Testing)ifm.Deserialize(mem);

                transaction.Complete();
            }

        }

Now at the point I'm performing the ifm.Deserialize, It errors with

Unable to find assembly 'MSMQWrite, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' Where MSMQWrite is the Method name within my write component.

When Writing to the queue I thought I might have to explicitly serialize the object first so on my component that writes I changed my code slightly to be:

var testing = new Testing {myBody = string.Format("Hello {0}",Environment.UserName), myMessageText = "Header"};
                    MemoryStream mem = new MemoryStream();

                    BinaryFormatter bf = new BinaryFormatter();
                    bf.Serialize(mem,testing);

                    var message = new Message
                    {   BodyStream = mem,
                        //Body = testing,
                        Label = Environment.MachineName,
                        UseDeadLetterQueue = true,
                        Recoverable = true,
                        Formatter = formatter
                    };
                    queue.Send(message, MessageQueueTransactionType.Single);

As you can see I'm setting the BodyStream directly this time, but I still receive the same error when trying to read from the queue.


Solution

  • You need to reference the assembly that contains the Testing class from your second component. I guess that assembly is MSMQWrite. If you already reference it make sure that is being copied to the folder from where the second component is running so it can be found at runtime.

    Other option is to move the actual class being serialised to a different component (e.g. MSMQCommon) and reference it from both your component writing and the one reading. Or just have one component.