Returning exception information to a Silverlight client through WCF

Error handling code can be a drag but the simple fact is that everyone needs to write it because runtime errors can and do occur. Developing a Silverlight app is no different here, exceptions will occur and you as a developer will need to deal with them.

One of the common things in Silverlight is communicate with a server through WCF and as soon as we start executing code on the server that is just another place where errors can occur. No big deal you might think as that is the same with any other application using WCF. Well the fact that it will also happen in other applications is certainly true but unfortunately the way Silverlight communicates with a WCF service makes live a bit more difficult.

 

But wait, WCF supports a FaultContract so we can just return exceptions as faults right?

Wrong [:(]

Unfortunately the Silverlight WCF stack doesn’t support a service contract with a fault contact and just adding the FaultContract attribute will make the service unusable for Silverlight clients. Even when no faults are returned [:(]

So the standard WCF faults are out, what else?

Well can’t we just throw an exception and have that resurface in the Silverlight client? Unfortunately we can’t.  Even though the server WCF stack returns the exception just fine, see the Fiddler output, the browser will not pass the information on to the client and inside of Silverlight all we see is a CommunicationException with the very helpful message “The remote server retuned an error: NotFound”. Less than useful [:(]

image

So this code will not work

[OperationContract]
public IList<Customer> GetCustomersWithException()
{
    IList<Customer> result = GetCustomers();
 
    throw new FaultException<ArgumentException>(
        new ArgumentException("This is my error text."));
 
    return result;
}


 



So is there no solution?



Well there are a few examples out there that tag an Error property onto the data returned. Guess that works but I kind of don’t like it for a few reasons:



  1. It means you cannot have a simple return value, it must always be a more complicated custom type.
  2. You are mixing good and bad data into the same object and presumably only a single set will be filled.
  3. It therefore breaks the single responsibility rule.


 



So a better solution would be to return two items instead of one.



Turns out we can use out parameters with WCF and they will be wrapped just fine into the return message. So we can return the error information using an out parameter. Great, feels like a much better design [:)]



So my first thought was to send the exception as the out parameter and the Silverlight client would get all error information that way. Turns out that didn’t work all that well. Even though the error was passed to the client the message shown in the client was always the default message and not the one actually send. And a second problem was that the parameter type had to mach the exact exception passed. using the KnownType attribute didn’t help there.



So instead of sending the original exception I decided to create a small wrapper type, MyFaultContract, that would pass the exception type and message to the Silverlight client. This info should be more than enough in most cases.



The service operation now looks like this.



[OperationContract]
public IList<Customer> GetCustomersWithCustomError(out MyFaultContract myFault)
{
    IList<Customer> result = null;
    myFault = null;
 
    try
    {
        result = GetCustomersWithException();
    }
    catch (FaultException<ArgumentException> ex)
    {
        myFault = new MyFaultContract()
        {
            FaultType = ex.Detail.GetType().FullName,
            Message = ex.Detail.Message
        };
    }
 
    return result;
}


With the following custom MyFaultContract



[DataContract]
public class MyFaultContract
{
    [DataMember]
    public string FaultType { get; set; }
    [DataMember]
    public string Message { get; set; }
}


 



So what does our client code look like with this extra fault contract?



private void Button_Click_2(object sender, RoutedEventArgs e)
{
    Service1Client proxy = GetService1Client();
 
    proxy.GetCustomersWithCustomErrorCompleted += (s, arg) =>
    {
        if (arg.Error != null)
            ErrorText.Text = arg.Error.GetType().FullName + 
                "\n" + arg.Error.Message;
 
        else if (arg.myFault != null)
            ErrorText.Text = arg.myFault.FaultType + 
                "\n" + arg.myFault.Message;
 
        else
            DataContext = arg.Result[0];
    };
    proxy.GetCustomersWithCustomErrorAsync();
}


Not bad. It does take an extra check as we have to check both the Error and myFault properties for errors but other than that it is exactly the same.



 



So not a perfect solution but it works well enough for most purposes!





Enjoy!

28 thoughts on “Returning exception information to a Silverlight client through WCF

  1. it’s so bad that I’m also facing the same probelm.. but I don’t think that we can change our WCF code like that. It’s kinda extra effort to modify each and every WCF methods

  2. Ouch… I’m pretty sure I’m running into this same problem. Thanks for the explanation. Kinda hard to take it all in though but gives me something to thing about.

  3. Very creative solution – I like it. The lack of support for custom FaultContracts between WCF and SL is a real pity, and something I hope they consider with the next release.

  4. Thank you for this article. Saved me a lot of time.

    In case anyone needs to do this in VB,

    To create an output parameter in VB.Net, add the
    attribute before the parameter definition:

    _
    Public Function MyMethod( _
    ByVal param1 As Short, _
    ByRef fault As ApplicationFault) As ReturnType

  5. We are also using out but instead we are returning enum type and each flag has its own definition defined under resource file. Silverlight apps gets the flag as per flag as a key.

  6. I forced a SqlException, removing some parameters from my stored procedure.

    I used your suggestion in my solution, but every time I have an error in my service, he ever pass in the first “if” (if (arg.Error !=null)) in my event “Completed” in client layer. And debugging the method of the service generated in my client, I saw that the out parameter doesn’t receive any value, because the error occurs before.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>