我有一个调用外部Web服务的程序,我希望向用户展示一个友好的对话框,例如服务器关闭,有人切断电缆等。假设以下代码
try {
client.MyWebService()
}
catch(? ex)
{
// display friendly dialog explaining what went wrong
}
我应该在代码中用什么异常代替问号?当一切工作顺利并且我无法控制外部部件时,很难真正测试这样的情况,所以一些见解会受到赞赏。
谢谢!
答案 0 :(得分:6)
要做的第一件事就是利用代理上的.Fululted事件,你可以像这样连接:
((ICommunicationObject)client).Faulted += new EventHandler(client_Faulted);
在client_Faulted
事件处理程序中,您可以尝试重新连接,或转移到备份服务器,或禁用UI,记录错误或在那里显示消息。
在try-catch中包装每个调用显然仍然是一个好习惯,但是.Fululted事件可以让你更早地处理大多数通道问题。
对于异常本身,您可以让您的服务抛出FaultException
,并通过您提供的详细信息传递回客户端。请参阅this blog posting中使用的示例。
如果通道本身发生故障,您将不会收到FaultException(FaultException是服务器将自己的内部故障传达给客户端的一种方式)。
对于频道错误,您可能会获得CommunicationException
或TimeoutException
。
最后,查看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
。