Bug 59318 - WCF Fault Exception Cannot Deserialize FaultDetail
Summary: WCF Fault Exception Cannot Deserialize FaultDetail
Status: CONFIRMED
Alias: None
Product: Android
Classification: Xamarin
Component: General (show other bugs)
Version: unspecified
Hardware: PC Windows
: --- normal
Target Milestone: ---
Assignee: Jonathan Pryor
URL:
Depends on:
Blocks:
 
Reported: 2017-09-08 04:09 UTC by Melbourne Developer
Modified: 2017-09-25 04:28 UTC (History)
9 users (show)

See Also:
Tags: Android WCF faultdetail faultexception faultcontract mono
Is this bug a regression?: ---
Last known good build:


Attachments

Description Melbourne Developer 2017-09-08 04:09:00 UTC
If a FaultException with a generic type argument (FaultDetail) is thrown on the WCF service side, an Android app will not catch the exception as a FaultException. Instead a normal Exception object will be caught which contains an error regarding deserialization of the FaultException. This behaviour works in UWP, but not Android. It is easy to reproduce this problem. The steps are outlined here:

***Get Code***
-Clone this repo: https://github.com/MelbourneDeveloper/xamarin-forms-samples.git (It's a fork of the forms samples)

***Run WCF Service***
-Open up the server side sample app. (WebServices\TodoWCF\TodoWCFService\TodoWCFService.sln)
-Go to project properties -> Web.
-Click "Create Virtual Directory" to create it as an IIS app
-Compile and run this service in debug mode. 

***Run UWP (Working Sample)***
-Open the client side sample app (Xamarin Forms) (WebServices\TodoWCF\TodoWCF.sln)
-Open the file "Constants.cs" in the TodoWCF (Portable) project.
-Change the Url here to point to your computer's machine name or IP address (test that the Url is working in a browser)
-Set the startup app to the UWP project
-Put breakpoints on 27, and 31 of TodoItemPage.xaml.cs
-Run the app
-Click the + button in the top right and corner of the screen
-Click Save
-A WCF exception will occur
-Hit F5
-Notice that you will hit line 27 which means that the exception is caught as a FaultException.
-Notice that the message says "Error: TodoItem name and notes fields are required" and this error is correctly displayed on screen. The message has come from the server side.

***Run Android (Broken Sample)***
-Set the startup app to the Droid project
-Run the app
-Click the + button in the top right and corner of the screen
-Click Save
-Notice that you will hit line 31 which means that the exception is caught as a generic Exception (not FaultException).
-Notice that the exception is a serialization exception with nothing meaningful from the server side. The result is different from the UWP version. 

Error in line 1 position 196. Expecting element 'ExceptionDetail' from namespace 'http://schemas.datacontract.org/2004/07/System.ServiceModel'.. Encountered 'Element'  with name 'FaultExceptionDetail', namespace 'http://schemas.datacontract.org/2004/07/TodoWCFService'.

{System.Runtime.Serialization.SerializationException: Error in line 1 position 196. Expecting element 'ExceptionDetail' from namespace 'http://schemas.datacontract.org/2004/07/System.ServiceModel'.. Encountered 'Element'  with name 'FaultExceptionDetail', namespace 'http://schemas.datacontract.org/2004/07/TodoWCFService'.
  at (wrapper managed-to-native) System.Object:__icall_wrapper_mono_delegate_end_invoke (object,intptr)
  at (wrapper delegate-end-invoke) <Module>:end_invoke_object__this___object[]&_IAsyncResult (object[]&,System.IAsyncResult)
  at System.ServiceModel.MonoInternal.ClientRuntimeChannel.EndProcess (System.Reflection.MethodBase method, System.String operationName, System.Object[] parameters, System.IAsyncResult result) [0x0001f] in <475dec2c1fe44b95bbfbd21b550b63f8>:0 
  at System.ServiceModel.ClientBase`1+ChannelBase`1[TChannel,T].EndInvoke (System.String methodName, System.Object[] args, System.IAsyncResult result) [0x00045] in <475dec2c1fe44b95bbfbd21b550b63f8>:0 
  at TodoWCF.TodoWCFService.TodoServiceClient+TodoServiceClientChannel.EndCreateTodoItem (System.IAsyncResult result) [0x00008] in C:\GitRepos\xamarin-forms-samples\WebServices\TodoWCF\TodoWCF\Service References\TodoWCFService\Reference.cs:533 
  at TodoWCF.TodoWCFService.TodoServiceClient.TodoWCF.TodoWCFService.ITodoService.EndCreateTodoItem (System.IAsyncResult result) [0x00001] in C:\GitRepos\xamarin-forms-samples\WebServices\TodoWCF\TodoWCF\Service References\TodoWCFService\Reference.cs:283 
  at System.Threading.Tasks.TaskFactory`1[TResult].FromAsyncCoreLogic (System.IAsyncResult iar, System.Func`2[T,TResult] endFunction, System.Action`1[T] endAction, System.Threading.Tasks.Task`1[TResult] promise, System.Boolean requiresSynchronization) [0x00019] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
  at System.Runtime.CompilerServices.TaskAwaiter.GetResult () [0x00000] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
  at TodoWCF.SoapService+<SaveTodoItemAsync>d__9.MoveNext () [0x0008c] in C:\GitRepos\xamarin-forms-samples\WebServices\TodoWCF\TodoWCF\Data\SoapService.cs:65 
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
  at System.Runtime.CompilerServices.TaskAwaiter.GetResult () [0x00000] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
  at TodoWCF.TodoItemPage+<OnSaveActivated>d__2.MoveNext () [0x0007e] in C:\GitRepos\xamarin-forms-samples\WebServices\TodoWCF\TodoWCF\Views\TodoItemPage.xaml.cs:22 }

