IErrorHandler接口作用范围及实现后未触发问题咨询
我来帮你梳理这两个问题:
一、IErrorHandler的生效范围
明确地说:IErrorHandler仅对被调用的WCF服务(服务端)生效。
它属于WCF服务端调度器(Dispatcher)的扩展组件,核心作用是捕获服务端处理请求过程中抛出的所有异常,然后允许你自定义异常转换逻辑——比如把技术异常包装成用户友好的Fault消息,或者返回符合特定格式的错误响应,最终把处理后的结果返回给调用方。
而调用方(客户端)想要处理服务端返回的错误,需要用其他方式:比如捕获FaultException、使用客户端消息检查器(IClientMessageInspector)或者自定义客户端行为,IErrorHandler在客户端环境下是完全不起作用的。
二、IErrorHandler未触发,ApplyDispatchBehavior未执行的问题排查
从你描述的现象(Validate、AddBindingParameters、ApplyClientBehavior执行,但ApplyDispatchBehavior没运行)来看,大概率是你的自定义行为被错误注册到了客户端行为配置里,而没有正确关联到服务端的行为中。结合你把BizTalk编排发布为Web服务的场景,给你几个具体的排查方向:
1. 确认行为注册的位置
WCF的行为分服务端和客户端两类,ApplyDispatchBehavior是服务端行为的专属方法,只有当行为被应用到服务端的服务或端点时才会执行。如果你的配置把行为加到了客户端的<client>节点下,那只会触发客户端相关的方法,服务端根本不会加载这个行为。
你需要检查服务端的web.config(BizTalk发布服务后生成的配置文件):
- 首先,确保在
<system.serviceModel><extensions><behaviorExtensions>里注册了你的自定义行为扩展,示例配置如下:
<extensions> <behaviorExtensions> <add name="customErrorHandlerBehavior" type="YourAssembly.YourErrorHandlerBehavior, YourAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> </behaviorExtensions> </extensions>
- 然后,在
<serviceBehaviors>或<endpointBehaviors>中定义包含该行为的配置,并关联到你的BizTalk服务:
<serviceBehaviors> <behavior name="BizTalkServiceBehavior"> <customErrorHandlerBehavior /> <!-- 保留BizTalk自动生成的其他行为,比如元数据发布等 --> </behavior> </serviceBehaviors>
- 最后,确保你的服务节点
service的behaviorConfiguration属性指向这个行为:
<service name="YourBizTalkPublishedServiceName" behaviorConfiguration="BizTalkServiceBehavior"> <endpoint address="" binding="webHttpBinding" contract="YourContract" /> </service>
2. 检查自定义行为的实现
确保你的行为类正确实现了IServiceBehavior或IEndpointBehavior,并且在ApplyDispatchBehavior方法中正确添加了IErrorHandler实例:
public class YourErrorHandlerBehavior : IServiceBehavior { public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { // 遍历所有通道调度器,添加自定义错误处理器 foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers) { channelDispatcher.ErrorHandlers.Add(new YourCustomErrorHandler()); } } // 实现其他接口的空方法 public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { } }
3. BizTalk特定的配置注意事项
当把BizTalk编排发布为WCF服务时,BizTalk会托管这个服务,你需要额外注意:
- 自定义行为的程序集要部署到BizTalk应用程序目录,或者注册到GAC(如果是强签名程序集),确保BizTalk托管的WCF服务能加载到它。
- 不要修改BizTalk自动生成的配置文件中的核心节点(比如服务名称、契约名称),确保行为配置关联的名称和实际服务完全匹配。
4. 调试验证
你可以尝试附加到BizTalk的WCF服务进程(IIS托管是w3wp.exe,自托管是BizTalkServiceHost.exe),在ApplyDispatchBehavior方法中加断点,确认是否被调用。如果还是没触发,优先检查配置文件的拼写错误——比如行为名称、程序集名称、类型名称是否完全正确,这是最常见的配置失误原因。
内容的提问来源于stack exchange,提问作者NealWalters

