Handling WCF errors - c#

I have a desktop c# app that uploads a stream of images to my server using WCF.
For testing I wanted to simulate handling errors when my server is down.
When I looked on MSDN it told me to use the Abort method, which I implemented.
This is my code:
try
{
wcf.UploadMotionDynamicRaw(package);
}
catch (TimeoutException tex)
{
wcf.Abort();
//log error
}
catch (ServiceActivationException sae)
{
wcf.Abort();
//log error
}
catch (CommunicationException)
{
wcf.Abort();
ErrorLogger.AddError("Engine", "ProcessFrame.3", new Exception("Service Communication Error"));
}
catch (Exception ex)
{
wcf.Abort();
//log error
}
So, to test this I run my client app. I went to my server and stopped IIS. I waited a few seconds and restarted IIS.
The streaming did not resume.
I am guessing that after I used Abort() I would need to reconnect my client?
If so then that would be impractical for my application.
Is there a better way of dealing with server/internet issues in terms of 'tidying up' after an error has been thrown?
Thanks

Related

If I have a catch exception will everything be caught, even with COM object?

I have noticed in production that our IIS app dies (app pool shutdown) and when this does happen I see an error in the COM object that our application uses. It happens infrequently so it is difficult to debug what is causing the error.
I have put a try...catch(Exception e){} block around the COM code and I was wondering if this random COM object is not being caught.
Is it this possible? In other words if the COM exception occurs it will be caught?
Yes you will catch it with
try
{
//code here
}
catch (System.Runtime.InteropServices.COMException COMex)
{
//you can try this too. Check this answer http://stackoverflow.com/questions/898726/why-would-this-catch-all-block-not-in-fact-catch-all
}
catch (Exception ex)
{
//do things
}
You can check the Microsoft documentation about the exception and see that inherits System.Exception

How can I close WCF Service connections when I close my program

