Click here to Skip to main content
Click here to Skip to main content

Sample Starter Project Using WCF and MSMQ

By , 4 Jan 2009
 

Introduction

As part of a project I was working on, I was tasked with developing a web service based on Windows Communication Foundation (WCF) as a frontend to an MSMQ queue. It was an opportunity to learn a new technology, and I eagerly looked around for examples.

My initial attempts were quite frustrating. I found some samples on the web, but just could not get them to work. The terminology was quite confusing. My pace improved significantly when I found an excellent starter project on Dennis van der Stelt’s blog. I would enthusiastically recommend this to anyone who is just getting started with WCF. I finally found a sample demonstrating the use of WCF to submit messages to a queue, on MSDN’s Windows Communication Foundation to Message Queuing page.

My manager suggested simplifying the application to simply queue an XML message rather than an object (PurchaseOrder), as shown in the article. This allows for the WCF service to act as an agnostic router, with no need to read or interpret the contents of the message placed on the queue. This project is the prototype that I created by piggy-backing on the MSDN example. I strongly recommend that a reader seeking to get started on WCF look at the original example in addition to the solution attached to this article.

Reviewing the code

Let’s start at the end, so we know where we are going right from the start.

This is what you see on the Client console

The screen above shows a client application that has successfully submitted an XML document as a string to a WCF service. That is all that the client does, i.e., build an XML string and submit it to the service.

This is what you see on the Service Console

The output of the WCF service shows output from two components. The first two lines provide confirmation that our WCF service is up and running. The rest of the lines are output by an asynchronous processor that monitors the message queue. In this case, it simply outputs routing information from the MSMQ message label and the contents of the XML message. Note, the message can be any valid XML document; the processor does not care about its contents. The processor could be extended to deliver the message to any one of multiple endpoints based on the destination specified in the MSMQ message label. If this approximates the functionality you are seeking, then read on as we delve into the code that makes this solution possible.

The client

The client is a simple project that creates the XML message. I chose to read in the outline of the message from a file on disk. I then merge my sample data with the outline. The following code illustrates these actions:

//Line 1
string fileTemplate = 
  ConfigurationManager.AppSettings["ShipperTxnTemplate"];
fileDoc.Load(fileTemplate);
if (fileDoc.DocumentElement == null)
    return;

string trnID = "00001001"; //Line 6
XmlNode rootNode = fileDoc.LastChild.LastChild.FirstChild;
rootNode.Attributes["txnid"].Value = trnID;
rootNode.Attributes["status"].Value = "Queued For Submission";
rootNode.Attributes["submitdate"].Value = DateTime.Now.ToString();

XmlNode fileNode = rootNode.FirstChild;
fileNode.Attributes["CompanyName"].Value = "FedEx Kinkos";
fileNode.Attributes["Phone"].Value = "425-884-9000";

Line 1 in the above snippet reads in the location of the template file from the client application configuration (app.config) file. Lines 6-14 merge the sample data with the outline. The message is now ready for delivery to the WCF service. The following code illustrates these actions:

string batchMsg = fileDoc.InnerXml;	//Line 1
MessageProcessorClient strClient = 
  new MessageProcessorClient("MessageResponseEndpoint");
MsmqMessage<String> strXmlMsg = new MsmqMessage<string>(batchMsg);	//Line 3
strXmlMsg.Label = "[WCFMQ_Client][WCFMQ_Service][ShipperTxn]";
using (TransactionScope scope = 
       new TransactionScope(TransactionScopeOption.Required))
{
    strClient.SubmitStringMessage(strXmlMsg);	//Line 7
    scope.Complete();
}

Line 1 in the snippet above converts the XMLDocument object to a string. Line 2 instantiates a MessageProcessorClient object from a definition within the client’s app.config file. The following snippet is a copy of the definition:

<endpoint	name="MessageResponseEndpoint" 
    address="msmq.formatname:DIRECT=OS:.\private$\northwindqueue"
    binding="msmqIntegrationBinding"
    bindingConfiguration="MessageProcessorBinding" 
    contract="WCFMQService.IMessageProcessor">
</endpoint>

The definition comprises the ABCs of a WCF message. An article providing an overview to the endpoint definition can be found here. Line 3 instantiates a MsmqMessage message containing the XML message. Line 4 sets the label for the message. It is this label that the WCF can use to identify the destination service and the type of the message. The message processor does not need to examine the contents of the message itself. Line 7 dispatches the MSMQ message to the WCF service.

The WCF service

I hope you will agree with me that creating the client was the easy part, creating the service is easier still. In fact, if you are using Visual Studio 2008, then there is no coding involved in creating the service or receiving messages from clients. Let's confirm this by looking at the Main() method of the service.

static void Main(string[] args)
{
    //Line 1
    if (!MessageQueue.Exists(ConfigurationManager.AppSettings["queueName"]))
        MessageQueue.Create(ConfigurationManager.AppSettings["queueName"], true);

    //Connect to the queue
    MessageQueue Queue = new 
      MessageQueue(ConfigurationManager.AppSettings["queueName"]);
    //Line 5

    //Line 7
    Queue.ReceiveCompleted += new ReceiveCompletedEventHandler(ProcessMessage);
    Queue.BeginReceive(); //Line 8
    Console.WriteLine("WCFMQService is running");
    Console.WriteLine("Press <ENTER> to terminate service.");
    Console.ReadLine();
}

Lines 1-2 check for the existence of an MSMQ queue, and if necessary create it. The name of the queue is defined in the service application configuration (app.config) file. Line 5 creates a handle to the queue and Line 7 attaches the message processing method (ProcessMessage) to the queue. Finally, line 8 sets the service up to monitor the queue for messages. Every one of these lines has to do with the processing of messages on the queue. As I said earlier, there is no code involved in creating the service or receiving messages from clients.

