WCF on Windows Phone – Unable to Catch Exception

Disclaimer!:  I am not a Window Phone Expert though dabble occasionally…

Summary

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.

Scenario

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:

Method: AddWindowsPhoneStatusSubscriptionAsync(oRequest);

Event: AddWindowsPhoneStatusSubscriptionCompleted

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.

Workaround

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:

20140209-01

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.

 Additional Detail

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)

Advertisements

One comment


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s