Logo




Subscribe:
RSS 2.0 | Atom 1.0
Categories:

Sign In


[Giagnocavo]Michael::Write()

# Thursday, December 11, 2008
Full Typed Faults in Silverlight 2 (FaultException)
Silverlight 2 doesn't support faults, so you can't catch them. That sucks, since WCF's FaultException<T> is pretty useful. In Beta 1 I did a vile hack to get some data. After reading online, Id determined that Silverlight should be able to intercept the fault message and interpret it. Unfortunately, some of the handy classes to insert yourself into the stack aren't in Silverlight's WCF. Fortunately, there is a sample that does most of it:

http://code.msdn.microsoft.com/silverlightws/Release/ProjectReleases.aspx?ReleaseId=1660

In the "Message Inspectors" sample. This sample has code to let you inspect messages, and it also has a sample where they throw "raw" faults (i.e., "wrapped exceptions", aka "ExceptionDetail"). Why they stopped there is beyond me. With a bit of hacking (I must say, this SOAP stuff looks very complex), I got it to recognize any fault type, and throw a FaultException<T>. Well, not a FaultException<T>, 'cause there is a neutered FaultException class already in System.ServiceModel from Silverlight. So I named mine "SLFaultException" (SL for Simple Lame).

To get the fault thrown, you need to hookup the SilverlightFaultMessageInspector. From the demo code:
            EndpointAddress address = new EndpointAddress("http://127.0.0.1:52620/Service.svc");
            BasicHttpMessageInspectorBinding binding = new BasicHttpMessageInspectorBinding(new SilverlightFaultMessageInspector());
            ServiceClient proxy = new ServiceClient(binding, address);
            proxy.DoWorkCompleted += new System.EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(proxy_DoWorkCompleted);
            proxy.DoWorkAsync();
You also need to register the assembly's types so that the fault throwing code can find the fault detail to deserialize. There's no way in Silverlight to get all the loaded assemblies (as far as I know). So we do this:
   System.ServiceModel.SilverlightFaultMessageInspector.RegisterCurrentAssembly();

This registers the calling assembly's types to be searched when a fault detail is received.

Now the only thing that needs to be done is fixup the HTTP 500 status code to a 200. The MS sample has a behaviour to do this. But that's annoying, having another DLL to deploy and deal with. So I do this in the Global.asax:
        protected void Application_EndRequest(object sender, EventArgs e) {
if (HttpContext.Current.Request.PhysicalPath.EndsWith(".svc", StringComparison.OrdinalIgnoreCase) &&
HttpContext.Current.Response.StatusCode == 500 &&
!HttpContext.Current.Request.Browser.Crawler &&
HttpContext.Current.Request.Browser.EcmaScriptVersion.Major > 0) {
// Set 200 if its a faulted service request
HttpContext.Current.Response.StatusCode = 200;
}
}
From there, go ahead and catch SLFaultException<T> just like you would a FaultException<T>.

Overall, this proved far easier than I expected. I'm at a complete loss why they didn't ship faults in SL2. I mean, if I hacked _something_ out in an hour or two, I'm sure someone who had some clue of what they're doing could have done so easier. Heck, they even have the real WCF source -- I was stuck using Reflector for parts :P.

SilverlightFaultsBinary.zip (13.81 KB)

SilverlightFaultsSource.zip (61.55 KB)
Code
Thursday, December 11, 2008 2:04:45 AM UTC  #    Comments [4]  |  Trackback

Friday, December 26, 2008 1:57:55 PM UTC
I've tried implementing this in my Silverlight client, but I am stuck... when I run my code it complains that the exception I throw in AfterReceiveReply() is unhandled. Is there anything special I need to implement to get this exception to be handled (so that my 'DoWorkCompleted' handler will be called) ? I have looked over (and over) your code and the Microsoft sample, but can't figure it out! It is driving me crazy!
Friday, December 26, 2008 6:43:33 PM UTC
Oh, I don't use the event based async stuff -- maybe that's the problem. Try it with the better BeginXXX/EndXXX pattern and see if that fixes it.
Tuesday, December 30, 2008 2:53:48 PM UTC
Thanks -- once I made the change to the BeginXXX/EndXXX pattern things fell right into place.
Tuesday, April 21, 2009 11:20:29 PM UTC
Is it possible to define the binding in configuration?
OpenID
Please login with either your OpenID above, or your details below.
Name
E-mail
Home page

Comment (HTML not allowed)  

Enter the code shown (prevents robots):

Live Comment Preview