Wednesday, July 22, 2009

Silverlight and WCF Faults

The WCF FaultContract behaviour is a nice functionality to report functional faults to the invoking client. The WCF service implements this by throwing a FaultException<T> instance. The proxy side catches this, and extracts the functional error.

Well, that's the general idea. With a standard .NET WCF proxy client this works perfectly. However, in Silverlight you ran into some problems. At first, the generic version of FaultException is not available. So you cannot catch and distinguish at WCF client side a FaultException<T>, but must resort to catching generic FaultException. But the real problem is that Silverlight treats all WCF Fault HttpResponse as general CommunicationException iso SOAP FaultResponse. The underlying cause of this is that the WCF service side default sets the HTTP status code to 500 in case of an unhandled exception, even in case of the SOAP FaultException. At Silverlight side (and also Flash) any non-200 HTTP response is generally treated as a communication error. Thereby ignoring/loosing the functional fault information that is responded by the WCF service:
Several posts suggest to prevent this situation by modifying the WCF service side to not return HTTP 500 errorcode for a WCF Fault. This will work if you yourself also have the control over the WCF service. Still, personally I feel this is the wrong approach. The problem is namely at Silverlight side, so you should correct it there. Additional benefit is that you are so also prepared for SOAP faults of external webservices (WCF or other).
My solution would be to implement a custom channel for Silverlight. I thankfully used the example code on this blog for the initial setup. Next I wanted to hook into the proper place in the custom channel to convert 500 HTTP status codes into 200 codes.
However, I've to admit I failed to correct the problem at the Silverlight client side. The reason is that the HTTP transfer is handled up in the stack via inaccessible Silverlight internal clients (System.Net.BrowserHttpRequest, InternalWebRequest, ...), and that all information of the HTTP Response is lost when reaching the context of the channel. Even Reflection cannot give an helping hand here, since the responsestream is closed already when returning to the channel context.
So for now I have to satisfy with letting the own WCF service also return HTTP status code OK (200) when a functional fault is thrown. The bigger drag is the inconsistency in all of this between Silverlight versus standard .NET CLR; in the latter the SOAP response for s:fault is always given priority above the HTTP status code. I think this is as it should be. Moreover given the ongoing discussion what is the correct and standard HTTP status code in case of SOAP FAULT (SOAP and HTTP status codes (200 vs 500 etc), Issue #12: HTTP Status Codes 500 v 200).

No comments:

Post a Comment