我从未理解过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。 InnerException消息是 '类型'TestWCFLib.DTO'的对象图包含循环而不能 如果参考跟踪被禁用,则序列化。请参阅 InnerException以获取更多详细信息。
那么有人能告诉我如何在客户端显示正确的异常消息吗?显然,将IncludeExceptionDetailInFaults
设置为true并没有什么不同。
答案 0 :(得分:2)
我认为通过设计将服务器错误传播给客户端。这通常是不将服务器内部暴露给客户端的做法,因为Client Server体系结构的主要目的是服务器的独立性。
您仍然可以使用Fault Exception
来实现这一目标使用错误合同装饰您的服务声明
[ServiceContract]
public interface IServer
{
[OperationContract]
[FaultContract(typeof(MyApplicationFault))]
DTO GetDTO();
}
然后捕获servcie实现中的错误并抛出错误异常。
[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) { ... }
希望这会有所帮助。 有关精彩的教程,请参阅Code Project Tutorial on Fault Exception