Note: In the standard Xamarin Forms samples repo, this sample runs fine, and FaultExceptions are correctly sent across WCF. The main difference in code between my sample and the Xamarin Forms samples are these:

Xamarin:
    throw new FaultException(string.Format("Error: {0}", ex.Message));

Mine (generic type argument):
    throw new FaultException<FaultExceptionDetail>(new FaultExceptionDetail(), string.Format("Error: {0}", ex.Message));

These lines can be found in TodoService.svc.cs in the WCF service itself.

Note: iOS untested (May have same issue)
Comment 1 Melbourne Developer 2017-09-08 04:45:12 UTC
Also, note that adding FaultContract for the FaultDetail types on both the client and server OperationContracts does not resolve this problem.
Comment 2 Melbourne Developer 2017-09-18 04:08:18 UTC
This bug was logged over a week ago. Is anyone looking in to this?
Comment 3 Jon Douglas [MSFT] 2017-09-18 17:04:50 UTC
Hello Christian, I apologize in advance for how long it took to respond to this bug. I had quite a busy schedule last week that didn't let me get to this until today.

Although I can CONFIRM this behavior based on the reproduction steps in https://bugzilla.xamarin.com/show_bug.cgi?id=59318#c0 I am asking for a couple of confirmation points.

Here is the current behavior I am also seeing:

1. UWP App catches the FaultException.

            catch (FaultException fe)
            {
                await DisplayAlert("Fault Exception", fe.Message, "OK");
            }


2. Android App does not catch the FaultException and rather catches generic Exception.

            catch (Exception ex)
            {
                await DisplayAlert("Exception", ex.Message, "OK");
            }

When using 10.0.2.2 in an emulator instead of localhost

> There was an error on processing web request: Status code 400(BadRequest): Bad Request

When using localhost

> Error: ConnectFailure (Connection refused)

3. iOS App seems to also be similar to Android.

            catch (Exception ex)
            {
                await DisplayAlert("Exception", ex.Message, "OK");
            }

It seems like this might be because of a different reason such as the simulator/emulators not being able to hit the localhost endpoint.

There seems to be a few forum posts related to this issue as well:

https://forums.xamarin.com/discussion/72425/how-to-handle-fault-in-wcf-service-call

https://forums.xamarin.com/discussion/37284/how-to-handle-fault-exception-in-xamarin-android

As for a followup step, have you confirmed that this is the same case with a live endpoint? Ensuring that there is no localhost connection issues given Android Emulators/Devices have their own concept of localhost? Lots of topics on this on Stack Overflow:

https://stackoverflow.com/questions/5528850/how-to-connect-localhost-in-android-emulator

Setting to NEEDINFO for now.
Comment 4 Melbourne Developer 2017-09-20 23:22:01 UTC
Hi. Yes. I can confirm that this is not just a localhost type issue.

I deployed my WCF service to IIS, and I ran the sample on my Android 7.1 device. I was hitting the service over the network by IP address.
Comment 5 Melbourne Developer 2017-09-25 04:28:28 UTC
Any progress on this?

Note You need to log in before you can comment on or make changes to this bug.