Label Cloud

Thursday, November 16, 2006

WCF - Processing untyped messages from MSMQ binding

Now that .NET 3.0 is finally released, I am putting in some hours to see how it can be implemented in our infrastructure. Up front the power and flexibility of the framework is a bit overwhelming, however, the tools that are included are great. For example Service Configuration Editor has a great way to specify every setting required and optional for setting up WCF communication.

One of the components that I was looking to replace is a MSMQ Message Processing application. Basically it is a custom written MSMQ Trigger service. Well.. here goes.

WCF includes a binding for interconnecting with non-WCF MSMQ implementations. I've created the final prototype from the basic service sample, and created a ServiceContract interface and implementation class

public interface IMessageProcessor
   [OperationContract(IsOneWay = true)]
   void ProcessMessage(MsmqMessage<Stream> msg);

public class MessageProcessor : IMessageProcessor
   public void ProcessMessage(MsmqMessage<Stream> msg)
      using (StreamReader sr = new StreamReader(msg.Body))
         MessageBox.Show("Hello: " + sr.ReadToEnd());

Then added created a main form, and added start/stop events
internal static ServiceHost myServiceHost = null;
internal static void StartService()
   // Instantiate new ServiceHost
   myServiceHost = new ServiceHost(typeof(MessageProcessor));
internal static void StopService()
   // Call StopService from your shutdown logic (i.e. dispose method)
   if (myServiceHost.State != CommunicationState.Closed)
private void MainForm_Load(object sender, EventArgs e)
private void MainForm_FormClosed(object sender, FormClosedEventArgs e)

The next step is to setup the app.config configuration file.

<?xml version="1.0" encoding="utf-8"?>
            <behavior name="Throttling">
               <serviceThrottling maxConcurrentCalls="2" />
         <binding name="NewBinding0" exactlyOnce="false" serializationFormat="Stream" />
         <service behaviorConfiguration="Throttling" name="WCFMQListener.MessageProcessor">
            <endpoint address="msmq.formatname:DIRECT=OS:.\private$\testqueue" binding="msmqIntegrationBinding" bindingConfiguration="NewBinding0" contract="WCFMQListener.IMessageProcessor" />

The most time I've spent was to figure out how to read the non-xml formatted message. The key is to declare the method as

void ProcessMessage(MsmqMessage<Stream> msg);

and to adjust binding in the configuration file


The message can be read just as easily as a binary array.


1 comment:

Snakefoot said...

Thank you for posting this quick guide. It worked wonderful.

I had to modify my contract a bit, so the ProcessMessage became a catch all (Action = "*"):

public interface IMessageProcessor
[OperationContract(IsOneWay = true), Action = "*"]
void ProcessMessage(MsmqMessage < Stream > msg);