msmqlinq-to-xsd

Element is not an instance of type


I am using Linq To XSD to send data over MSMQ. Here is my sending code

public void Send()
        {
            string criMessageQueuePath = ConfigurationManager.AppSettings["CRIMessageQueuePath"];

            if (!MessageQueue.Exists(criMessageQueuePath))
            {
                MessageQueue.Create(criMessageQueuePath, false);
            }

            var messageQueue = new MessageQueue(criMessageQueuePath) { Label = "CRI Message Queue" };
            messageQueue.Formatter = new XmlMessageFormatter(new[] { typeof(XML) });

            var transaction = new MessageQueueTransaction();

            transaction.Begin();

            messageQueue.Send(CreateAuction(1), transaction);
            messageQueue.Send(CreateAuction(2), transaction);
            messageQueue.Send(CreateAuction(3), transaction);
            messageQueue.Send(CreateAuction(4), transaction);
            messageQueue.Send(CreateAuction(5), transaction);

            transaction.Commit();
        }

        private XML CreateAuction(int id)
        {
            var message = new XML {id = id};
            return message;
        }

Here is my receiving code

public IEnumerable<string> Receive()
        {
            string criMessageQueuePath = ConfigurationManager.AppSettings["CRIMessageQueuePath"];

        var messageQueue = new MessageQueue(criMessageQueuePath);

        Message[] messages = messageQueue.GetAllMessages();

        foreach (Message message in messages)
        {
            message.Formatter = new XmlMessageFormatter(new[] { typeof(XML) });
            yield return message.Body.ToString();
        }

        messageQueue.Purge();
    }

I've tried lots of variations of this code but can't figure out why I can't get a valid XML object out the other end.

Currently, my code is failing when I call it

static void Main()
        {
            var sender = new Sender.Sender();
            sender.Send();

            var receiver = new Receiver.Receiver();
            foreach (var xml in receiver.Receive())
            {
                var typedXML = XML.Parse(xml);
                Console.WriteLine(typedXML.id);
            }
        }

The line it fails on is var typedXML = XML.Parse(xml);. The error is

Element is not an instance of type Domain.XML

The XSD for the object is

<?xml version="1.0" encoding="Windows-1252"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="Domain">
  <xs:element name="XML">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="id" type="xs:int" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Looking at the value of xml on the line

var typedXML = XML.Parse(xml);

I can see that it generates this

"<XML>\r\n  <XML xmlns=\"Domain\">\r\n    <id>1</id>\r\n  </XML>\r\n</XML>"

In other words it generates an additional xml node around the whole xml. If I remove this extra node in the debugger then it all works. what am I doing wrong?


Solution

  • This is the result of using hte XmlMessageFormatter as it serializes your object and wraps it in XML. I would suggest that you write your XML document directly to the BodyStream property instead.

    var msg = new Message();
    var writer = new StreamWriter(msg.BodyStream);
    
    writer.Write(xmlDoc.ToString());
    writer.Flush();
    
    queue.Send(msg);
    

    This way you have full Control over what is sent in your queue. The formatters are mostly there for legacy use and should not be used when sending XML documents as messages.