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

时间:2011-03-21 06:16:00

标签: c# wcf exception-handling

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

try {
   client.MyWebService()
}
catch(? ex)
{
   // display friendly dialog explaining what went wrong
}

我应该在代码中用什么异常代替问号?当一切工作顺利并且我无法控制外部部件时,很难真正测试这样的情况,所以一些见解会受到赞赏。

谢谢!

3 个答案:

答案 0 :(得分:6)

要做的第一件事就是利用代理上的.Fululted事件,你可以像这样连接:

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

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

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

对于异常本身,您可以让您的服务抛出FaultException,并通过您提供的详细信息传递回客户端。请参阅this blog posting中使用的示例。

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

对于频道错误,您可能会获得CommunicationExceptionTimeoutException

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

答案 1 :(得分:1)

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

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));
}

答案 2 :(得分:1)

我问了同样的问题,因为我必须在我的客户端应用程序上对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èleLerouxBustamante 的文章(显然是异常处理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<TDetail>来自FaultException,而FaultException来自CommunicationException