I have a program that calls an external web service, and I want to present the user with a friendly dialog if e.g. the server is down, someone cut the cable etc. Assuming th
I was asking the same question, as I have to implement some exception handling on web services calls at my client application, so I ended up here. Although it's an old question, I'd like to give my two cents, updating it a little bit.
The answer given by C. Lawrence Wenham was already very good and points to some interesting information, although the blog link is broken and Codeplex is now archived.
I found those articles very valuables:
Sending and Receiving Faults
https://docs.microsoft.com/en-us/dotnet/framework/wcf/sending-and-receiving-faultsExpected Exceptions
https://docs.microsoft.com/en-us/dotnet/framework/wcf/samples/expected-exceptions
And this article from Michèle Leroux Bustamante (apparently the creator of the Exception Handling WCF Proxy Generator CodePlex project) is very insighful also:
An Elegant Exception-Handling Proxy Solution
http://www.itprotoday.com/microsoft-visual-studio/elegant-exception-handling-proxy-solution
I'm still studying the subject but I guess I'll use a lot of ideias from Michèle. I'm just a little bit concerned about using reflection to call the web service's methods, but I wonder if this would have any impact in such kind of operation, that is inherently slow already.
Just to answer here explicitly what was asked originally, which are the exceptions that could be tested against a web service call:
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();
}
As stated by the articles, the order the exceptions are catched is important, since FaultException<TDetail>
derives from FaultException
, and FaultException
derives from CommunicationException
.
It's not really the client's job to provide as much detail as possible. The maximum amount you really have to provide at the client side is as much as you get back in your exception.
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));
}
The first thing to do is take advantage of the .Faulted event on your proxy, which you can wire up like this:
((ICommunicationObject)client).Faulted += new EventHandler(client_Faulted);
In your client_Faulted
event handler you can then try re-connecting, or shifting to a backup server, or disabling the UI, logging the error, or displaying a message there.
It's obviously still good practice to wrap each call in a try-catch as well, but the .Faulted event can let you deal with most channel problems even earlier.
As for the exception itself, you can have your service throw a FaultException
that gets passed back to the client with the details you provide. See an example of its use at this blog posting.
You won't get a FaultException if the channel itself fails (FaultException is a way for the server to communicate its own internal faults to the client).
For channel faults, you may get a CommunicationException
or TimeoutException
.
Finally, take a look at this project on Codeplex for generating Exception Handling WCF proxies. It may give you a more flexible way of handing faults.