5

I am currently developing a Windows Phone 7 App that calls a WCF web service which I also control. The service offers an operation that returns the current user's account information when given a user's login name and password:

[ServiceContract]
public interface IWindowsPhoneService
{
    [OperationContract]
    [FaultContract(typeof(AuthenticationFault))]
    WsAccountInfo GetAccountInfo(string iamLogin, string password);
}

Of course, there is always the possibility of an authentication failure and I want to convey that information to the WP7 app. I could simply return null in that case, but I would like to convey the reason why the authentication failed (i.e. login unknown, wrong password, account blocked, ...).

This is my implementation of the above operation (for testing purposes, all it does is throwing an exception):

public WsAccountInfo GetAccountInfo(string iamLogin, string password)
{
    AuthenticationFault fault = new AuthenticationFault();
    throw new FaultException<AuthenticationFault>(fault);
}

Now, if I call this operation in my WP7 app, like this:

Global.Proxy.GetAccountInfoCompleted += new EventHandler<RemoteService.GetAccountInfoCompletedEventArgs>(Proxy_GetAccountInfoCompleted);
Global.Proxy.GetAccountInfoAsync(txbLogin.Text, txbPassword.Password);

void Proxy_GetAccountInfoCompleted(object sender, RemoteService.GetAccountInfoCompletedEventArgs e)
{
    if (e.Error != null)
    {
        MessageBox.Show(e.Error.Message);
        return;
    }
}

The debugger breaks in Reference.cs, saying that FaultException'1 was unhandled, here:

public PhoneApp.RemoteService.WsAccountInfo EndGetAccountInfo(System.IAsyncResult result) {
      object[] _args = new object[0];
      PhoneApp.RemoteService.WsAccountInfo _result = ((PhoneApp.RemoteService.WsAccountInfo)(base.EndInvoke("GetAccountInfo", _args, result)));
      return _result;
}

BEGIN UPDATE 1

When pressing F5, the exception bubbles to:

public PhoneApp.RemoteService.WsAccountInfo Result {
  get {
    base.RaiseExceptionIfNecessary();   // <-- here
    return ((PhoneApp.RemoteService.WsAccountInfo)(this.results[0]));
  }
}

and then to:

private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
{
    if (System.Diagnostics.Debugger.IsAttached)
    {
        // An unhandled exception has occurred; break into the debugger
        System.Diagnostics.Debugger.Break();
    }
}

After that, the app terminates (with or without the debugger).

END UPDATE 1

Now, I would love to catch the exception in my code, but I am never given the chance, since my Completed handler is never reached.

Based on similar questions on this site, I have already tried the following:

  • Re-add the service reference --> no change
  • Re-create a really simple WCF service from scratch --> same problem
  • Start the app without the debugger to keep the app from breaking into the debugger --> well, it doesn't break, but the exception is not caught either, the app simply exits
  • Tell VS 2010 not to break on FaultExceptions (Debug > Options) --> does not have any effect
  • wrap every line in my app in try { ... } catch (FaultException) {} or even catch (Exception) --> never called.

BEGIN UPDATE 2

What I actually would like to achieve is one of the following:

  • ideally, reach GetAccountInfoCompleted(...) and be able to retrieve the exception via the GetAccountInfoCompletedEventArgs.Error property, or

  • be able to catch the exception via a try/catch clause

END UPDATE 2

I would be grateful for any advice that would help me resolve this issue.

  • I see that you got the exception in the `EndGetAccountInfo` method, but did you try to press F5 to keep the code running and see if the `Proxy_GetAccountInfoCompleted` was called with the exception info? – Pedro Lamas Mar 19 '12 at 10:19
  • I have updated the question to include what happens after pressing F5. The exception ends up in the app's Application_UnhandledException handler. – Chris Leesch Mar 19 '12 at 11:34
  • 1
    Check the proxy class if the methods are marked with `[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]` – Pedro Lamas Mar 19 '12 at 12:17
  • No, they weren't. I tried adding the attribute to the relevant methods, but it didn't change anything. – Chris Leesch Mar 19 '12 at 14:15
  • That attribute was in a proxy class I have generated a long time ago for a WP7 app of mine... If I recall well, I generated it adding the service reference to the project and it added that attribute (that seems related to the current problem); I know this is really just guessing, but have you tryed to regenerate/refresh the proxy or recheck the config. you setted when you added it? – Pedro Lamas Mar 19 '12 at 14:36
  • If I update the service reference, all the attributes I had added manually are removed. As for configuration, I didn't make any changes. I added a service reference via the VS2010 GUI, and in the case of a WP7 app, most configuration options (like async ops) are essentially preconfigured and read-only. – Chris Leesch Mar 19 '12 at 14:42
  • Same issue if the device does not have internet connection and you want to handle this situation. Exception is thrown on some background thread in the WCF proxy. – Stilgar Jan 17 '13 at 09:37

2 Answers2

0

The framework seems to read your WsAccountInfo.Result property. This rethrows the exception on client side. But you should be the first to read this property.

I don't know your AuthenticationFault class, does it have a DataContractAttribute and is it a known type like the example in http://msdn.microsoft.com/en-us/library/system.servicemodel.faultcontractattribute.aspx ?

Stefan Forster
  • 405
  • 4
  • 7
0

I believe I had the same problem. I resolved it by extending the proxy class and calling the private Begin.../End... methods within the Client object rather than using the public auto-generated methods on the Client object.

For more details, please see: http://cbailiss.wordpress.com/2014/02/09/wcf-on-windows-phone-unable-to-catch-faultexception/

cbailiss
  • 1,304
  • 11
  • 21