IncludeExceptionDetailInFaults 的行为不像想象的那样

Posted

技术标签:

【中文标题】IncludeExceptionDetailInFaults 的行为不像想象的那样【英文标题】:IncludeExceptionDetailInFaults not behaving as thought 【发布时间】:2011-02-03 10:07:30 【问题描述】:

我有这个简单的测试项目只是为了测试 IncludeExceptionDetailInFaults 行为。

    public class Service1 : IService1
    
        public string GetData(int value)
        
            throw new InvalidCastException("test");
            return string.Format("You entered: 0", value);
        
    

    [ServiceContract]
    public interface IService1
    
        [OperationContract]
        string GetData(int value);
    

在服务的 app.config 中,我将其设置为 true

 <serviceDebug includeExceptionDetailInFaults="True" />

在客户端:

            try
            
                using (var proxy = new ServiceReference1.Service1Client())
                    Console.WriteLine(proxy.GetData(5));
            
            catch (Exception ex)
            
                Console.WriteLine(ex.Message);
            

这就是我认为的行为: 设置为 includeExceptionDetailInFaults=true 会将异常详细信息传播到客户端。但我总是收到 CommunicationObjectFaultException。

我确实尝试在合同上使用 FaultContract(typeof(InvalidCastException)),但行为相同,只得到 CommunicationObjectFaultException。

让它工作的唯一方法是抛出 new FaultException(new InvalidCastException("test"));

但我认为使用 IncludeExceptionDetailInFaults=true 以上是自动完成的。

我错过了什么吗?

【问题讨论】:

【参考方案1】:

这是因为您将服务客户端放在了 using 块中。

WCF 客户端是 .NET 中您shouldn't use using 的一个地方,因为它会掩盖“真正的”异常。

技术解释:Dispose 调用 Close,如果通道已经发生故障(即由于先前的异常),它将始终抛出 CommunicationObjectFaultedException,随后将 那个堆栈顶部的异常。在清理ICommunicationObject 时,为了避免屏蔽异常,您必须先检查State 是否有故障,如果有故障,请调用Abort 而不是Close

【讨论】:

啊,谢谢!当通道发生故障时,Close 会如何导致通信对象故障异常? @pdiddy: CommunicationObject.Close 被编程为在通道出现故障时抛出异常。这不是偶然的。 不能在通道出现故障时检查状态并中止吗?只是想知道为什么它是这样实现的。 @pdiddy:它确实检查了状态,并且确实调用了Abort...,然后它抛出了一个异常。我确信它可以做许多其他事情,但这是 WCF 团队选择实施它的方式,这对许多人不利。它现在甚至记录在 MSDN 上:msdn.microsoft.com/en-us/library/ms733912.aspx

以上是关于IncludeExceptionDetailInFaults 的行为不像想象的那样的主要内容,如果未能解决你的问题,请参考以下文章