C# SOAP日志实现问题:ApplyClientBehavior未被调用(.NET472/.NET8)
解决SOAP日志中ApplyClientBehavior未调用的问题
在实现C# SOAP日志功能时,若ApplyClientBehavior方法未按预期调用,会导致消息监控失效,直接影响SOAP通信的诊断能力。结合你提供的代码,以下是具体的排查和修复方案:
核心问题分析
ApplyClientBehavior未触发通常由以下原因导致:
- 行为添加时机过晚(通道已初始化后才添加)
- 行为添加的目标对象错误
- 重复行为处理逻辑有误
- ChannelFactory已处于打开状态,无法加载新行为
修复方案
1. 确保行为在通道初始化前添加
必须在第一次调用服务方法或**调用CreateChannel()**之前执行EnableSoapLogging扩展方法。示例:
var soapClient = new MySoapServiceClient(); soapClient.EnableSoapLogging(); // 先启用日志 soapClient.CallServiceMethod(); // 再调用服务
2. 修正行为添加逻辑
修改扩展方法,直接操作客户端Endpoint,并仅移除自身类型的行为(避免误删其他必要行为):
public static class SoapLoggingExtensions { public static void EnableSoapLogging<TChannel>(this ClientBase<TChannel> client) where TChannel : class { // 移除已存在的自定义日志行为 var existingBehavior = client.Endpoint.EndpointBehaviors .OfType<SoapLoggingEndpointBehavior>() .FirstOrDefault(); if (existingBehavior != null) { client.Endpoint.EndpointBehaviors.Remove(existingBehavior); } // 添加新的日志行为 client.Endpoint.EndpointBehaviors.Add(new SoapLoggingEndpointBehavior()); } private class SoapLoggingEndpointBehavior : IEndpointBehavior { public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { clientRuntime.ClientMessageInspectors.Add(new SoapLoggingInspector()); } public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { } public void Validate(ServiceEndpoint endpoint) { } } }
3. 处理ChannelFactory已打开的情况
如果ChannelFactory已经处于Opened状态,新增行为不会生效,需重置ChannelFactory:
public static void EnableSoapLogging<TChannel>(this ClientBase<TChannel> client) where TChannel : class { // 重置ChannelFactory(若已打开) if (client.ChannelFactory.State != CommunicationState.Created) { client.ChannelFactory.Close(); client.ChannelFactory.Open(); } // 移除并添加行为的逻辑... }
4. 修复消息处理的引用问题
原代码中LogMessage方法未正确通过ref参数恢复原始消息,会导致后续消息处理失败。修改如下:
public class SoapLoggingInspector : IClientMessageInspector { public object BeforeSendRequest(ref Message request, IClientChannel channel) { try { LogMessage(ref request, "Outgoing Request"); } catch (Exception ex) { Console.WriteLine($"Error logging outgoing request: {ex.Message}"); } return null; } public void AfterReceiveReply(ref Message reply, object correlationState) { try { LogMessage(ref reply, "Incoming Response"); } catch (Exception ex) { Console.WriteLine($"Error logging incoming response: {ex.Message}"); } } private void LogMessage(ref Message message, string messageType) { MessageBuffer buffer = message.CreateBufferedCopy(int.MaxValue); Message messageCopy = buffer.CreateMessage(); string messageStr = MessageToString(messageCopy); Console.WriteLine($"---{messageType} at {DateTime.Now}---"); Console.WriteLine(messageStr); Console.WriteLine("---End of Message---\n"); // 正确恢复原始消息 message = buffer.CreateMessage(); } private string MessageToString(Message message) { using (var stream = new MemoryStream()) { using (var writer = XmlDictionaryWriter.CreateTextWriter(stream, Encoding.UTF8)) { message.WriteMessage(writer); writer.Flush(); } stream.Position = 0; using (var reader = new StreamReader(stream)) { return reader.ReadToEnd(); } } } }
5. 检查配置文件冲突
确认WCF配置文件的<endpointBehaviors>节点中没有其他行为覆盖或阻止自定义日志行为的加载。
内容的提问来源于stack exchange,提问作者TheNIK
相关产品推荐
相关产品推荐

