Handling Service Side Exception and Faulty Channel at Client Side in WCF


Objective:

In this article, I will show different approach to deal with service side exception and channel fault at client side. I will do a comparison study between various approaches and I will provide best approach also.

Service

Consider the below very simple Contract and Service

IService1

using System;

using System.Collections.Generic;

using System.Linq;

using System.Runtime.Serialization;

using System.ServiceModel;

using System.Text;

namespace FaultSample1

{

  [ServiceContract]

  public interface IService1

  {

 

    [OperationContract]

    string GetData();  

  } 
}

Service1

using System;

using System.Collections.Generic;

using System.Linq;

using System.Runtime.Serialization;

using System.ServiceModel;

using System.Text;

namespace FaultSample1

{

  public class Service1 : IService1

  {

    public string GetData()

    {

      return "Hello WCF";

    }

  }

}

Three facts about Channel Faulting is

  1. If there is transport session, Client cannot even close the Proxy.
  2. If there is no transport session, technically client could continue to using Proxy after a Service exception.
  3. Client could only Abort the proxy in case of exception.

Now at client side,

Approach #1: Simple Approach

using
System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ConsoleApplication1.ServiceReference1;

namespace ConsoleApplication1

{

  class Program

  {

    static void Main(string[] args)

    {

 

      Service1Client Proxy = new Service1Client();

      try

      {

        string result= Proxy.GetData();

        Console.WriteLine(result);

      }

      catch

      {

      }

 

       string resultafterexception =Proxy.GetData();

       Console.WriteLine(resultafterexception);

       Console.ReadKey(true);

    }

  }

}

If there is no transport session, technically client could continue using the Proxy even after Channel is faulted. So in above approach client may continue using faulted channel and that is not good.

Approach #2: Calling Abort

The other thing client could do to prevent using Proxy for a faulted channel is to call Abort.

using
System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ConsoleApplication1.ServiceReference1;

namespace ConsoleApplication1

{

  class Program

  {

    static void Main(string[] args)

    {

 

      Service1Client Proxy = new Service1Client();

      try

      {

       string res= Proxy.GetData();

       Console.WriteLine(res);

      }

      catch

      {

        Proxy.Abort();

      }

 

      Console.ReadKey(true);

    }

  }

}

But problem in above approach is that, Proxy is not getting closed. So there is Service Instance, which has not disposed.

Approach #3: Closing the Proxy with using statement

using
System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ConsoleApplication1.ServiceReference1;

namespace ConsoleApplication1

{

  class Program

  {

    static void Main(string[] args)

    {

     using (Service1Client Proxy = new Service1Client())

      {

 

        try

        {

          string res= Proxy.GetData();

          Console.WriteLine(res);

        }

        catch

        {

          Proxy.Abort();

        }

      }

 

      Console.ReadKey(true);

    }

  }

}

Problem with relying in using statement to close the proxy is that, if any server side exception is causing channel to get faulted and after that when using statement will try to dispose the proxy, when the channel is faulted will cause CommunicationObjectFaultedException. Code after using statement will never get called.

Approach #4: using statement in try/catch

using
System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ConsoleApplication1.ServiceReference1;

namespace ConsoleApplication1

{

  class Program

  {

    static void Main(string[] args)

    {

 

     

      try

      {

 

        using (Service1Client Proxy = new Service1Client())

        {

 

          try

          {

            string res = Proxy.GetData();

            Console.WriteLine(res);

          }

          catch

          {

            Proxy.Abort();

          }

        }

      }

      catch

      {

 

      }

      Console.ReadKey(true);

    }

  }

}

Readability of this code is not so good. It is very tough to understand many nested try/catch.

Best Approach

using
System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ConsoleApplication1.ServiceReference1;

namespace ConsoleApplication1

{

  class Program

  {

    static void Main(string[] args)

    {

 

      Service1Client Proxy=null;

      try

      {

        Proxy = new Service1Client();

        string res = Proxy.GetData();

        Console.WriteLine(res);

        Proxy.Close();

 

      }

      catch

      {

        Proxy.Abort();

      }

      Console.ReadKey(true);

    }

  }

}

Above approach is closing the Proxy. If channel is faulted then aborting the Proxy. Above code is highly readable also.

Conclusion:
 
In this article, we saw various ways of dealing with Service side Exception and Channel Fault at client side. You could download the attached code for reference. Thanks for reading.

Happy Coding!

Up Next
    Ebook Download
    View all
    Learn
    View all