Обрабатывать исключение NormalizePoisonException в привязке интеграции MSMQ

Добрый вечер,

У меня есть очередь MSMQ, которая отправляет сообщения в службу WCF с помощью msmqIntegrationBinding. Для свойства receiveErrorHandling по умолчанию установлено значение "Ошибка". Время от времени MSMQ начинает шипеть, пытаясь десериализовать сообщение:

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)

Сообщение никогда не достигает метода в сервисе:

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

Сервис имеет этот атрибут:

[ServiceKnownType(typeof(MyMessage))]

В привязке установлена ​​очередь мертвых писем:

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

Сообщение не обрабатывается службой WCF и помещается прямо в очередь журнала. Он не остается в очереди сообщений и не перемещается в очередь недоставленных сообщений. Я попытался реализовать IErrorHandler, как описано здесь, но он не дошел до него.

При получении сообщения от MSMQ традиционным способом...

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

Это работает, если я установил форматер как выше. Но когда несмотря на то, что serializationFormat="Xml" установлен в привязке, он все равно не сможет десериализоваться.

Я что-то пропустил наверняка. Я гуглил везде. Любая помощь с благодарностью.

Благодарю.

1 ответ

После некоторого интенсивного поиска в Google я столкнулся с двумя проблемами:

1) Если вы хотите, чтобы транзакции в MSMQ работали, убедитесь, что тот, кто настроил очередь, сделал ее транзакционной очередью при создании. (Вздох..) Создать очередь MSMQ Владельцы очереди

2) В примере IErrorHandler я не концентрировался на копировании и вставке (меньше кофе, больше сна) и по ошибке поместил логику ApplyDispatchBehavior в Validate, где еще нет ChannelDispatchers (Extra sigh...).

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

Что за пустяк!

Другие вопросы по тегам