我从来不理解 WCF 的一件事是,当服务器遇到未处理的异常时,为什么没有异常消息详细信息传播回调用客户端。
例如,如果我有以下服务器代码
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class Server : IServer
{
public DTO GetDTO()
{
DTO dto = new DTO();
dto.dto = dto;
return dto;
}
}
public class DTO
{
public DTO dto;
}
[ServiceContract]
public interface IServer
{
[OperationContract]
DTO GetDTO();
}
我特意引入了一个ObjectGraph,以便在返回DTO对象时引发序列化异常。
如果我有一个客户端调用该服务器的GetDTO()
方法,我会得到以下CommunicationException
.
套接字连接被中止。这可能是由错误引起的
正在处理您的消息或超出了接收超时
远程主机或底层网络资源问题。本地套接字
超时为“00:00:58.9350000”。
这是绝对没用的。它没有内部异常,甚至没有真正的异常消息。
如果您随后使用 Microsoft Service TraceViewer,您将看到异常,但您必须为此打开诊断跟踪。
应该发回的异常消息是
尝试序列化参数时出错http://tempuri.org/:GetDTOResult http://tempuri.org/:GetDTOResult。 InnerException 消息是
'TestWCFLib.DTO'类型的对象图包含循环并且不能
如果参考跟踪被禁用,则序列化。'。请参见
有关更多详细信息,请参阅 InnerException。
那么有人可以告诉我如何在客户端显示正确的异常消息吗?显然,设置IncludeExceptionDetailInFaults
true 没有什么区别。
我认为服务器错误不会传播到客户端是有意设计的。通常,这是一种不向客户端公开服务器内部结构的做法,因为客户端服务器体系结构的主要目的是服务器的独立性。
您仍然可以通过使用来实现此目的故障异常 http://msdn.microsoft.com/en-us/library/system.servicemodel.faultexception%28VS.85%29.aspx/
用故障合同装饰您的服务声明
[ServiceContract]
public interface IServer
{
[OperationContract]
[FaultContract(typeof(MyApplicationFault))]
DTO GetDTO();
}
然后捕获服务实现中的错误并抛出错误异常。
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class Server : IServer
{
public DTO GetDTO()
{
try
{
DTO dto = new DTO();
dto.dto = dto;
return dto;
}
catch (Exception ex)
{
MyApplicationFault fault = new MyApplicationFault(...);
throw new FaultException<MyApplicationFault>(fault);
}
}
}
并在客户端捕获异常
IServer proxy = ...; //Get proxy from somewhere
try
{
proxy.GetDTO();
}
catch (TimeoutException) { ... }
catch (FaultException<MyApplicationFault> myFault) {
MyApplicationFault detail = myFault.Detail;
//Do something with the actual fault
}
catch (FaultException otherFault) { ... }
catch (CommunicationException) { ... }
希望这可以帮助。
如需精彩教程,请参阅关于Fault异常的代码项目教程 http://www.codeproject.com/Articles/26320/WCF-Error-Handling-and-Fault-Conversion/
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)