I am hosting my WCF service on a windows Azure website. In my program I select between 1-16 users and for each user selected I contact my wcf service and return the data using the format below:
try
{
...
client.Close();
}
catch (CommunicationException e)
{
...
client.Abort();
}
catch (TimeoutException e)
{
...
client.Abort();
}
catch (Exception e)
{
...
client.Abort();
throw;
}
The WCF service is contacting an azure SQL database to get the data which means the service call may last up to 10 seconds in total. But if i close the program while retreiving data and open it again and try to retrieve data the connection times out and I get a HTTP server error on my azure website which is then subsequently down for 2-3 minutes.
How can I close the WCF service connections on closing my program. should I be using a "Using" statment instead? And also should I try refactor my code to only contact the service once rather than once for each user selected?
It will be closed automatically. But if you want to be sure, you can use finally block:
try
{
...
client.Close();
}
finally
{
if(client.State != CommunicationState.Closed)
client.Abort();
}
When you said you close the program, did you close the program through terminating the process in Task Manager? If so, because the program is closed disgracefully, there may not be Tcp/IP conversation for closing the connection.
If you close the program gracefully so client.dispose() will be called, the server will be acknowledged of the closure of the connection, rather than waiting for tcp/ip packet arriving and keeping the connection open.
You may be using try-finally block as Uriil suggested.
or
try
{
using (...)
{
...
}
}
catch (some exceptions...

Reading data from a server and detecting network unavailability in C#

I have a simple task: to read data from a server, if the server is unreachable (server down or bad network), load data (possibly stale) from local disk cache.
Here's a simple pseudo representation of what the Java code would look like:
try {
//read from server
} catch (IOException ioe) {
//most likely a socket timeout exception
//read from local disk
} finally {
//free I/O resources
}
but implementing that in C# doesn't seem to work as WebClient doesn't seem to throw any exception even when there's no internet access on the host machine so there's no way to detect that condition via the catch block and revert back to the local cache.
I'm aware of WebClient's async APIs and its rather funny callback chain but I perceive this as too awkward and doesn't suit my design goal properly. Is there a way I can do this in C# as easily as the Java skeleton code shown above? Thanks.
WebClient will timeout, but only after 100s.
I would recommend you use HttpWebRequest instead. This has a settable timeout property.
See http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.timeout.aspx
Furthermore to bobbymond's answer, it's a WebException that will be returned by the WebClient, so that's what you're looking to catch:
WebClient wc = new WebClient();
try
{
wc.Credentials = new NetworkCredential("Administrator", "SomePasword", "SomeDomain");
byte[] aspx = wc.DownloadData("http://SomeServer/SomeSub/SomeFile.aspx");
}
catch (WebException we)
{
//Catches any error in the WebClient, including an inability to contact the remote server
}
catch (System.Exception ex)
{
}

Exception in "using" statement with WCF not closing connections properly. How does one close faulted WCF client connections or those with exceptions?

There are several questions on StackOverflow regarding closing WCF connections, however the highest ranking answers refers to this blog:
http://marcgravell.blogspot.com/2008/11/dontdontuse-using.html
I have a problem with this technique when I set a breakpoint at the server and let the client hang for more than one minute. (I'm intentionally creating a timeout exception)
The issue is that the client appears to "hang" until the server is done processing. My guess is that everything is being cleaned up post-exception.
In regard to the TimeOutException it appears that the retry() logic of the client will continue to resubmit the query to the server over and over again, where I can see the server-side debugger queue up the requests and then execute each queued request concurrently. My code wan't expecting WCF to act this way and may be the cause of data corruption issues I'm seeing.
Something doesn't totally add up with this solution.
What is the all-encompassing modern way
of dealing with faults and exceptions
in a WCF proxy?
Update
Admittedly, this is a bit of mundane code to write. I currently prefer this linked answer, and don't see any "hacks" in that code that may cause issues down the road.
This is Microsoft's recommended way to handle WCF client calls:
For more detail see: Expected Exceptions
try
{
...
double result = client.Add(value1, value2);
...
client.Close();
}
catch (TimeoutException exception)
{
Console.WriteLine("Got {0}", exception.GetType());
client.Abort();
}
catch (CommunicationException exception)
{
Console.WriteLine("Got {0}", exception.GetType());
client.Abort();
}
Additional information
So many people seem to be asking this question on WCF that Microsoft even created a dedicated sample to demonstrate how to handle exceptions:
c:\WF_WCF_Samples\WCF\Basic\Client\ExpectedExceptions\CS\client
Download the sample:
C# or VB
Considering that there are so many issues involving the using statement, (heated?) Internal discussions and threads on this issue, I'm not going to waste my time trying to become a code cowboy and find a cleaner way. I'll just suck it up, and implement WCF clients this verbose (yet trusted) way for my server applications.
Optional Additional Failures to catch
Many exceptions derive from CommunicationException and I don't think most of those exceptions should be retried. I drudged through each exception on MSDN and found a short list of retry-able exceptions (in addition to TimeOutException above). Do let me know if I missed an exception that should be retried.
Exception mostRecentEx = null;
for(int i=0; i<5; i++) // Attempt a maximum of 5 times
{
try
{
...
double result = client.Add(value1, value2);
...
client.Close();
}
// The following is typically thrown on the client when a channel is terminated due to the server closing the connection.
catch (ChannelTerminatedException cte)
{
mostRecentEx = cte;
secureSecretService.Abort();
// delay (backoff) and retry
Thread.Sleep(1000 * (i + 1));
}
// The following is thrown when a remote endpoint could not be found or reached. The endpoint may not be found or
// reachable because the remote endpoint is down, the remote endpoint is unreachable, or because the remote network is unreachable.
catch (EndpointNotFoundException enfe)
{
mostRecentEx = enfe;
secureSecretService.Abort();
// delay (backoff) and retry
Thread.Sleep(1000 * (i + 1));
}
// The following exception that is thrown when a server is too busy to accept a message.
catch (ServerTooBusyException stbe)
{
mostRecentEx = stbe;
secureSecretService.Abort();
// delay (backoff) and retry
Thread.Sleep(1000 * (i + 1));
}
catch(Exception ex)
{
throw ex; // rethrow any other exception not defined here
}
}
if (mostRecentEx != null)
{
throw new Exception("WCF call failed after 5 retries.", mostRecentEx );
}
Closing and Disposing a WCF Service
As that post alludes to, you Close when there were no exceptions and you Abort when there are errors. Dispose and thus Using shouldn't be used with WCF.

WCF/C# Unable to catch EndpointNotFoundException

I have created a WCF service and client and it all works until it comes to catching errors. Specifically I am trying to catch the EndpointNotFoundException for when the server happens not to be there for whatever reason. I have tried a simple try/catch block to catch the specific error and the communication exception it derives from, and I've tried catching just Exception. None of these succeed in catching the exception, however I do get
A first chance exception of type
'System.ServiceModel.EndpointNotFoundException'
occurred in System.ServiceModel.dll
in the output window when the client tries to open the service. Any ideas as to what I'm doing wrong?
I was able to replicate your issue and got interested (since I needed the same). I even researched a way to handle \ catch first chance exceptions but unfortunately it is not possible (for managed code) for .net framework 3.5 and below.
On my case I always get a System.ServiceModel.CommunicationObjectFaultedException whenever something gets wrong on the service or whenever I access a down service. It turns out that c#'s using statement is the cause since behind the scene, the using statement always closes the service client instance even if an exception was already encountered (it doesn't jump to catch statement directly).
What happens is that the original exception System.ServiceModel.EndpointNotFoundException will be replaced by the new exception System.ServiceModel.CommunicationObjectFaultedException whenever the using tries to close the service client instance.
The solution i've made is to not use the using statement so that whenever an exception is encountered inside the try block it will instantly throw the exception to the catch blocks.
Try to code something like:
DashboardService.DashboardServiceClient svc = new Dashboard_WPF_Test.DashboardService.DashboardServiceClient();
try
{
svc.GetChart(0);
}
catch (System.ServiceModel.EndpointNotFoundException ex)
{
//handle endpoint not found exception here
}
catch (Exception ex)
{
//general exception handler
}
finally
{
if (!svc.State.Equals(System.ServiceModel.CommunicationState.Faulted) && svc.State.Equals(System.ServiceModel.CommunicationState.Opened))
svc.Close();
}
Instead of:
try
{
using (DashboardService.DashboardServiceClient svc = new Dashboard_WPF_Test.DashboardService.DashboardServiceClient())
{
svc.GetChart(0);
}
}
catch (System.ServiceModel.EndpointNotFoundException ex)
{
//handle endpoint not found exception here (I was never able to catch this type of exception using the using statement block)
}
catch (Exception ex)
{
//general exception handler
}
And you'll be able to catch the right exception then.
Take a look at this post for details on this possible solution. The code shows use of a generate proxy but is valid on ChannelFactory and others as well.
Typical here-be-dragons pattern
using (WCFServiceClient c = new WCFServiceClient())
{
try
{
c.HelloWorld();
}
catch (Exception ex)
{
// You don't know it yet but your mellow has just been harshed.
// If you handle this exception and fall through you will still be cheerfully greeted with
// an unhandled CommunicationObjectFaultedException when 'using' tries to .Close() the client.
// If you throw or re-throw from here you will never see that exception, it is gone forever.
// buh bye.
// All you will get is an unhandled CommunicationObjectFaultedException
}
} // <-- here is where the CommunicationObjectFaultedException is thrown
Proper pattern:
using (WCFServiceClient client = new WCFServiceClient())
{
try
{
client.ThrowException();
}
catch (Exception ex)
{
// acknowledge the Faulted state and allow transition to Closed
client.Abort();
// handle the exception or rethrow, makes no nevermind to me, my
// yob is done ;-D
}
}
Or, as expressed in your question without a using statement,
WCFServiceClient c = new WCFServiceClient();
try
{
c.HelloWorld();
}
catch
{
// acknowledge the Faulted state and allow transition to Closed
c.Abort();
// handle or throw
throw;
}
finally
{
c.Close();
}
This may be a reporting issue for the debugger, rather than not actually catching the exception. this post gives some tips on resolving it, if that is the case... Why is .NET exception not caught by try/catch block?
What is a First Chance Exception?
First chance exception messages most
often do not mean there is a problem
in the code. For applications /
components which handle exceptions
gracefully, first chance exception
messages let the developer know that
an exceptional situation was
encountered and was handled.
Place a try catch block in the CompletedMethod.
An Example:
...
geocodeService.ReverseGeocodeCompleted += ReverseGeocodeCompleted(se, ev);
geocodeService.ReverseGeocodeAsync(reverseGeocodeRequest);
}
private void ReverseGeocodeCompleted(object sender, ReverseGeocodeCompletedEventArgs e)
{
try
{
// something went wrong ...
var address = e.Result.Results[0].Address;
}
catch (Exception)
{ // Catch Exception
Debug.WriteLine("NO INTERNET CONNECTION");
}

Categories