在我的WCF客户端类中,我正在处理Faulted()
事件,这样如果远程服务抛出异常并使通道出现故障,我仍然可以至少正常关闭它。这是我的代码:
protected void RemoteDataRetriever_Faulted(object sender, EventArgs e)
{
(sender as ICommunicationObject).Abort();
this.Dispose();
throw new ChannelTerminatedException("The remote service threw an unhandled exception and as a result the channel has been closed.");
}
所以我期望的是客户端可以处理我手动抛出的ChannelTerminatedException
并向用户发送消息等。相反,我的异常包含在System.ServiceModel.Diagnostics.CallbackException
中。好的。除了这里的问题:ServiceModel库中不存在这个CallbackException,除了作为通用Exception
之外,我似乎无法处理它,这对我的单元测试没有好处。到底发生了什么事?我可以以某种方式禁用它并抛出我最初想要的异常吗?
答案 0 :(得分:4)
事实证明,System.ServiceModel.Diagnostics.CallbackException
是一个内部类,填充在一个名为“%SystemRoot%\ Microsoft.net \ Framework \ v3.0 \ Windows Communication Foundation \ SMDiagnostics.dll”的小型已知程序集中,仅包含内部类。嗯,这很臭,因为这意味着我们永远不会捕获那个例外。但是,我能够找到实例化上述异常的类/方法(System.ServiceModel.Diagnostics.ExceptionUtility.ThrowHelperCallback(Exception innerException)),并发现它正在由CommunicationObject中的虚方法OnFaulted()调用。因此理论上任何派生自CommunicationObject的类(抱歉ClientBase<T>
)都可以覆盖该方法并告诉它不要调用ThrowHelperCallback()。这意味着唯一可行的候选人是来自ChannelFactoryBase<T>
的类。从理论上讲,我可以继续实现我自己的自定义通道工厂,它可以抑制恼人的CallbackException,但目前它的工作量太大,所以我想我只需处理它。
<s:Body>
<s:Fault>
<s:Code>
<s:Value>s:Receiver</s:Value>
<s:Subcode>
<s:Value xmlns:a="http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher">a:InternalServiceFault</s:Value>
</s:Subcode>
</s:Code>
<s:Reason>
<s:Text xml:lang="en-US">The server was unable to process the request due to an internal error. For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the <serviceDebug> configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework 3.0 SDK documentation and inspect the server trace logs.</s:Text>
</s:Reason>
</s:Fault>
</s:Body>
答案 1 :(得分:2)
您看到System.ServiceModel.Diagnostics.CallbackException
,因为服务器上发生了异常。由于异常发生在客户端应用程序的域之外,因此它可能是客户端无权访问的类型。回调机制通过生成您正在看到的CallbackException来处理此问题。这类似于访问静态成员时发生未处理异常时抛出的System.TypeInitializationException
。如果您正在尝试优雅地处理此问题,您可能希望在服务器端处理异常并关闭套接字,这将随后在客户端上触发可以处理的异常。