Disclaimer!: I am not a Window Phone Expert though dabble occasionally…
When consuming a basic WCF Service on Windows Phone 8, exceptions aren’t handled in the proxy class and don’t reach user code. As a result it is impossible to easily handle them until the exception reaches the Apps global exception handler – far from the original code that called the WCF service (ugly). A workaround is to make use of some private methods in the auto-generated proxy class to catch the faults.
It took me a couple of hours to work through this. There are some unanswered questions on Stack Overflow related to this, so I thought I’d share my workaround.
I have a basic WCF service, TrainDataAdminSvc, which exposes a method called AddWindowsPhoneStatusSubscription. The details of what the service does aren’t relevant here.
When consuming this service in my Windows Phone 8 project, the auto-generated proxy class is named TrainDataAdminClient and exposes the following:
If a fault occurs calling the WCF service, be it a FaultException from the service or some other exception, the exception is first visible in the proxy class – in the TrainDataAdminClientChannel.EndAddWindowsPhoneStatusSubscription method:
An exception of type ‘System.ServiceModel.FaultException`1’ occurred in System.ServiceModel.ni.dll but was not handled in user code
The stack trace (at the point the error is seen in the debugger) is:
- [External Code]
- > TD Admin.DLL!TD_Admin.TrainDataAdmin.TrainDataAdminClient.TrainDataAdminClientChannel.EndAddWindowsPhoneStatusSubscription(System.IAsyncResult result) Line 1601 C#
- [External Code]
The method EndAddWindowsPhoneStatusSubscription in the proxy class contains no error handler. Apparently, neither does the calling external code. My code in the AddWindowsPhoneStatusSubscriptionCompleted event handler both has a try-catch block and examines the event arguments for any error. However, this code is never invoked. Instead, the error bubbles straight up to the applications UnhandledException global event handler. All in all, pretty horrible.
Luckily, the proxy class includes BeginAddWindowsPhoneStatusSubscription and EndAddWindowsPhoneStatusSubscription methods. Unfortunately, these are private. However, as luck would have it, the proxy class is declared as a partial class, allowing us easy access to these methods. Thus, I can extend the proxy class as follows:
Since it is now my code that is calling EndAddWindowsPhoneStatusSubscription, I can easily catch any exceptions in the normal way. In the example above, the try-catch is not shown and instead wraps the call to AddWindowsPhoneStatusSubscription. In this example, I wanted to effectively call the WCF service synchronously. To recreate the event-based call pattern requires a little extra code. The important thing however, is that it is finally possible to catch exceptions.
For reference, the StackTrace seen on the Exception is shown below. Again, all of this is either code in the framework or code in the proxy class.
at System.ServiceModel.Channels.ServiceChannel.ThrowIfFaultUnderstood(Message reply, MessageFault fault, String action, MessageVersion version, FaultConverter faultConverter)
at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object outs, IAsyncResult result)
at System.ServiceModel.ClientBase`1.ChannelBase`1.EndInvoke(String methodName, Object args, IAsyncResult result)
at TD_Admin.TrainDataAdmin.TrainDataAdminClient.TrainDataAdminClientChannel.EndAddWindowsPhoneStatusSubscription(IAsyncResult result)
at TD_Admin.TrainDataAdmin.TrainDataAdminClient.TD_Admin.TrainDataAdmin.ITrainDataAdmin.EndAddWindowsPhoneStatusSubscription(IAsyncResult result)
at TD_Admin.TrainDataAdmin.TrainDataAdminClient.OnEndAddWindowsPhoneStatusSubscription(IAsyncResult result)
at System.ServiceModel.ClientBase`1.OnAsyncCallCompleted(IAsyncResult result)