WCF中IErrorHandler扩展加载失败及请求错误捕获方案咨询
出现The type 'Microsoft.WCF.Documentation.EnforceGreetingFaultBehavior...' could not be loaded错误的核心原因是:你引用了微软WCF文档中的示例行为类,该类仅用于演示,并非正式发布的可依赖组件,无法在实际项目中直接加载。解决步骤如下:
清理无效配置
打开项目的app.config或web.config,删除以下内容:<extensions>节点下<behaviorExtensions>中的<add name="enforceGreetingFaults" type="Microsoft.WCF.Documentation.EnforceGreetingFaultBehavior, HostApplication..." /><serviceBehaviors>对应行为节点中的<enforceGreetingFaults />
实现自定义错误处理行为
若要通过IErrorHandler捕获错误,需自行实现完整的错误处理逻辑及行为扩展:首先实现
IErrorHandler接口:public class CustomErrorHandler : IErrorHandler { public bool HandleError(Exception error) { // 替换为你的日志逻辑,比如写入本地文件或日志框架 System.Diagnostics.Trace.WriteLine($"未进入业务方法的错误:{error.Message}\n{error.StackTrace}"); return true; } public void ProvideFault(Exception error, MessageVersion version, ref Message fault) { // 如需自定义错误响应,可在此构造Fault消息,否则留空即可 } }接着实现服务行为类(注入错误处理器到WCF管道):
public class CustomErrorHandlerBehavior : IServiceBehavior { public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers) { channelDispatcher.ErrorHandlers.Add(new CustomErrorHandler()); } } // 以下接口方法无需逻辑,保留空实现 public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { } public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } }最后实现行为扩展元素(用于配置文件注册):
public class CustomErrorHandlerBehaviorExtensionElement : System.ServiceModel.Configuration.BehaviorExtensionElement { public override Type BehaviorType => typeof(CustomErrorHandlerBehavior); protected override object CreateBehavior() { return new CustomErrorHandlerBehavior(); } }配置自定义行为
在配置文件中注册并启用自定义错误处理:<system.serviceModel> <extensions> <behaviorExtensions> <!-- 替换为你的命名空间和程序集名称 --> <add name="customErrorHandler" type="YourNamespace.CustomErrorHandlerBehaviorExtensionElement, YourAssemblyName" /> </behaviorExtensions> </extensions> <serviceBehaviors> <behavior name="YourServiceBehavior"> <customErrorHandler /> <!-- 其他已有行为配置(如metadata、debug等) --> </behavior> </serviceBehaviors> </system.serviceModel>
XML截断导致的反序列化失败发生在WCF管道早期阶段,IErrorHandler可能无法覆盖所有场景,以下是更可靠的替代方案:
方案1:用IDispatchMessageInspector拦截原始请求
通过IDispatchMessageInspector可在反序列化前捕获原始请求内容,即使反序列化失败也能记录完整请求:
public class RequestLoggingInspector : IDispatchMessageInspector { public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) { // 复制请求流,避免后续读取时流被耗尽 MessageBuffer messageBuffer = request.CreateBufferedCopy(int.MaxValue); request = messageBuffer.CreateMessage(); Message originalMessage = messageBuffer.CreateMessage(); // 读取并记录原始请求 using (MemoryStream stream = new MemoryStream()) { XmlWriter writer = XmlWriter.Create(stream); originalMessage.WriteMessage(writer); writer.Flush(); stream.Position = 0; string requestContent = new StreamReader(stream).ReadToEnd(); System.Diagnostics.Trace.WriteLine($"原始请求内容:{requestContent}"); } return null; } public void BeforeSendReply(ref Message reply, object correlationState) { } } // 对应的行为类 public class RequestLoggingBehavior : IServiceBehavior { public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers) { foreach (EndpointDispatcher ed in cd.Endpoints) { ed.DispatchRuntime.MessageInspectors.Add(new RequestLoggingInspector()); } } } // 空实现接口方法 public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { } public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } } // 扩展元素类 public class RequestLoggingBehaviorExtensionElement : System.ServiceModel.Configuration.BehaviorExtensionElement { public override Type BehaviorType => typeof(RequestLoggingBehavior); protected override object CreateBehavior() { return new RequestLoggingBehavior(); } }
配置方式与自定义错误处理一致,在<extensions>注册后,将对应扩展节点添加到服务行为中即可。
方案2:启用WCF跟踪日志
WCF内置详细跟踪机制,可记录管道所有事件,包括反序列化错误及原始请求:
在配置文件中添加以下内容:
<system.diagnostics> <sources> <source name="System.ServiceModel" switchValue="Information, ActivityTracing" propagateActivity="true"> <listeners> <add name="wcfTraceListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData="wcf_trace.svclog" /> </listeners> </source> <source name="System.ServiceModel.MessageLogging"> <listeners> <add name="wcfMessageListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData="wcf_messages.svclog" /> </listeners> </source> </sources> </system.diagnostics> <system.serviceModel> <diagnostics> <messageLogging logEntireMessage="true" logMalformedMessages="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" /> </diagnostics> </system.serviceModel>
生成的.svclog文件可使用Service Trace Viewer工具(随.NET Framework安装)打开,直观查看请求流程、错误详情及原始请求内容。
方案3:自定义消息编码器(进阶)
若需对请求流做底层控制,可实现自定义MessageEncoder,在读取请求时记录原始内容或处理截断场景。该方案复杂度较高,适合深度定制需求,可参考WCF官方文档中MessageEncoder的实现示例。
内容的提问来源于stack exchange,提问作者Circle Hsiao

