<

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x

Propagating Fault Exception to Silverlight Client

Published on
10,678 Points
4,678 Views
Last Modified:
Approved
While working on Silverlight and WCF application, I faced one issue where fault exception occurred at WCF operation contract is not getting propagated to Silverlight client. So after searching net I came to know that it was behavior by default for silverlight client. And these issues can be addressed by little tweak. So, here I am writing on how to propagate fault exception from service to silverlight client.

Reason for this kind of behavior is if any fault exception is raised at operation contract, then the exception is converted to SOAP faults and returned to the client. Since the networking in Silverlight is performed based on browser's HTTP stack. But this limitation is applicable to Silverlight 2. In Silverlight 3, the networking is performed using browser HTTP stack by default. But the new client HTTP stack allows you to bypass the browser and perform networking operation through operating system.

In Silverlight 2, SOAP faults cannot be propagated to client side because due to limitations in silverlight, it cannot access some of the messages in the browser HTTP stack bodies. So HTTP error code 500 which holds the SOAP faults is converted to 404(Page not found), and same is returned to client. So obviously client will be receiving "Remote Server not found"  exception.

In Silverlight 3, this limitation is solved. Since Silverlight 3 uses client HTTP stack, it is simple that networking is performed by API's exposed by operating system itself. So you can tell Silverlight to use the client HTTP stack for requests made, instead of using browser HTTP stack. Below is the code use to inform the silverlight to use client http stack for requests call made for sites begin with http://.
HttpWebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);

Open in new window


Adding the above line code will make all subsequent call starts with http:// to client HTTP stack.

To support for specific site then add the below code
HttpWebRequest.RegisterPrefix("http://xxxx.com", WebRequestCreator.ClientHttp);

Open in new window



Ok, here another question kicked off my mind. What if my Silverlight client is creating web request to WCF service via proxies created at my client side and Silverlight is intended to receive SOAP faults regardless of the address. So do I need to extend my WCF behaviors, so that WCF service will be intelligent enough to convert the http error codes before sending back to client? The answer is YES. Here I will explain on how to achieve this.

My Service Contract and Operation Contract is defined as shown below

 [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        [FaultContract(typeof(ValidationException))]
        string getData();
    }

Open in new window


Data contract class which define data member with some validation rules. StringLength validator is available in System.ComponentModel.DataAnnotations.

 [DataContract]
    public class MyDataContract
    {
        [DataMember]
        [StringLength(10, ErrorMessage="String length should not be greater than 10")]
        public string Name { get; set; }
    }

Open in new window


Contracts implemented in Service class

public class Service1 : IService1
    {
        
        public string getData()
        {
            MyDataContract dc = new MyDataContract();
            dc.Name = "12345678901"; // string length greater than 10
            return dc.Name;
        }
    }

Open in new window


here getData() method throws FaultException of type ValidationException, which inturn converted to SOAP fault. So in order to propagate the SOAP fault to silverlight client we need to extend the endpoint behavior so that SOAP faults can be sent to silverlight client. Below are the steps:

1.) Create a class which is inherited from System.ServiceModel.Configuration.BehaviorExtensionElement and also implemets System.ServiceModel.Description.IEndpointBehavior.

 public class SilverlightFaultContractBehavior : BehaviorExtensionElement, IEndpointBehavior

    {
        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
            SilverlightFaultMessageInspector faultnspector = new SilverlightFaultMessageInspector();
            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(faultnspector);
        }

        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)
            {
                // Dont do anything to incoming request. 
                return null;
            }


        }

        // The following methods are not relevant. So doing dummy implementation of  IEndpointBehavior interface

        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(SilverlightFaultContractBehavior); }
        }

        protected override object CreateBehavior()
        {
            return new SilverlightFaultContractBehavior();
        }

    }

Open in new window


2.) Do the appropriate changes to web.config file.

<system.serviceModel>
      <extensions>
        <behaviorExtensions>
          <add name="silverlightFaults"
               type="SilverlightApplication1.Lib.SilverlightFaultContractBehavior, 
             SilverlightFaultContractBehavior, 
             Version=1.0.0.0, 
             Culture=neutral, 
             PublicKeyToken=null"/>
        </behaviorExtensions>
      </extensions>

      <behaviors>
        <endpointBehaviors>
          <behavior name="SilverlightFaultBehavior">
            <silverlightFaults/>
          </behavior>
        </endpointBehaviors>

        <serviceBehaviors>
                <behavior name="">
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="false" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
     
      <services>
        <service name="SilverlightApplication1.Web.Service1">
          <endpoint address=""
                    binding="basicHttpBinding"
                    contract="SilverlightApplication1.Web.IService1"
                    behaviorConfiguration="SilverlightFaultBehavior" />
        </service>
      </services>

      <serviceHostingEnvironment aspNetCompatibilityEnabled="True" multipleSiteBindingsEnabled="true" />
    </system.serviceModel>

Open in new window


3.) Client code:
 SilverlightApplication1.ServiceReference1.Service1Client client = new SilverlightApplication1.ServiceReference1.Service1Client();
            client.getDataCompleted += new EventHandler<getDataCompletedEventArgs>(client_getDataCompleted);
            client.getDataAsync();

 void client_getDataCompleted(object sender, getDataCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                if (e.Error is FaultException)
                {
                    MessageBox.Show(e.Error.Message);
                }
            }
        }

Open in new window


This is how you can propagate Fault Exceptions to Silverlight Client.

Any feedback and suggestions is highly recommended!!!!!!!!

Thanks......
0
Author:Sathish DV
0 Comments

Featured Post

Build an E-Commerce Site with Angular 5

Learn how to build an E-Commerce site with Angular 5, a JavaScript framework used by developers to build web, desktop, and mobile applications.

Make it easier to see the current record on your Microsoft Access forms! To highlight the current record with a yellow background color, use Conditional Formatting, a control to keep track of the primary key value, a control to change color, and a l…
I previously published an Experts Exchange video Micro Tutorial that describes how to scan documents to a PDF file using an excellent, free product called Foxit Reader: How to scan to a PDF file with free software (https://www.experts-exchange.co…
Other articles by this author

Keep in touch with Experts Exchange

Tech news and trends delivered to your inbox every month