Con risposta FaultException in ForkJoins

  • Tuesday, March 19, 2013 11:53 PM
     
      Has Code

    Hi,

    I am using SL5 (MVVM)+ Rx + WCF (non-RIA) in my project.

    In my WCF services, under certain circumstances, I am raising a (custom) FaultException which would be handled by my Silverlight Code. So my WCF method has something like below:

    public FlagAlertDto GetFlagAlertById(int alertId, string condition)
    {
        ....
        if (!IsSomeCondition(condition)) throw new FaultException<InvalidConditionFault>(new InvalidConditionFault("Invalid Condition"));
        ....
    }

    The Contract has the following:

    [OperationContract]
    
            [FaultContractAttribute(typeof(InvalidConditionFault), Action = "http://www.blahblah.com/InvalidConditionFault", ProtectionLevel = ProtectionLevel.None)]
     
            BookmarkDto GetBookmarkById(int? bookmarkId, string condition);

    Now the following works correctly, catching and identifying the exception correctly:

    try { var client = _serviceClientFactory.GetContactServiceClient(); IObservable<IEvent<GetIndividualsCompletedEventArgs>> observable =Observable.FromEvent<GetIndividualsCompletedEventArgs>(client, "GetIndividualsCompleted").Take(1); observable.Subscribe( e => { if (e.EventArgs.Error == null) { callbackAction(e.EventArgs.Result); } else { callbackAction(new ExceptionNotifier()); _errorLogger.ProcessError(GetType().Name, MethodBase.GetCurrentMethod().Name, ErrorSource.WCF, "", -1, e.EventArgs.Error); //FaultException is thrown here } }, ex => { callbackAction(new ExceptionNotifier()); _errorLogger.ProcessError(GetType().Name, MethodBase.GetCurrentMethod().Name, ErrorSource.Observable, "", -1, ex); } );

    client.GetIndividualsAsync(UserInformation.SecurityToken); } catch (Exception ex) { callbackAction(new ExceptionNotifier()); _errorLogger.ProcessError(GetType().Name, MethodBase.GetCurrentMethod().Name, ErrorSource.Code, "", -1, ex); }

    The exceptiont that I am receiving (correctly) is:

    System.ServiceModel.FaultException`1[MyProject.UI.BlahServiceReference.InvalidConditionFault]

    However, the following does not work: 

    try
    {
        var clientBookmark = _serviceClientFactory.GetUserServiceClient(); 
        var clientNotification = _serviceClientFactory.GetUserServiceClient();
        var clientUserSummaries = _serviceClientFactory.GetUserServiceClient();
    
        var allBookmarkCall = Observable.FromEvent<GetBookmarksByUserIdCompletedEventArgs>( 
            h => clientBookmark.GetBookmarksByUserIdCompleted += h,
            h => clientBookmark.GetBookmarksByUserIdCompleted -= h).Select(e => e.EventArgs).Take(1); 
    
        var allNotificationCall = Observable.FromEvent<GetNotificationsByUserIdCompletedEventArgs>(
            h => clientNotification.GetNotificationsByUserIdCompleted += h, 
            h => clientNotification.GetNotificationsByUserIdCompleted -= h).Select(e => e.EventArgs).Take(1);
    
        var allUserSummaries = Observable.FromEvent<GetUserSummariesCompletedEventArgs>( 
            h => clientUserSummaries.GetUserSummariesCompleted += h,
            h => clientUserSummaries.GetUserSummariesCompleted -= h).Select(e => e.EventArgs).Take(1);
    
        Observable.ForkJoin<Object>(allBookmarkCall, allNotificationCall, allUserSummaries).Subscribe(
            data =>
            {
            var d0 = (GetBookmarksByUserIdCompletedEventArgs)data[0];
            var d1 = (GetNotificationsByUserIdCompletedEventArgs)data[1]; 
            var d2 = (GetUserSummariesCompletedEventArgs)data[2];                                               
    
            if (d0.Error != null) 
            {
                callbackAction(new ExceptionNotifier(), null, null);
                _errorLogger.ProcessError(GetType().Name, MethodBase.GetCurrentMethod().Name, ErrorSource.WCF, "", -1, d0.Error); //Wrong exception is caught here
                return;
            }
    
            else if (d1.Error != null) 
            {
                callbackAction(null, new ExceptionNotifier(), null);
                _errorLogger.ProcessError(GetType().Name, MethodBase.GetCurrentMethod().Name, ErrorSource.WCF, "", -1, d1.Error); 
                return;
            }
    
            else if (d2.Error != null) 
            {
                callbackAction(null, null, new ExceptionNotifier());
                _errorLogger.ProcessError(GetType().Name, MethodBase.GetCurrentMethod().Name, ErrorSource.WCF, "", -1, d2.Error); 
                return;
            }
    
            callbackAction(d0.Result, d1.Result, d2.Result);
        },
            ex =>
            { 
                callbackAction(new ExceptionNotifier(), new ExceptionNotifier(), new ExceptionNotifier());
                _errorLogger.ProcessError(GetType().Name, MethodBase.GetCurrentMethod().Name, ErrorSource.Observable, "", -1, ex); 
            }
            );
    
        clientBookmark.GetBookmarksByUserIdAsync(UserInformation.UserID, UserInformation.SecurityToken); 
        clientNotification.GetNotificationsByUserIdAsync(UserInformation.UserID, UserInformation.SecurityToken);
        clientUserSummaries.GetUserSummariesAsync(UserInformation.SecurityToken); 
    }
    catch (Exception ex)
    {
        callbackAction(new ExceptionNotifier(), new ExceptionNotifier(), new ExceptionNotifier());
        _errorLogger.ProcessError(GetType().Name, MethodBase.GetCurrentMethod().Name, ErrorSource.Code, "", -1, ex); 
    }

    In the above code, a different exception (as mention below) is caught.

    System.ServiceModel.CommunicationException: The remote server returned an error: NotFound. --->

    However, I want my custom FaultException there. Why am I getting a CommunicationException there?

    I have tripple checked that all my functions on WCF side have exactly the same format and do actually throw an FaultExcetion. Besides, all the methods check the same given condition and throws the same custom FaultException. However, in forkjoins what I receive is an CommunicationException. It works fine in nomal Rx calls (as in sample 1 above).

    Thanks in advance,


    Dharmesh

All Replies

  • Wednesday, March 20, 2013 12:49 PM
     
     Answered

    Hi Dharmesh,

    You've shown 4 code examples with several service methods and yet every one of the service methods is different!  Are you absolutely sure that you've tried calling the problematic service method alone to verify that the exception is actually of the type that you expect?

    I'm sure that Rx has nothing to do with your problem.  Rx doesn't know anything about WCF.  Rx certainly doesn't reassign the type of exception in the Error property to a different exception type.  Nor does WCF know anything about Rx.  WCF certainly doesn't change the type of exception assigned to the Error property dependent on whether the service method is invoked directly or within an Rx query.

    I suspect that it's a simple case of misconfiguration.  My recommendation is to create a new project and test the service in question without using Rx.  You should see the same incorrect exception type.  In that case, your question is more suitable in the WCF forum.

    Otherwise, if you do see a different exception type, then please post a short but complete example that reproduces the problem.

    - Dave


    http://davesexton.com/blog

    • Proposed As Answer by LeeCampbell Wednesday, March 20, 2013 4:59 PM
    • Marked As Answer by Dharmesh1 Thursday, March 21, 2013 9:02 PM
    •  
  • Wednesday, March 20, 2013 10:58 PM
     
     

    Hi Dave,

    Thanks for your reply. Regrets for posting different code examples. They are actually part of the same project and are focused around bits that are working vs bits that are not working. I would rather edit my post, or build a smaller sample project for a better idea.

    I posted this question (in Rx forum rather than WCF one) because I was not too sure of how I am using ForkJoin in my code. Though it gives the desired output, the FaultException handling issue made me rethink of it. The sad part is the same WCF service(/s) if used without ForkJoin work fine, but with it throws a communication exception (though I know it's outside the scope of Rx mechanism).

    Once again, if you think my usage (of ForkJoin in specific and Rx in general) is proper, I would post my question in WCF forum.

    Thanks,


    Dharmesh

  • Thursday, March 21, 2013 3:08 PM
     
     

    Hi Dharmesh,

    > I would rather edit my post, or build a smaller sample project for a better idea.

    It's best not to edit posts when providing new information that requires attention.  The forum doesn't notify subscribers about edits.

    Building a small project that can reproduce the problem is always helpful.  Often, it's all that is needed for the poster to solve the problem themselves.  And if not, then at least it provides us with a quick and simple way to repro the issue, without having to make any assumptions.

    > Once again, if you think my usage (of ForkJoin in specific and Rx in general) is proper, I would post my question in WCF forum.

    Your usage of ForkJoin seems fine.  Though you could probably use Zip instead, as of Rx 2.0.  That way you won't need to take a dependency on the Rx experimental library.

    As for the unexpected exception, I still recommend writing a short but complete example that reproduces the problem.  Make sure that you:

    1. define only one service method.
    2. invoke that service without Rx, inside of a Silverlight application.
    3. invoke that service with ForkJoin, inside of a Silverlight application.

    You should not see any difference in the type of exception.  If you do, then please post your complete sample code here.

    - Dave


    http://davesexton.com/blog

    • Edited by Dave Sexton Thursday, March 21, 2013 3:10 PM clarified step #1
    •