Click here to Skip to main content
15,867,704 members
Articles / Programming Languages / C#

Sample Starter Project Using WCF and MSMQ

Rate me:
Please Sign up or sign in to vote.
4.88/5 (14 votes)
4 Jan 2009CPOL6 min read 147.1K   5K   79   14
This project is provided as a starter application to get you started with WCF and MSMQ. It uses MsmqIntegrationBinding. The sample messages borrow their structure from the Northwind database, but that database is not a requirement.

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:

C#
//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:

C#
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:

XML
<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.

C#
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.

C#
// 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)


Written By
United States United States
ASP.Net Developer
Seattle, WA

Comments and Discussions

 
Question[My vote of 1] Your service is not kicking off Pin
msdevtech29-Mar-12 6:26
msdevtech29-Mar-12 6:26 
QuestionChanges In XML File Pin
LearningSpark23-Oct-11 23:33
LearningSpark23-Oct-11 23:33 
QuestionHow to Start the service automatically in given Example Pin
Rakesh.kumar.dce6-Oct-11 5:51
Rakesh.kumar.dce6-Oct-11 5:51 
Questionwcf msmq Pin
LearningSpark3-Oct-11 0:52
LearningSpark3-Oct-11 0:52 
GeneralMy vote of 5 Pin
Pankajsh10-Oct-10 19:41
Pankajsh10-Oct-10 19:41 
GeneralSorry I know this is old but Pin
ChristianProgrammer29-Aug-10 9:44
professionalChristianProgrammer29-Aug-10 9:44 
GeneralTrying to step through service with debugger Pin
Member 391904921-Mar-10 8:01
Member 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 debugger Pin
OUSoonerTaz20-Dec-10 15:55
OUSoonerTaz20-Dec-10 15:55 
GeneralRe: Trying to step through service with debugger Pin
jikkujj11-Nov-12 10:47
jikkujj11-Nov-12 10:47 
GeneralRe: Trying to step through service with debugger Pin
jikkujj11-Nov-12 10:49
jikkujj11-Nov-12 10:49 
QuestionWCF MSMQ Question [modified] Pin
CPK_201110-Aug-09 3:22
CPK_201110-Aug-09 3:22 
QuestionYou are not using MSMQ as WCF (service binding="netMsmqBinding") Pin
Mirza_Abazovic5-Feb-09 1:51
Mirza_Abazovic5-Feb-09 1:51 
GeneralRe: You are not using MSMQ as WCF (service binding="netMsmqBinding") Pin
k_ahmed_khan10-Jun-09 7:20
k_ahmed_khan10-Jun-09 7:20 
GeneralRemote Machines PinPopular
MarkJoel6029-Jan-09 10:48
MarkJoel6029-Jan-09 10:48 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.