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
[ServiceContract()]
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());
         sr.Close();
      }
   }
}
internal static void StartService()
{
// Instantiate new ServiceHost
myServiceHost = new ServiceHost(typeof(MessageProcessor));
myServiceHost.Open();
}
internal static void StopService()
{
// Call StopService from your shutdown logic (i.e. dispose method)
if (myServiceHost.State != CommunicationState.Closed)
myServiceHost.Close();
}
private void MainForm_Load(object sender, EventArgs e)
{
StartService();
}
private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
{
StopService();
}
The next step is to setup the app.config configuration file.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
   <system.serviceModel>
      <behaviors>
         <serviceBehaviors>
            <behavior name="Throttling">
               <serviceThrottling maxConcurrentCalls="2" />
            </behavior>
         </serviceBehaviors>
      </behaviors>
      <bindings>
         <msmqIntegrationBinding>
         <binding name="NewBinding0" exactlyOnce="false" serializationFormat="Stream" />
         </msmqIntegrationBinding>
      </bindings>
      <services>
         <service behaviorConfiguration="Throttling" name="WCFMQListener.MessageProcessor">
            <endpoint address="msmq.formatname:DIRECT=OS:.\private$\testqueue" binding="msmqIntegrationBinding" bindingConfiguration="NewBinding0" contract="WCFMQListener.IMessageProcessor" />
         </service>
      </services>
   </system.serviceModel>
</configuration>
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
serializationFormat="Stream"
The message can be read just as easily as a binary array.
 





1 comment:
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 = "*"):
[ServiceContract()]
public interface IMessageProcessor
{
[OperationContract(IsOneWay = true), Action = "*"]
void ProcessMessage(MsmqMessage < Stream > msg);
}
Post a Comment