2010-04-26 87 views
1

在服务器上我抛出像这样的异常。捕获通信异常,而不是自定义故障异常 - WCF

catch(SqlException exception) 
{ 
    if (exception.Message.Contains("Custom error from stored proc")) 
    { 
    //Exception to be thrown when authentication fails. 
    throw new FaultException<MyServiceFault>(new MyServiceFault { MessageText = exception.Message }); 
    } 
} 

而在客户端,我捕捉异常

catch(FaultException<MyServiceFault> faultException) 
{ 

} 

这里是我的MyServiceFault

[DataContract] 
public class MyServiceFault 
{ 
    [DataMember] 
    public string MessageText { get; set; } 

    [DataMember] 
    public Guid Id { get; set; } 
} 

的问题是,在客户端,它并没有去追赶MyServiceFault而是转到通信异常catch块并抛出此错误

System.ServiceModel.CommunicationException: The underlying connection was closed: The connection was closed unexpectedly. ---> System.Net.WebException 

我也在我的服务实现的接口中修饰了我的服务方法[FaultContract(typeof(MyServiceFault))]

在我的web.config servicebehaviour标签由 <serviceDebug includeExceptionDetailInFaults="true" />

任何想法,我要去哪里错了。

这个问题发生在Windows 7上。可以有一个相关的原因吗?

重要更新
根据应答者,在服务器上的任何未处理的异常可能会导致在客户端的通讯异常抛出,它可能没有什么关系,你已在服务器上抛出的自定义错误异常。因此解决方案是记录服务器上的错误并找出导致此行为的错误。这是我发现和实施的一个非常有用的开源日志记录功能,在您的项目进入生产环境后,它甚至会更有用。非常感谢回答者。

A better way of logging exceptions in WCF

回答

6

将日志记录添加到您的app.config中,将日志记录添加到您的WCF调用中。

<system.diagnostics> 
    <trace autoflush="true" /> 
    <sources> 
    <source name="System.ServiceModel" switchValue="Information, ActivityTracing"> 
     <listeners> 
     <add name="sdt" type="System.Diagnostics.XmlWriterTraceListener" initializeData="c:\LogPath\LogFile.svclog" /> 
     </listeners> 
    </source> 
    </sources> 
</system.diagnostics> 

(您可以为服务器和客户端做到这一点,显然,指定不同的日志文件)

一旦你产生了一些日志,通过对异常或警告一下。我经常发现这会产生一些非常有用的信息,帮助我解决WCF问题。

要阅读日志文件,您需要使用SvcTraceViewer.exe。不幸的是,获得这个的唯一方法是使用the windows SDK,这对于一个小小的工具来说有点大的下载。

还值得注意的是,WCF可以在关闭时通过CommunicalException,这是预期的行为。你不应该只用using与客户端WCF comm通道。相反,你应该遵循这样一个规律:

try{ 
    x.Close() 
} 
catch(Comms ex){ 
    x.Abort() 
} 
+0

我正在使用相同的try catch模式来调用服务器方法。 并感谢您的配置设置。我会看到细节,但它给了我很多的XML。任何xsl为它看到它格式正确? – IsmailS 2010-04-26 10:10:48

+0

@Ismail:您需要使用[SvcTraceViewer.exe](http://msdn.microsoft.com/zh-cn/library/ms732023.aspx)来读取日志文件。我会更新我的答案。 – 2010-04-26 10:43:18

+0

我在Windows 7上开发。可以有任何相关的原因吗? 它在企业库异常处理块的某处失败。 在此处查看详情http://entlib.codeplex.com/Thread/View.aspx?ThreadId=205122。我最后发布了它。在此先感谢 – IsmailS 2010-04-26 11:31:36

4

有一两件事我从WCF工作了解到的情况是错误的CommunicationException抛出了很多的时间。甚至有可能你得到的错误与你抛出的异常无关,而是与其他东西引发的错误无关。目前,客户端和服务器之间正在发送内容,因此很难找出导致异常的原因。

我可以通过调整app.config中的一些设置来解决我的一些问题。设置超时等...

也许这可以帮助吗?

+1

同意CommunicationException似乎在很多情况下都会抛出。当心,如果你实现IErrorHandler的例子([链接](http://stackoverflow.com/questions/3036692/ierrorhandler-doesnt-seem-to-be-handling-my-errors-in-wcf-any-ideas)) 。在将操作值重置为空之前得到以下消息: message = Message.CreateMessage(version,fault,null); – Henrik 2013-04-03 13:57:55

4

作为后续,一个原因让CommunicationException是,FaultException无法正确序列化。在日志中(请参阅Simon关于如何设置日志记录的答案),这将显示为“处理异常”,然后“回复操作抛出异常”

在我而言,这是由未初始化的枚举值造成的:

[DataContract] 
public class MyCustomWebServiceFault 
{ 
    public MyCustomWebServiceFault() 
    { 
    } 

    [DataMember] 
    public EMyCustomWebServiceFaultReason Reason { get; set; } 

    [...] 

然后,日志显露了它:

枚举值“0”是类型无效“EMyCustomWebServiceFaultReason”和不能被序列化。如果类型具有DataContractAttribute属性,请确保存在必要的枚举值并使用EnumMemberAttribute属性标记。

长话短说,使用日志或单元测试异常序列化。

+0

[文档](https://msdn.microsoft.com/en-us/library/ff650547.aspx)指出,错误类型必须是可序列化的:“FaultContractAttribute中指定的类型必须可序列化为'DataContract,SerializableAttribute'或'ISerializable'“。 – paulroho 2017-10-17 11:59:10