Silverlight 3 and WCF Faults

Posted by: Glavs Blog, on 14 Jul 2009 | View original | Bookmarked: 0 time(s)

On  a previous project that utilised WCF and Silverlight 2, I began implementing an error handling strategy that was going to rely on certain FaultExceptions being propagated to the Silverlight client. Well it turned out that Silverlight 2 does not support FaultExceptions so that was not going to fly and a custom solution was built.

Well Silverlight 3 does change this to some degree. Silverlight 3 now supports to the notion of Fault Contracts and FaultExceptions. In your Silverlight client code, if I have a WCF service called ThrowExceptionMethod (which as you may have guessed throws a FaultException) you can do something like this:

First wire up the service call:

private void Button_Click_1(object sender, RoutedEventArgs e)
{
    TestRef.TestServiceClient client = new TestSilverlightApplication3.TestRef.TestServiceClient();
    client.ThrowExceptionMethodCompleted += new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(client_ThrowExceptionMethodCompleted);
    client.ThrowExceptionMethodAsync();
}

Then handle any error situation in the completed event:

void client_ThrowExceptionMethodCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
    if (e.Error == null)
        MessageBox.Show("Call sucessfull");
    else
    {
        string msg;
        FaultException<ExceptionDetail> fex = e.Error as FaultException<ExceptionDetail>;
        if (fex != null)
            msg = string.Format("Fault Exception recevied. Reason: {0}, Message: {1}", fex.Reason, e.Error.Message);
        else
            msg = string.Format("Error recevied of type: {0}, Message: {1}",e.Error.GetType(),e.Error.Message);
        MessageBox.Show(msg);
    }
}

Here you can see that we test the e.Error property to see if its an exception of type FaultException, otherwise the error will flow through generally as a CommunicationException as per normal WCF behaviour.

That all sounds easy, however you still need to tell the WCF service (or more specifically WCF itself) to return the fault using a HTTP status code of 200 (OK) instead of a HTTP status code of 500 (server error) which is the default. If you dont do this, then the error will always come through as a CommunicationException .

You need a little bit of code and configuration for this. First you need to define a custom behaviour like so:

public class SilverlightFaultBehavior : BehaviorExtensionElement, IEndpointBehavior
    {        
        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
            SilverlightFaultMessageInspector inspector = new SilverlightFaultMessageInspector();
            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
        }

        public class SilverlightFaultMessageInspector : IDispatchMessageInspector
        {
            public void BeforeSendReply(ref Message reply, object correlationState)
            {
                if (reply.IsFault)
                {
                    HttpResponseMessageProperty property = new HttpResponseMessageProperty();

                    // Here the response code is changed to 200.
                    property.StatusCode = System.Net.HttpStatusCode.OK;
                    reply.Properties[HttpResponseMessageProperty.Name] = property;
                }
            }
            
            public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
            {
                // Do nothing to the incoming message.
                return null;
            }
        }

        // The following methods are stubs and not relevant. 
        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
        }
        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
        }
        public void Validate(ServiceEndpoint endpoint)
        {
        }
        public override System.Type BehaviorType
        {
            get { return typeof(SilverlightFaultBehavior); }
        }
        protected override object CreateBehavior()
        {
            return new SilverlightFaultBehavior();
        }
    }

Then some config:

<system.serviceModel>
    <extensions>
      <behaviorExtensions>
        <add name=silverlightFaults 
             type=Microsoft.Silverlight.Samples.SilverlightFaultBehavior, 
             SilverlightFaultBehavior, 
             Version=1.0.0.0, 
             Culture=neutral, 
             PublicKeyToken=null/>
      </behaviorExtensions>
    </extensions>
    <behaviors>
        <endpointBehaviors>
          <behavior name=SilverlightFaultBehavior>
            <silverlightFaults/>
          </behavior>
        </endpointBehaviors>
    </behaviors>
    <services>
        <service name=Calculator.Web.Service>
            <endpoint address= 
                      binding=basicHttpBinding 
                      contract=Calculator.Web.Service 
                      behaviorConfiguration=SilverlightFaultBehavior />
</service>
  </services>
</system.serviceModel> 

So, its still not quite there yet, but its better. It would be nice if this status code behaviour were part of the default Silverlight service template and that it was a provided behaviour, rather than a roll your own custom one.

Note: The custom behaviour, as well as more information on this subject, can and was taken from this article here.

Advertisement
Free Agile Project Management Tool from Telerik
TeamPulse Community Edition helps your team effectively capture requirements, manage project plans, assign and track work, and most importantly, be continually connected with each other.
Category: Silverlight | Other Posts: View all posts by this blogger | Report as irrelevant | View bloggers stats | Views: 2076 | Hits: 19

Similar Posts

  • Using WCF with SQL Azure and Telerik OpenAccess more
  • Silverlight MVP more
  • Mixing Silverlight and MS ASP.NET AJAX 3.5 in the same web application. more
  • Building a Silverlight 3 based RIA Image Magagement System (1) more
  • Building a Silverlight 3 based RIA Image Management System - 1 more
  • Telerik Launches RadControls for Silverlight 3 for Line-of-Business Application Development more
  • Provide startup parameters to Silverlight with InitParams more
  • Binary Encoding and Handling Faults in Silverlight 3 more
  • Business Apps Example for Silverlight 3 RTM and .NET RIA Services July Update Summary more
  • Silverlight Twitter Client with authentication more

News Categories

.NET | Agile | Ajax | Architecture | ASP.NET | BizTalk | C# | Certification | Data | DataGrid | DataSet | Debugger | DotNetNuke | Events | GridView | IIS | Indigo | JavaScript | Mobile | Mono | Patterns and Practices | Performance | Podcast | Refactor | Regex | Security | Sharepoint | Silverlight | Smart Client Applications | Software | SQL | VB.NET | Visual Studio | W3 | WCF | WinFx | WPF | WSE | XAML | XLinq | XML | XSD