Note: If you comment out line 8, then messages placed on the queue will be left there. Uncommenting it and running the service will result in processing and automatic removal of all messages on the queue. You can view the contents of the queue by starting the ‘Computer Management’ (compmgmt.msc) utility and checking the private queue ‘northwindqueue’ under the ‘Message Queuing’ sub-node of the ‘Services and Applications’ node.

You can see one message on the queue awaiting processing

If you don’t find the ‘Message Queuing’ sub-node, then you probably do not have MSMQ installed. You can install MSMQ using ‘Add/Remove Programs’. You can go to this MSDN page for instructions on installing MSMQ.

Finally, let’s look at the last portion of code for our solution – the message processor.

// Connect to the queue.
MessageQueue Queue = (MessageQueue)source;	//Line 2
Queue.Formatter = new XmlMessageFormatter(new Type[] { typeof(String) });
// Pause the asynchronous receive operation while processing current message.
System.Messaging.Message msg = Queue.EndReceive(asyncResult.AsyncResult);
//Line 5

string[] tokenArr = msg.Label.Split(new char[] { '[', ']' }); //Line 7

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml((string)msg.Body);

Console.WriteLine(Environment.NewLine + "Processing incoming message "
    + Environment.NewLine + "Service Name:\t{0}"
    + Environment.NewLine + "Destination:\t{1}"
    + Environment.NewLine + "Document ID:\t{2}"
    + Environment.NewLine + "Message Contents:" + 
      Environment.NewLine + "{3}"
    , tokenArr[1], tokenArr[3], tokenArr[5]
    , FormatXML(xmlDoc.InnerXml, true));

//Resume servicing future messages
Queue.BeginReceive();	//Line 21

Line 2 creates a reference handle to the queue. Line 3 creates a formatter that will enable us to read the contents of the message. Line 5 temporarily suspends the receiving of queue messages while the current message is being processed. Lines 7-18 read the message and output it to the console. This is the point in code where you can insert your custom code to interpret and act on the XML message received. Line 21 then resumes monitoring the queue for further messages. Note: The processing of queue messages is asynchronous, and this is the central advantage to using queues with a Windows Service. Placing all messages on the queue enables the service to return immediately to accept the next message without having to wait for the previous message to be completely processed. This can offer significant advantages for scalability.

Summary

The Windows Communication Foundation is a great framework for applications to interoperate with each other. You could have multiple applications exchanging messages via the queue. Each application can place messages on the queue, and read messages off the queue if it is addressed to them. They can do so by reading the label attached to each message. Alternately you can create a specialized WCF router that delivers messages to one or more endpoints. Either way, you have an elegant way to implement a service-oriented architecture for your applications.

References

History

  • 03 Jan. 2009 - Initial submission.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

kannankeril
Software Developer
United States United States
Member
Born & raised in Mumbai, India
Living & working in WA, USA
Hope to retire to Auckland, NZ

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Question[My vote of 1] Your service is not kicking offmembertroybooth29 Mar '12 - 6:26 
There is something up with your ReceiveCompletedEventHandler, The ProcessMessage never gets kicked off.
QuestionChanges In XML FilememberRakesh_pooja23 Oct '11 - 23:33 
Hi,
 
on every time it shows unneccesary data like
 
Processing incoming message"
Service Name
Destination
Document ID
 
I want to remove this,PLease please help me...It is urgent
 
Thanks In Advance
QuestionHow to Start the service automatically in given ExamplememberRakesh.kumar.dce6 Oct '11 - 5:51 
HI,
 
Please i want to start dis service automatiically,Its urgent...
Questionwcf msmqmemberRakesh_pooja3 Oct '11 - 0:52 
Hi,
First of all thanks for Ur article ,I am implementing Ur wcf msmq module in my project,the requirement is little bit change,Ur whole application is in console but in my web application calling wcf service.i am able to make client side web application but how the console service change into wcf service and i have to stored that XML file in server side as a XML file.please help me..please
 

 
Thanks In Advance
GeneralMy vote of 5memberPankajsh10 Oct '10 - 19:41 
Great article, explains in detail the code as well as the concepts
GeneralSorry I know this is old butmemberCharles AtPLS9 Aug '10 - 9:44 
when you manually create your Queue "northwindqueue"   if you don't toggle transactional chk-box   you aint going to get any messages in there (Win 7)      not a server OS By the way...
 
So in case anyone falls into this little caveat here's my two cents.
GeneralTrying to step through service with debuggermemberMember 391904921 Mar '10 - 8:01 
Hi - Thanks for creating this sample project.
 
I can debug and step into the Main method in service\Service.cs. However, my breakpoint in the service\Service.cs ProcessMessage method doesn't get hit. Why is this? It appears that this method does process the messages that are sent to "northwindqueue" although the debugger doesn't appear to be hitting the breakpoint.....
modified on Sunday, March 21, 2010 2:20 PM

GeneralRe: Trying to step through service with debuggermemberOUSoonerTaz20 Dec '10 - 15:55 
You probably already have the answer to this, but, just after you add the ReceiveCompleted event handler, you need to actually tell the code to start processing messages using Queue.BeginReceive(); Then you should see it get into the ProcessMessage method.
 
HTH,
 
Sean
GeneralRe: Trying to step through service with debuggermemberjikkujj11 Nov '12 - 10:47 
Why was this commented out in the first place? A twisted way of making us take notice of the fact that you need to tell the queue to begin receiving?
GeneralRe: Trying to step through service with debuggermemberjikkujj11 Nov '12 - 10:49 
Oops. I should have read the whole article. Smile | :) . He explicit mentions that it is to see the message in the queue

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 4 Jan 2009
Article Copyright 2009 by kannankeril
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid