在服务器上,我正在抛出这样的异常。
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块而是转到通信异常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上出现此问题。是否存在与之相关的原因?
重要更新
根据回答者的说法,服务器上任何未处理的异常都可能导致在客户端抛出通信异常,并且它可能与您在服务器上抛出的自定义故障异常无关。因此,解决方案是在服务器上记录错误并找出导致此行为的错误。这是我发现并实现的一个非常有用的开源日志记录功能,在项目进入生产环境后甚至可以更有用。非常感谢回答者。
答案 0 :(得分: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在关闭时可以通过CommunctionException,这是预期的行为。您不应该只使用客户端WCF通信通道using
。相反,你应该遵循这样的模式:
try{
x.Close()
}
catch(Comms ex){
x.Abort()
}
答案 1 :(得分:4)
我从使用wcf中学到的一件事是,很多时候抛出错误CommunicationException。甚至有可能你得到的错误与你抛出的异常无关,而是与其他原因造成的。目前,在客户端和服务器之间发送了一些内容,很难找到导致异常的原因。
我可以通过调整app.config中的一些设置来解决我的一些问题。设置超时等...
也许这有帮助?
答案 2 :(得分:4)
作为后续行动,获取CommunicationException
的一个原因是FaultException
无法正确序列化。在日志中(参见Simon关于如何设置日志记录的答案),这将显示为“处理异常”,然后是“回复操作引发异常”。
就我而言,这是因为没有初始化枚举值:
[DataContract]
public class MyCustomWebServiceFault
{
public MyCustomWebServiceFault()
{
}
[DataMember]
public EMyCustomWebServiceFaultReason Reason { get; set; }
[...]
然后日志显示它:
枚举值“0”对于“EMyCustomWebServiceFaultReason”类型无效,无法序列化。确保存在必要的枚举值,并且如果类型具有DataContractAttribute属性,则使用EnumMemberAttribute属性标记。
长话短说,使用日志记录或单元测试异常序列化。