CSLA .NET

Vibrant discussion about CSLA .NET and using the framework to build great business applications.

Forum has moved

New location: CSLA .NET forum


CSLA .NET Resources:
  • CSLA .NET forum
  • CSLA .NET home page
  • CSLA Light: Question regarding exception handling in DataPortalClient.WcfProxy

    rated by 0 users
    This post has 0 Replies | 0 Followers

    Top 150 Contributor
    Posts 58
    paupdb Posted: Thu, Sep 11 2008 2:41 AM
    This is a question for the Magenic guys primarily.

    I ran into an interesting issue today while debugging a problem in one of my callback methods.

    Basically my callback method was halfway through exception following a successful dataportal fetch and was then throwing up an unhandled exception.
    Now I expected this exception to bubble all the way up to a "critical error" handler I had implemented on the Silverlight App class (i.e. the UnhandledException event on the App was attached to Application_UnhandledException in my App.xaml.cs).

    Problem was that instead of the exception percolating up, I found that my callback method was being called again.
    This was kind of weird but it became clear why this was happening when I stepped through line by line into the WcfProxy to the code below:

        private void proxy_FetchCompleted(object sender, Csla.WcfPortal.FetchCompletedEventArgs e)
        {
          try
          {
            if (e.Error == null && e.Result.ErrorData == null)
            {
              var buffer = new System.IO.MemoryStream(e.Result.ObjectData);
              var formatter = new MobileFormatter();
              T obj = (T)formatter.Deserialize(buffer);
              _globalContext = (ContextDictionary)MobileFormatter.Deserialize(e.Result.GlobalContext);
              OnFetchCompleted(new DataPortalResult<T>(obj, null, e.UserState));
            }
            else if (e.Error != null)
            {
              var ex = new DataPortalException(e.Error.ToErrorInfo());
              OnFetchCompleted(new DataPortalResult<T>(default(T), ex, e.UserState));
            }
            else if (e.Result.ErrorData != null)
            {
              var ex = new DataPortalException(e.Result.ErrorData);
              OnFetchCompleted(new DataPortalResult<T>(default(T), ex, e.UserState));
            }
            else
              throw new InvalidOperationException("Server must return an object or an error");
          }
          catch (Exception ex)
          {
            OnFetchCompleted(new DataPortalResult<T>(default(T), ex, e.UserState));
          }
        }


    My issue with the above is that the exception handler will be hit, even if the exception comes from within the OnFetchCompleted method (i.e. from within my callback).  So the exceptions never percolate past the WcfProxy up to the Application_UnhandledException in the Silverlight App.
    Then to compound my issue, the exception handler then proceeds to invoke the callback again, this time with a blank result, which really isn't great if the exception occurred inside the callback in the first place.

    Now I know what I could do is implement try catch blocks within all my callbacks, and I'm OK with that if this is the desired pattern you guys want CSLA to enforce. 
    But obviously this is extra work I didn't necessarily want to be doing, plus having catchall try blocks in each callback doesn't look very nice to me.

    I'd like to suggest modifying the above WcfProxy code, moving the exception handler to only trap issues encountered with the code prior to invoking the callback method.
    So something like this:

    private void proxy_FetchCompleted(object sender, Csla.WcfPortal.FetchCompletedEventArgs e)
        {
          if (e.Error == null && e.Result.ErrorData == null)
          {
            try {
              var buffer = new System.IO.MemoryStream(e.Result.ObjectData);
              var formatter = new MobileFormatter();
              T obj = (T)formatter.Deserialize(buffer);
              _globalContext = (ContextDictionary)MobileFormatter.Deserialize(e.Result.GlobalContext);
            }
            catch (Exception ex)
            {
              OnFetchCompleted(new DataPortalResult<T>(default(T), ex, e.UserState));
            }

            OnFetchCompleted(new DataPortalResult<T>(obj, null, e.UserState));
          }
          else if (e.Error != null)
          {
            var ex = new DataPortalException(e.Error.ToErrorInfo());
            OnFetchCompleted(new DataPortalResult<T>(default(T), ex, e.UserState));
          }
          else if (e.Result.ErrorData != null)
          {
            var ex = new DataPortalException(e.Result.ErrorData);
            OnFetchCompleted(new DataPortalResult<T>(default(T), ex, e.UserState));
          }
          else
            throw new InvalidOperationException("Server must return an object or an error");
        }
      }

    This way the exceptions continue up the stack, and there isnt a risk of a callback being invoked twice.

    Thanks

    Paul
    Page 1 of 1 (1 items) | RSS

    Copyright (c) 2006-2014 Marimer LLC. All rights reserved.
    Email admin@lhotka.net for support.
    Powered by Community Server (Non-Commercial Edition), by Telligent Systems