WCF Fault Contract

18:59

Introduction

Any Service that we develop might get some error. Basically we can not see what wents wrong actually in our and where cause the error. We handle this problem using Fault Contract.

Why Fault Contract

By default if thrown any exception from service, it will not reach the client side. WCF handle error message and send to client from service using SOAP Fault contract.
For example, suppose we create a service and it is not working in the client application. I want to know the real cause of the problem. How I can know the error? For this we are having Fault Contract.
Let us try to understand the concept using sample example.

Create Simple Test Application

We create a simple calculator service i.e. Add(), Subtract(), Multiply(), Divide()
Go to Visual studio > File > New > Project > Templates > WCF > WCF Service Application > Provide a name (Ex: "WCF_Fault_Contract") of project > Ok
Now replace "IService1.cs" code by the below code.
Here we decorate the service operation with the FaultContract attribute and specify the type name.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace WCF_Fault_Contract
{
    [ServiceContract]
    public interface ICalculator
    {
        [OperationContract]
        int Add(int n1, int n2);

        [OperationContract]
        int Subtract(int n1, int n2);

        [OperationContract]
        int Multiply(int n1, int n2);

        [OperationContract]
        [FaultContract(typeof(MathFault))]
        int Divide(int n1, int n2);
    }

    [DataContract]
    public class MathFault
    {
        [DataMember]
        public string Operation { get; set; }

        [DataMember]
        public string ProblemType { get; set; }
    }
}
Service1.svc
After that replace "Service1.svc.cs" code by the below code.
Here we throw a FaultException if getting any error, when we try to divide two variables.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace WCF_Fault_Contract
{
    public class Calculator : ICalculator
    {
        public int Add(int n1, int n2)
        {
            return n1 + n2;
        }

        public int Subtract(int n1, int n2)
        {
            return n1 - n2;
        }

        public int Multiply(int n1, int n2)
        {
            return n1 * n2;
        }

        public int Divide(int n1, int n2)
        {
            try
            {
                return n1 / n2;
            }
            catch (Exception ex)
            {
                MathFault mf = new MathFault();
                mf.Operation = "Division";
                mf.ProblemType = "Sorry, divide by zero is not possible!";
                throw new FaultException<MathFault>(mf, ex.ToString());
            }
        }
    }
}
Now we create the service endpoint in the web.config file like below:
<?xml version="1.0"?>
<configuration>

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5"/>
  </system.web>
  <system.serviceModel>
    <services>
      <service name="WCF_Fault_Contract.Calculator" behaviorConfiguration="WCF_Fault">
        <!-- Service Endpoints -->
        <endpoint address="" binding="wsHttpBinding" contract="WCF_Fault_Contract.ICalculator">
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="WCF_Fault">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
        <add binding="basicHttpsBinding" scheme="https" />
    </protocolMapping>    
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <!--
        To browse web app root directory during debugging, set the value below to true.
        Set to false before deployment to avoid disclosing web app folder information.
      -->
    <directoryBrowse enabled="true"/>
  </system.webServer>

</configuration>
Now we need to add a client application by right click on the project solutions. Follow the below steps:


Now select the console application like following image:


After that we need to add service reference. Right click on Reference and select Add reference..


Click on the Discover button and we see that the address is show in the textbox. Click Ok.


Now replace the Program.cs file by following:
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ServiceModel;
using WCF_Fault_Contract;

namespace WCFFaultContractUsing
{
    class Program
    {
        public static ServiceReference1.CalculatorClient obj = new ServiceReference1.CalculatorClient();
        static void Main(string[] args)
        {
            try
            {
                int result = 0;

                result = obj.Add(1, 0);
                Console.WriteLine("Add Result:" + result);
                Console.WriteLine("---------------------------------------------");

                result = obj.Subtract(1, 0);
                Console.WriteLine("Subtract Result:" + result);
                Console.WriteLine("---------------------------------------------");

                result = obj.Multiply(1, 0);
                Console.WriteLine("Multiply Result:" + result);
                Console.WriteLine("---------------------------------------------");

                result = obj.Divide(1, 0);
                Console.WriteLine("Divide Result:" + result);
                Console.WriteLine("---------------------------------------------");

                Console.ReadLine();
            }
            catch (FaultException<MathFault> Fex)
            {
                Console.WriteLine("ErrorType:" + Fex.Detail.Operation + Environment.NewLine);
                Console.WriteLine("ErrorMessage:" + Environment.NewLine + Fex.Detail.ProblemType);
                Console.ReadLine();
            }
        }
    }
}
Add the endpoint in the App.config file like below:
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
    <system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_ICalculator" />
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:49628/Service1.svc" binding="wsHttpBinding"
                bindingConfiguration="WSHttpBinding_ICalculator" contract="ServiceReference1.ICalculator"
                name="WSHttpBinding_ICalculator">
                <identity>
                    <dns value="localhost" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>
Run the application. See below image:

Download

You can download application zip file here - 84.6 KB

Conclusion

Guys I try to explain how to create a fault contract. I think it will very helpfull.

You Might Also Like

0 comments