Handle NormalizePoisonException in MSMQ Integration Binding

82 Views Asked by At

Good evening,

I have an MSMQ queue that is pushing messages to a WCF service using msmqIntegrationBinding. The receiveErrorHandling property is set to the default of "Fault". Occasionally, MSMQ has a hissy fit trying to deserialise a message:

System.ServiceModel.ProtocolException: An error was encountered while deserializing the message. The message cannot be received.
System.Runtime.Serialization.SerializationException: An error occurred while deserializing an MSMQ message's XML body. The message cannot be received. Ensure that the service contract is decorated with appropriate [ServiceKnownType] attributes or the TargetSerializationTypes property is set on the MsmqIntegrationBindingElement.
at System.ServiceModel.Channels.MsmqDecodeHelper.XmlDeserializeForIntegration(MsmqIntegrationChannelListener listener, Stream stream, Int64 lookupId)
at System.ServiceModel.Channels.MsmqDecodeHelper.DeserializeForIntegration(MsmqIntegrationChannelListener listener, Stream bodyStream, MsmqIntegrationMessageProperty property, Int64 lookupId)

The message never reaches the method in the service:

[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)] public void ProcessMessage(MsmqMessage<MyMessage> msg) {...

The service has this attribute:

[ServiceKnownType(typeof(MyMessage))]

There is a dead letter queue set in the binding:

<msmqIntegrationBinding>
<binding name="MyBinding" serializationFormat="Xml" exactlyOnce="false" deadLetterQueue="Custom" customDeadLetterQueue="msmq.formatname:DIRECT=OS:.\private$\services/deadLetterQueue" useMsmqTracing="true" receiveErrorHandling="Fault">

The message is not processed by the WCF service and is dumped straight into the Journal queue. It is not left in the Messaging queue or moved to the dead letter queue. I have tried implementing an IErrorHandler as detailed here but it doesn't reach it.

When receiving a message from MSMQ in the traditional way...

MessageQueue msMq = new MessageQueue(_queueName);
msMq.Formatter = new XmlMessageFormatter(new Type[] { typeof(MyMessage) });
Message m = msMq.Receive();

It works if I set the formatter as above. But when despite serializationFormat="Xml" being set in the binding, it still fails to deserialise.

I've missed something for sure. I've Googled everywhere. Any help is greatly appreciated.

Thanks.

1

There are 1 best solutions below

0
On

After some intense Googling I came across two issues:

1) If you want transactions in MSMQ to work, make sure that whoever setup the queue made it a transactional queue when they created it. (Sigh..) Create a MSMQ queue Queue proeprties

2) In the IErrorHandler example, I wasn't concentrating with my copying and pasting (Less coffee, more sleep) and put the ApplyDispatchBehavior logic into Validate by mistake, where no ChannelDispatchers exist yet (Extra sigh...).

foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
{
    ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
    channelDispatcher.ErrorHandlers.Add(errorHandler);
}

What a kerfluffle!