WCF MessageContract, ServiceContract, OperationContract, and DataContracts

Learn how to use the ServiceContract, MessageContract, OperationContract, and DataContract

Contract

Contract defines the operations of the WCF service. These operations are collection of service functionalities, data members, messages and faults (errors). There are following types of WCF contracts.

Types of Contract

1. Service contract
2. Data Contract
3. Message Contract
4. Fault contract

Service Contract

Service Contract describes the functionalities of the service. It represents the methods, which are exposed by service. WCF has predefined attribute to define the service contract. Service can be defined by using [ServiceContract] attribute.

Example-

    [ServiceContract]
     public interface IMyService
    {
         [OperationContract]
         string GetData();
    }

You can see in above code, I have written [ServiceContract] attribute on top of the interface "IMyService" which represents the service. To define the functionalities or operations of service, I have used [OperationContract] attribute. This service should be implemented to describe the functionality. Check the below implementation of service.

public class MyService: IMyService
    {
         public string GetData()
        {
          return "Hello";
        }
     }

Data Contract

Data Contract represents the data which is passed between client to server and vice versa. This data contract can be of simple type (like - int, string etc.) or Custom type (class). To define data contract [DataContract] attribute is used and to define the data member [DataMember] attribute is used.

Example-

   [DataContract]
    public class Employee
    {
         private int strEmpID;
        private string strEmpName;

        [DataMember]
        public int EmpID
        {
            get { return strEmpID; }
            set { strEmpID = value; }
        }

        [DataMember]
         public string EmpName
        {
            get { return strEmpName; }
            set { strEmpName= value; }
        }
    }

In above code, I have defined one custom type- "Employee", to make it data contract, I have written   [DataContract] attribute on top of it. Here I have defined 2 data members- "EmpID" and "EmpName". To define these data contract members, I have used [DataMember] attribute.


Message Contract

Message Contract allows framing of message format to interact with service. WCF by default supports SOAP format but by using message contract we can control over message format. Message contract is defined by using [MessageContract] attribute.

Example-

   //MessageContract
    [MessageContract]
    public class Dept
    {
         private int deptID;
        private string deptName;

        [MessageHeader]
         public int DeptID
        {
            get { return deptID; }
            set { deptID = value; }
        }
        [MessageBodyMember]
         public string DeptName
        {
            get { return deptName; }
            set { deptName = value; }
        }
    }

You can see in above code, I have taken one class - "Dept" and defined as message contract using [MessageContract] attribute. I have used [MessageHeader] and [MessageBodyMember] attributes for defining the message header and message body member. Now this message contract can be used to pass the message between client to server and vice versa.

I have added one method to set message contract.

       //Method to set Messagecontract data
        public Dept SetMessageContract(Dept objDept)
        {
            Dept tempDept = null;
            try
            {
                tempDept = new Dept();
                tempDept.DeptID = objDept.DeptID;
                tempDept.DeptName = objDept.DeptName;
            }
            catch (Exception)
            {
                throw new FaultException();
             }
            return objDept;
        }

I have added “DeptID” as MessageHeader and “DeptName” as MessageBodyMember, so DeptID will be added to SOAP header and DeptName will be added to SOAP body. You will find additional entries in response like this-

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" >
  <s:Header>
    ---------------
    <h:DeptID u:Id="_3" xmlns:h="http://tempuri.org/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">1</h:DeptID>
    ---------------
    ---------------
  </s:Header>
  <s:Body u:Id="_0">
    <Dept xmlns="http://tempuri.org/">
     <DeptName>AC</DeptName>
    </Dept>
  </s:Body>
</s:Envelope>


Note-

1. MessageContract provides facility to format the SOAP message.
2. MessageContract allows interoperating with any system that communicates through SOAP.


Versioning of MessageConract

1. WCF does not deal with missing headers and the corresponding members are assigned with their default values.

Example-


Suppose, I have MessageContract with following properties-

DeptID(Header), DeptName(BodyMember)

I am passing values for these 2 properties from client, it is ok.

Now I have changed the version of the MessageContract and added 1 more header "Location". So, if I will not pass value for "Location" header from client then it will be assigned with its default value.


2. WCF also does not deal with extra headers (Exception- if the extra header has a “MustUnderstand” attribute set to true in the incoming SOAP message then it will generate error).

Example-

Suppose I have MessageContract with following properties-

DeptID(Header), DeptName(BodyMember), Location(Header)

I am passing values for these 3 properties from client.

Now I have changed the version of the MessageContract and removed 1 "Location" header and passing values for 3 properties from client. So, even location header is removed it will include "Location" header in SOAP header.

But if you will set MustUnderstand =true for Location(Header) then it will generate error-





You can check the implementation in attached code.


Fault contract

Fault contract allows handling the errors at service level. Using fault contract we can report proper error message to client so that it will be understood by client.

Example-

Here I am creating one class to describe fault contract.

[DataContract]
public class FaultEX
{    
    private int exCode;
    private string exDesc;

    [DataMember]
     public int  ExCode
    {
        get { return  exCode;}
        set {  exCode= value; }
    }

    [DataMember]         
    public string ExDesc
    {
        get { return exDesc;}
        set { exDesc= value; }
    }
}

Here I have defined only 2 properties but you can define more. Now bind this with operation contract.

    [ServiceContract]
    public interface IMyService
    {
        [OperationContract]
        [FaultContract(typeof(FaultEX))]
        void MethodToTestFault();
    }

Here you can see, I have used [FaultContract] attribue on the of MethodToTestFault(). Now check the below code to use fault contract.

       //Method to show functionality of Fault contract
        public void MethodToTestFault()
        {
            try
            {
                 //Generating DivideByZero Exception
                int a = 0;
                int b = 10;
                b = b / a;
            }
            catch (Exception ex)
            {
                FaultEX f = new FaultEX();
                f.ExCode = 101;
                f.ExDesc = "Can not divide number with zero.";
                 //Throwing Fault Contract
                 throw new FaultException<FaultEX>(f, new FaultReason("DivideByZero Exception"));
            }
        }

In above code, I have implemented code for fault contract. At the time of execution, if any error occurs then service will throw fault exception.




You can see above snap to get details of FaultContract.

Check the below link for more details about WCF contract-  Link

You can download the code from here-

WCFContractService

WCFContractClient

By Jitendra Faye   Popularity  (2696 Views)