什么是System.ServiceModel.Diagnostics.CallbackException以及为什么我无法处理它?

Rep*_*Man 6 .net wcf exception-handling exception faulted

在我的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.");
}
Run Code Online (Sandbox Code Playgroud)

所以我期望的是客户端可以处理ChannelTerminatedException我手动抛出的并向用户发送消息等等.相反,我的例外是包装在一个System.ServiceModel.Diagnostics.CallbackException.好的.除了这里是catch:ServiceModel库中不存在这个CallbackException,除了作为泛型之外,我似乎无法处理它Exception,这对我的单元测试没有好处.到底发生了什么事?我可以以某种方式禁用它并抛出我最初想要的异常吗?

Rep*_*Man 5

事实证明,它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,但目前工作量太大,所以我想我只能处理它。

编辑:@Jeremy - 如果我检查通过网络返回的 SOAP 信封,我发现它给了我一个通用错误,正如预期的那样,这表明 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 &lt;serviceDebug&gt; 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>
Run Code Online (Sandbox Code Playgroud)