Translate

Monday 15 December 2014

Fault Exception and Fault Contract in WCF Services

Handling wcf service exceptions using fault contracts and data contracts.

WCF gives you enough flexibility to handle exceptions and send required detail to clients. By default WCF sends exception details to clients using SOAP FaultContract. The default FaultContract will allow you to set Message, Reason properties and throw it to clients.

We can easily customize the FaultContract with generic version FaultContract<T> which helps you to provide more appropriate and meaningful details to client with custom error messages and also the flexibility to log or take actions on critical errors.
Why we should use the FaultContract rather than using. Net exceptions?
Exceptions has limitations and security risks.
  1. .Net exception can be used by only CLR supported languages so loosing great WCF feature of interoperability.
  2. Throwing exceptions can provide service implementation and private details to clients.
  3. Exceptions are tightly coupled between clients and service.
1. Service Implementation

namespace FaultContractSampleWCF
{
    // NOTE: You can use the "Rename" command on the
    // "Refactor" menu to change the interface name
    // "IService" in both code and config file together.
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        [FaultContract(typeof(ServiceData))]
        ServiceData TestConnection(string strConnectionString);
    }

    // Use a data contract as illustrated in the sample
    // below to add composite types to service operations.
    [DataContract]
    public class ServiceData
    {
        [DataMember]
        public bool Result { get; set; }
        [DataMember]
        public string ErrorMessage { get; set; }
        [DataMember]
        public string ErrorDetails { get; set; }
    }
}

namespace FaultContractSampleWCF
{
    // NOTE: You can use the "Rename" command on the "Refactor"
    // menu to change the class name "Service1" in code, svc and config file together.
    public class Service1 : IService1
    {
        /// <summary>
        /// Implement the TestConnection method.
        /// </summary>
        /// <returns></returns>
        public ServiceData TestConnection(string StrConnectionString)
        {
            ServiceData myServiceData = new ServiceData();
            try
            {
                SqlConnection con = new SqlConnection(StrConnectionString);
                con.Open();
                myServiceData.Result = true;
                con.Close();
                return myServiceData;
            }
            catch (SqlException sqlEx)
            {
                myServiceData.Result = true;
                myServiceData.ErrorMessage = "Connection can not open this " + 
                   "time either connection string is wrong or Sever is down. Try later";
                myServiceData.ErrorDetails = sqlEx.ToString();
                throw new FaultException<ServiceData>(myServiceData, sqlEx.ToString());
            }
            catch (Exception ex)
            {
                myServiceData.Result = false;
                myServiceData.ErrorMessage = "unforeseen error occurred. Please try later.";
                myServiceData.ErrorDetails = ex.ToString();
                throw new FaultException<ServiceData>(myServiceData, ex.ToString());
            }
        }
    }
}

The following endpoint details are automatically added to web.cofig when you create a WCF Service Project.
<services>
  <service name="FaultContractSampleWCF.Service1" 
      behaviorConfiguration="FaultContractSampleWCF.Service1Behavior">
    <!-- Service Endpoints -->
    <endpoint address="" binding="wsHttpBinding" contract="FaultContractSampleWCF.IService1">         
      <identity>
        <dns value="localhost"/>
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
  </service>
</services>


<system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, set the value below to false before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.
  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>

Consuming the Services:

namespace Client_FaultContractSampleWCF
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Service1Client objServiceClient = new Service1Client();
                //Pass the connection string to the TestConnection Method.
                ServiceData objSeviceData = objServiceClient.TestConnection(
                  @"integrated security=true;data source=localhost;initial catalog=master");
                if (objSeviceData.Result == true)
                    Console.WriteLine("Connection Succeeded");
                Console.ReadLine();
            }
            catch (FaultException<ServiceData> Fex)
            {
                Console.WriteLine("ErrorMessage::" + Fex.Detail.ErrorMessage + Environment.NewLine);
                Console.WriteLine("ErrorDetails::" + Environment.NewLine + Fex.Detail.ErrorDetails);
                Console.ReadLine();
            }
        }
    }
}


Difference between “Throw” and “Throw ex”?

“Throw” propagates the full stack information to the caller, while “Throw ex” excludes stack information from the point where you called “Throw ex”.
For instance let’s say you have a “Main” method which calls “Method2” and “Method2” calls “Method1”. Now in “Method2” if you handle exception by using just “Throw”, it will propagate the complete stack error to the main method.
If you add “ex” i.e. if you use “Throw ex” it will propagate stack information only from “Method2”.



Example:

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                MethodA();
            }
            catch (Exception ex)
            {
                //Showing overridden exception stack with MethodA instead of MethodB on top
                Console.WriteLine(ex.ToString());
            }
            Console.ReadLine();
        }

        private static void MethodA()
        {
            try
            {
                MethodB();
            }
            catch (Exception ex)
            {
                //Overrides original stack trace
                throw ex;
            }
        }

        private static void MethodB()
        {
            throw new NotImplementedException();
        }
    }
}


Difference between var and dynamic in C#

Table of difference



var
dynamic
Introduced inC# 3.0
Introduced inC# 4.0
Statically typed– This means the type of variable declared is decided by the compiler at compile time.
Dynamically typed- This means the type of variable declared is decided by the compiler at runtime time.
Needto initialize at the time of declaration.
e.g.,var str=”I am a string”;
Looking at the value assigned to the variablestr, the compiler will treat the variablestras string.
Noneedto initialize at the time of declaration.
e.g.,dynamic str;
str=”I am a string”;//Works fine and compiles
str=2;//Works fine and compiles
Errors are caught at compile time.
Since the compiler knows about the type and the methods and properties of the type at the compile time itself
Errors are caught at runtime
Since the compiler comes to about the type and the methods and properties of the type at the run time.
Visual Studio shows intellisensesince the type of variable assigned is known to compiler.
Intellisense is not availablesince the type and its related methods and properties can be known at run time only


e.g.,var obj1;
willthrow a compile errorsince the variable is not initialized. The compiler needs that this variable should be initialized so that it can infer a type from the value.
e.g.,dynamic obj1;
will compile;
e.g.var obj1=1;
will compile
var obj1=” I am a string”;
will throw errorsince the compiler has already decided that the type of obj1 is System.Int32 when the value 1 was assigned to it. Now assigning a string value to it violates the type safety.
e.g.dynamic obj1=1;
will compile and run
dynamic obj1=” I am a string”;
will compile and runsince the compiler creates the type for obj1 as System.Int32 and then recreates the type as string when the value “I am a string” was assigned to it.
This code will work fine.