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