3

晚上好,

我有一个 MSMQ 队列,它使用 msmqIntegrationBinding 将消息推送到 WCF 服务。receiveErrorHandling 属性设置为默认值“Fault”。有时,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" ,但它仍然无法反序列化。

我肯定错过了一些东西。我到处都用谷歌搜索过。任何帮助是极大的赞赏。

谢谢。

4

1 回答 1

2

经过一番激烈的谷歌搜索后,我遇到了两个问题:

1) 如果您希望 MSMQ 中的事务正常工作,请确保设置队列的人在创建队列时将其设为事务队列。(叹..) 创建 MSMQ 队列 队列属性

2)在IErrorHandler 示例中,我没有集中精力进行复制和粘贴(少喝咖啡,多睡觉),并且错误地将 ApplyDispatchBehavior 逻辑放入 Validate 中,其中尚不存在 ChannelDispatchers(额外叹息......)。

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

真是个松饼!

于 2018-04-03T12:46:54.520 回答