1

我有一个使用 WCF 响应 MSMQ 上的消息的服务。当消息格式正确时,它可以正常工作,我们很高兴。当消息用于不同的服务并且操作不同时,消息将保留在队列中,我们获取日志条目,我们修复,我们很高兴。

但是,当消息具有正确的操作,但包含服务器无法反序列化的 XML 元素时,消息将从队列中消失,我们不会获得日志条目,并且我们几乎不知道发生了什么。我们不开心。

我试过添加一个 IErrorHandler。我试过添加一个故障事件处理程序。我唯一能做的就是使用 WCF 中内置的诊断日志记录。有什么方法可以使用我自己的记录器或错误处理程序来响应代码中的此类错误?

我的队列恰好是事务性的,但这似乎与这个问题没有任何区别。这发生在 Windows Server 2003 上的 MSMQ 3.0 版上。

此源代码显示了问题:

class Program : IErrorHandler {
    private static Uri QueueUri = new Uri("net.msmq://localhost/private/server_queue");

    static void Main(string[] args) {
        Program program = new Program();

        if (args.Length > 0) {
            if (args[0] == "server") {
                program.Server();
            } else if (args[0] == "bad") {
                program.BadClient();
            }
        } else {
            program.Client();
        }
    }

    public void BadClient() {
        using (var client = new BadServiceClient(QueueUri)) {
            client.Do(new [] {new BadStuff { BadMessage = "hi" }});
        }
    }

    public void Client() {
        using (var client = new ServiceClient(QueueUri)) {
            client.Do(new [] {new Stuff {Message = "hi"}});
        }
    }

    public void Server() {
        var serviceHost = new ServiceHost(typeof(Service));
        serviceHost.AddServiceEndpoint(typeof (IService), new NetMsmqBinding(), QueueUri);
        serviceHost.Open();

        serviceHost.Faulted += serviceHost_Faulted;
        serviceHost.UnknownMessageReceived += new EventHandler<UnknownMessageReceivedEventArgs>(serviceHost_UnknownMessageReceived);
        foreach (ChannelDispatcher dispatcher in serviceHost.ChannelDispatchers) {
            dispatcher.ErrorHandlers.Add(this);
        }

        Console.WriteLine("press the any key");
        Console.ReadKey(true);
    }

    void serviceHost_UnknownMessageReceived(object sender, UnknownMessageReceivedEventArgs e) {
        Console.WriteLine("unknown message: {0}", e);
    }

    private static void serviceHost_Faulted(object sender, EventArgs e) {
        Console.WriteLine("fault: {0}", e);
    }

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault) {
        Console.WriteLine("handling error: {0}", error);
    }

    public bool HandleError(Exception error) {
        Console.WriteLine("handling error: {0}", error);
        return true;
    }
}

[ServiceContract]
public interface IService {
    [OperationContract(IsOneWay = true, Action = "do")]
    void Do(IEnumerable<Stuff> stuffs);
}

[ServiceContract]
public interface IBadService {
    [OperationContract(IsOneWay = true, Action = "do")]
    void Do(IEnumerable<BadStuff> stuffs);
}

class ServiceClient : ClientBase<IService>, IService {
    public ServiceClient(Uri uri) : base(new NetMsmqBinding(), new EndpointAddress(uri)) {}

    public void Do(IEnumerable<Stuff> stuffs) {
        Channel.Do(stuffs);
    }
}

class BadServiceClient : ClientBase<IBadService>, IBadService {
    public BadServiceClient(Uri uri) : base(new NetMsmqBinding(), new EndpointAddress(uri)) {}

    public void Do(IEnumerable<BadStuff> stuffs) {
        Channel.Do(stuffs);
    }
}

[ServiceBehavior(TransactionTimeout = "00:5:00", InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
class Service : IService {
    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    public void Do(IEnumerable<Stuff> stuffs) {
        foreach (var stuff in stuffs) {
            Console.WriteLine("service doing stuff, message: " + stuff.Message);
        }
    }
}

[DataContract]
public class Stuff {
    [DataMember]
    public string Message;
}

[DataContract]
public class BadStuff : Stuff {
    [DataMember]
    public string BadMessage;
}
4

1 回答 1

0

这已经很晚了,但是为可能像我一样有类似问题的其他人添加了答案。请注意,使用 MSMQ 与无法提取格式错误的消息无关。正如蒂姆所提到的,如果由于格式错误(例如包含 & 字符)而无法反序列化 XML,则使用 IDispatchMessageInspector 实现不会给您消息。

我唯一能找到的是打开常规 WCF 消息跟踪,其中根据本文档在 messageLogging 元素下将 logMalformedMessages 设置为 true(希望 MS 不要移动链接):

配置消息记录

于 2017-05-25T07:04:14.267 回答