tags:

views:

595

answers:

4

I have the standard error handing in place in my service:

  • I have an IErrorHandler hooked to the service to handle unexpected errors during service execution.
  • I have try/catch blocks in all my service methods to handle expected cases.

However, there are cases where exceptions are thrown on the server and neither is called.

Here is a case where the server exception is not sent to the IErrorHandler:

  • Set the receiveTimout on the server binding to 5 seconds.

  • On the client do this:

.

Service1Client sc = new Service1Client();
ICommunicationObject o = sc as ICommunicationObject;

o.Open(); // open channel

sc.GetData(10); // do a first call

Thread.Sleep(10000); // wait longer than the server receiveTimeout

sc.GetData(10); // Attempt another call: server throws a FaulException

In that case, the error is thrown on the server but I cannot find a way to handle it (and log it). I know an error is raised because if I attach a debugger on the server process and break on all exceptions, the debugger breaks.

I have found other similar cases where low level errors are not passed to my program.

Where can I hook my code to ensure that I can handle ALL exceptions that occur on the server before they are returned to the client app? Should I implement my own IChannel or some other low level interface?

Thanks

UPDATE Sep 21 2009: See this thread on the Microsoft WCF Forum. I'll probably have to implement my own Channel if I want to handle this type of exception. I'll update this post again when I have more info.

A: 

The point is - if the server is not reachable or can't handle the message, there won't be an error on the server - the error will pop up on the client ("TimeoutException" or others).

So in those cases, having the IErrorHandler on the server really isn't gonna help - since the error really happens on the client (no connection can be made, due to network down, or typo in server's address or sstuff like that).

So on the client side, you definitely also have to use try....catch around all your server calls.

Marc

marc_s
Not correct. It's the server that refuses to handle the call because the receiveTimeout has expired. Therefore the exception is raised by the server. As I wrote, I can attach the debugger on the server process and then I see the exception being raised; the problem is that it's not passed to a handler before it's returned to the client. I need a way to handle this exception on the server.
Sly
OK, you're right for the receiveTImeout - but other errors (esp. communication errors) might happen as the client is attempting to connect, and won't ever reach the server, and in these cases, the IErrorHandler on the server obviously is of no use, really.
marc_s
That's right; in some cases (server is down for example), the error will only occur on the client. But for those cases where it occurs on the server, I need to make sure I handle them all.
Sly
A: 

Set up diagnostic tracing and check the logs with Service Trace Viewer Tool. Link contains information about configuring tracing as well.

Artem K.
I did; I do see the error on the server in the trace. I don't want to "trace" these cases, I want to "handle" them.
Sly
The tracing will help understand where and why the exceptions are occurring is what I think he meant (trace both client and service). Correctly handling exceptions at the operation level (try/catch/throw faultexception) and an IErrorHandler should cover your bases (at least I thought). Where that might fall down is a bug in the IErrorHandler implementation or a problem with the service configuration so that the exception handling itself has an error and doesn't accurately report the problem. Definitely interested to know if this doesn't cover all bases tho!
Zach Bonham
How would you "handle" this exception?
John Saunders
@John: At the very minimum, I will log the error in my own centralized error database. We log all errors that occur on our servers. Then, we can regularly analyze all the logs and find potential problems to work on. Our customers don't always report it when they have a problem with web services so we have to be proactive. I may also want to return a different exception to the client in some specific scenarios.
Sly
+1  A: 

Use FaultContracts. Then the fault can be handled at the client end.

http://msdn.microsoft.com/en-us/library/ms732013.aspx

http://www.c-sharpcorner.com/UploadFile/ankithakur/ExceptionHandlingWCF12282007072617AM/ExceptionHandlingWCF.aspx

This is also much better for debugging, since often you will be developing a client and don't want to bring down the server for debugging purposes.

On the client end, use try/catch blocks to catch all exceptions/faults. There are definitely errors that can't be detected on the server end, such as a communication problem, so you need to handle errors on the client end anyways.

If you want centralized error handling, you can create a service that takes messages about all errors, send the error to that server, and have it log that. This can be useful if you want to create a centralized message tracing/performance analysis/logging tool and have a large number of application processors, servers, clients etc.

Larry Watanabe
I do use FaultContracts as well. But in this specific case, the error happens way before the operation execution. So I don't even have a chance to convert the exception into a FaultException<T>.
Sly
A: 

After much research and experimentation, the answer is:

At this time (.Net 3.5) there is no mechanism that allows one to handle all possible exceptions that may occur in the context of a WCF call.

Exceptions that happen during the service method execution can easily be handled with:

  1. Try/catch blocks in all service methods to handle expected cases.
  2. IErrorHandler hooked to the services to handle unexpected errors during service execution.

However, for low level WCF infrastructure errors, there is no perfect solution. The best solution that exists seems to be to implement a custom channel to catch more exceptions.

In this Microsoft Connect Bug Report, Microsoft confirms that there is no way to handle all types WCF infrastructure errors.

In this thread on the Microsoft WCF forums, there is a sample on how to implement a custom channel. That solution only works for HTTP, not for HTTPS. Also some WCF infrastructure errors are not caught by the custom channel either (see more details in that specific thread).

Sly