Reputation: 237
How can I read MSMQ messages from a VB.net Windows Service written in VB.net 2008. The messages in MQ contains XML data. I need to read that XML using LinQ to XML, Validate against XSD.
I would really appreciate if you can direct me to a sample
Thanks
Upvotes: 0
Views: 2515
Reputation: 411
I just wrote this exact thing, but since I bound my messages to a concrete class, the validation is automatic. Mind you, when you send an object in MSMQ as a message, it is still 'reduced' to XML... So in a way, I guess I'm doing what XSD would do, but in a much simpler way.
The 'service' part is probably irrelevant here, but I use services as both senders, receivers, and parsers for MSMQ.
Here is how I shepherd an object in MSMQ:
To understand reading, you need to understand how to send the object (XML, Class, whatever):
Note: SyslogEntry is a POCO with attributes for each part of a normal syslog/UDP514 message. No logic in that class.
Public Sub SendMessage(syslogEntry As SyslogEntryLibrary.syslog.SyslogEntry, qPath As String)
Try
' Connect to a queue on the local computer.
Me.TheQ = New MessageQueue(qPath)
' make all messages recoverable
Me.TheQ.DefaultPropertiesToSend.Recoverable = True
' Create a new message.
Me.MsgTo = New Message(syslogEntry, New XmlMessageFormatter(New Type() {GetType(SyslogEntryLibrary.syslog.SyslogEntry)}))
With Me.MsgTo
.AcknowledgeType = AcknowledgeTypes.PositiveReceive Or AcknowledgeTypes.PositiveArrival
' .Body = syslogEntry
.Priority = MessagePriority.Normal
End With
' set what will be sent with message...
TheQ.MessageReadPropertyFilter.ArrivedTime = True
TheQ.MessageReadPropertyFilter.SentTime = True
TheQ.MessageReadPropertyFilter.CorrelationId = True
TheQ.MessageReadPropertyFilter.Id = True
TheQ.Formatter = New XmlMessageFormatter(New Type() {GetType(SyslogEntryLibrary.syslog.SyslogEntry)})
TheQ.Send(MsgTo)
Catch ex As Exception
[...]
End Try
Return
The only interesting part of the above is this:
Me.MsgTo = New Message(syslogEntry, New XmlMessageFormatter(New Type(){GetType(SyslogEntryLibrary.syslog.SyslogEntry)}))
I am telling MSMQ the exact format the sent message will take, so it can break it up into XML for me in the Body of the Message. Oh, and one other thing, I try not to instantiate any objects when sending or receiving messages (preferring to re-use a class level variable) purely for speed & resources considerations. That is why you see things like "Me.TheQ", "Me.MsgTo", etc. No idea if this matters, but it's a practice/habit I've had for years... :)
Anyway, a typical message of this class looks like this:
You can see the class name, and some of the schema definitions in the Body. I have nothing to do with it-it's all done for me (with Reflection) :)
So now that my message (instance of a class, really) in on the queue, it's time to grab it from another program (maybe a service?) and reconstitute it!
Public Function ReceiveMessage(qPath As String) As SyslogEntryLibrary.syslog.SyslogEntry
Dim sysEvent As SyslogEntryLibrary.syslog.SyslogEntry = Nothing
Try
' Connect to the a queue on the local computer.
Me.rcvQueue = New MessageQueue(qPath)
Me.rcvQueue.MessageReadPropertyFilter.CorrelationId = True
' Set the formatter to indicate body contains a SyslogEntry instance
Me.rcvQueue.Formatter = New XmlMessageFormatter(New Type() {GetType(SyslogEntryLibrary.syslog.SyslogEntry)})
' Receive and format the message.
Dim myMessage As Message = Me.rcvQueue.Receive()
sysEvent = CType(myMessage.Body, SyslogEntryLibrary.syslog.SyslogEntry)
Catch ex As InvalidOperationException
[...]
Catch ex As Exception
[...]
End Try
Return sysEvent
End Function 'ReceiveMessage
So just like before, the magic happens in these lines:
Me.rcvQueue.Formatter = New XmlMessageFormatter(New Type(){GetType(SyslogEntryLibrary.syslog.SyslogEntry)})
Dim myMessage As Message = Me.rcvQueue.Receive()
sysEvent = CType(myMessage.Body, SyslogEntryLibrary.syslog.SyslogEntry)
I have seen examples that use XML as the body, and even just a string, so I'm sure you can play with this as you see fit.
Still, without understanding what you are trying to do, you'll forgive me if I suggest you stick with POCOs in your business logic, and let lower level tools like MSMQ do all the XML formatting for you. One thing I hate doing it writing XML in code 'manually'. :)
I hope this gives you a few ideas!
Upvotes: 0
Reputation: 13104
I would suggest looking into WCF using the MsmqIntegrationBinding. I've recently done the same (except using the netMsmqBinding since I was not integrating with a pre-existing system), and it has worked out very well. For samples, you should look at the WCF Samples provided by Microsoft.
Upvotes: 4