WCF Web 服务调用 - 要捕获哪些异常?

Posted

技术标签:

【中文标题】WCF Web 服务调用 - 要捕获哪些异常?【英文标题】:WCF web service call - which exception(s) to catch? 【发布时间】:2011-07-19 11:12:35 【问题描述】:

我有一个调用外部 Web 服务的程序,我想向用户展示一个友好的对话框,例如:服务器停机,有人切断电缆等。假设以下代码

try 
   client.MyWebService()

catch(? ex)

   // display friendly dialog explaining what went wrong

我应该用什么异常来代替代码中的问号?当一切顺利并且我无法控制外部部分时,实际测试这样的情况有点困难,因此我们将不胜感激。

谢谢!

【问题讨论】:

如果你想尝试一些特定的场景,那么……试试看会发生什么?在某种程度上,答案取决于不泄露已知细节以外的任何细节有多重要——即是否可以显示“糟糕,出了点问题”+ ex.Message 虽然从安全的角度来看“糟糕...”消息可能没问题,但我更喜欢更具体的内容。 “两扇门下的那位女士正在做一些家务,目前在现场的两名工人中个子较高的 Jim 不小心将一把铁锹插入了接线盒;一位电信工程师被叫来,但首先还有另外 2 份工作,另外还想吃他面包车里的那个肉丸子;这将在 14:12 前解决”——不确定是否有特定的例外...... ;p 【参考方案1】:

首先要做的是利用代理上的 .Faulted 事件,您可以这样连接:

((ICommunicationObject)client).Faulted += new EventHandler(client_Faulted);

在您的 client_Faulted 事件处理程序中,您可以尝试重新连接,或转移到备份服务器,或禁用 UI、记录错误或在此处显示消息。

显然,将每个调用也包含在一个 try-catch 中仍然是一种好习惯,但是 .Faulted 事件可以让您更早地处理大多数通道问题。

至于异常本身,您可以让您的服务抛出一个FaultException,并使用您提供的详细信息将其传递回客户端。在this blog posting 上查看其使用示例。

如果通道本身发生故障,您将不会收到 FaultException(FaultException 是服务器将自己的内部故障传达给客户端的一种方式)。

对于通道故障,您可能会收到CommunicationExceptionTimeoutException

最后,看看 Codeplex 上的 this project 用于生成异常处理 WCF 代理。它可以为您提供更灵活的故障处理方式。

【讨论】:

【参考方案2】:

提供尽可能多的细节并不是客户的工作。您真正必须在客户端提供的最大金额与您在异常中获得的金额一样多。

var userName = "bob";
try 
      
   client.MyWebService(userName);

catch(Exception ex)

   //Maybe we know WellKnownExceptions and can provide Foo advice:
   if (ex is WellKnownException)
   
       Console.WriteLine("WellKnownException encountered, do Foo to fix Bar.");
   
   //otherwise, this is the best you can do:
   Console.WriteLine(string.Format(
         "MyWebService call failed for 0. Details: 1", userName, ex));

【讨论】:

如果您知道它可能会抛出 WellKnownException,那么您应该将其设为单独的 catch(WellKnownException wkex) 块。 @CLaw:这是风格问题。您可以根据异常类型以这种风格执行更简洁的 if/then/else 逻辑,而不是每个都有自己的 catch 块。不过,我的示例并没有真正证明这一点。【参考方案3】:

我问了同样的问题,因为我必须在我的客户端应用程序的 Web 服务调用上实现一些异常处理,所以我最终来到了这里。虽然这是一个老问题,但我想给我两分钱,稍微更新一下。

C给出的答案。 Lawrence Wenham 已经非常好,并指出了一些有趣的信息,尽管博客链接已损坏并且 Codeplex 现在已存档。

我发现那些文章很有价值:

收发故障https://docs.microsoft.com/en-us/dotnet/framework/wcf/sending-and-receiving-faults

预期异常https://docs.microsoft.com/en-us/dotnet/framework/wcf/samples/expected-exceptions

Michèle Leroux Bustamante(显然是异常处理 WCF 代理生成器 CodePlex 项目的创建者)的这篇文章也非常有见地:

优雅的异常处理代理解决方案http://www.itprotoday.com/microsoft-visual-studio/elegant-exception-handling-proxy-solution

我仍在研究这个主题,但我想我会使用很多来自 Michèle 的想法。我只是有点担心使用反射来调用 Web 服务的方法,但我想知道这是否会对这种操作产生任何影响,这本来就很慢。

在这里明确回答最初询问的内容,哪些是可以针对 Web 服务调用进行测试的异常:

string errorMessage = null;

// A class derived from System.ServiceModel.ClientBase.
MyWebService wcfClient = new MyWebService();
try

   wcfClient.Open();
   wcfClient.MyWebServiceMethod();

catch (TimeoutException timeEx)

   // The service operation timed out.
   errorMessage = timeEx.Message;

catch (FaultException<ExceptionDetail> declaredFaultEx)

   // An error on the service, transmitted via declared SOAP
   // fault (specified in the contract for an operation).
   errorMessage = declaredFaultEx.Detail.Message;

catch (FaultException unknownFaultEx)

   // An error on the service, transmitted via undeclared SOAP
   // fault (not specified in the contract for an operation).
   errorMessage = unknownFaultEx.Message;

catch (CommunicationException commEx)

   // A communication error in either the service or client application.
   errorMessage = commEx.Message;

finally

   if (wcfClient.State == CommunicationState.Faulted)
      wcfClient.Abort();
   else
      wcfClient.Close();

如文章所述,捕获异常的顺序很重要,因为FaultException&lt;TDetail&gt; 派生自FaultException,而FaultException 派生自CommunicationException

【讨论】:

以上是关于WCF Web 服务调用 - 要捕获哪些异常?的主要内容,如果未能解决你的问题,请参考以下文章

WCF 捕获异常“服务器没有提供有意义的回复..”

从 Web 异常调用 WCF

WCF 捕获异步异常

客户端的 WCF Web 服务自定义异常错误

调试 WCF Web 服务故障

WCF 跨域使用 Jsonp 错误未捕获语法错误:意外令牌: