Message Contract In WCF And Implementation

Before explaining Message contract, I will explain about the message. Message is a unit of communication and it is in the form of a packet. These packets travel for sharing the data. It is an envelope by which the communication completes between the client and Service. This envelope consists of two parts- one is header and other is body . Header is used to send the sensitive information such as credential and token key etc.

What is Message Contract?

WCF uses soap message for communicating between the two parties. Most of the time the programmers focus on implementing the data contract, serializing the data but sometimes they need more control over the message format, then they should use message contract.

Data contract basically controls the content of the soap message such as message body but Message contract controls the structure of the message. Data contract describes what type will be exchange between the two parties and message contract describes the structure of the soap message.

Message contract is involved in controlling the structure of soap message body. It is also used to send and receive the data into soap header. The data contract and operation contract creates soap message by default but it is only the message body content. Sometimes we need more control over soap message, as we want to part our message in two portions, where one should contain the sensitive data and other should contain the message body and we can think about the message contract and this is only the choice for doing this.

Some important things that should be known to each developer about the message contract are-

  1. When we pass the message contract in an operation parameter, only one parameter can be passed. If we do against this rule, run time error will occur.
  2. The operation that has a message contract in the parameters can return either message contract type or nothing.
  3. The operation will return the message contract type and also accept only message contract type as a parameter.

Let’s explain with an example. Suppose, I am developing a Service, which has an operation for authenticating to the student. After successful authentication,  this method will return the detail of the student. To create this service, I need to create a Student class and this class is decorated with the data contract attribute.

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Runtime.Serialization;  
  5. using System.Web;  
  6. namespace WcfService {  
  7.     [DataContract]  
  8.     public class Student {  
  9.         [DataMember]  
  10.         public string studentName {  
  11.             get;  
  12.             set;  
  13.         }  
  14.         [DataMember]  
  15.         public string studentId {  
  16.             get;  
  17.             set;  
  18.         }  
  19.         public string studentFees {  
  20.             get;  
  21.             set;  
  22.         } // this will not expose to client side because it does not hava DataMember Attribute  
  23.     }  
  24. }  
Now, I am creating a class StudentLogin and this class has two public properties, where one is token and other is studentName. This class will be the parameter of LoginStudentAndGetDetail operation. Please see the given method, as it returns StudentLoginSussess type and accepts StudentLogin class Object. These both classes are decorated with the message contract attribute because the rule says that the operation that uses the message contract as a parameter can return only message contract type.

[OperationContract]
StudentLoginSussess LoginStudentAndGetDetail(StudentLogin login);


Token in StudentLogin class is decorated with Message Header attribute, which says this variable will come in header section of soap message and StudentName is decorated with MessageBodyMember attribute, which says it will come in body section of soap message.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Runtime.Serialization;  
  6. using System.ServiceModel;  
  7. namespace WcfService {  
  8.     [MessageContract]  
  9.     public class StudentLogin {  
  10.         [MessageHeader]  
  11.         public string Token {  
  12.             get;  
  13.             set;  
  14.         }  
  15.         [MessageBodyMember]  
  16.         public string studentName {  
  17.             get;  
  18.             set;  
  19.         }  
  20.     }  
  21.     [MessageContract]  
  22.     public class StudentLoginSussess {  
  23.         [MessageBodyMember]  
  24.         public Student student {  
  25.             get;  
  26.             set;  
  27.         }  
  28.     }  
  29. }  
MessageHeader

Message header says that the member, which is decorated with MessageHeader attribute will be the part of a message header. In other words, if we want to declare a member inside the message header, we must apply MessageHeader attribute on that member.

MessageBodyMember

Message Body Member says that the member, which is decorated with MessageBodyMember attribute will be the part of the message body. In other words, if we want to declare a member inside the message body, we must apply MessageBodyMember attribute before the member.

Now, the code of IStudentWcfService interface is there, where I declared all the operations of my Service but right now, I will show only one operation, which has a parameter of type StudentLogin and returns StudentLoginSussess.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Runtime.Serialization;  
  5. using System.ServiceModel;  
  6. using System.Text;  
  7. namespace WcfService {  
  8.     // NOTE You can use the "Rename" command on the "Refactor" menu to change the interface name "IStudentWcfService" in both code and config file together.  
  9.     [ServiceContract]  
  10.     public interface IStudentWcfService {  
  11.         [OperationContract]  
  12.         StudentLoginSussess LoginStudentAndGetDetail(StudentLogin login);  
  13.         // NOTE: both classes are decorated with message contract.  
  14.     }  
  15. }  
Now, I am creating a class StudentWcfService, which implements the IStudentWcfService interface and define all the methods, which are declared in  an interface. In this class, I defined the method LoginStudentAndGetDetail , which is used for authenticating the student by checking the token, if the token is "12121212" (hard coded) and return the student detail, else it throws an exception.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Runtime.Sesrialization;  
  5. using System.ServiceModel;  
  6. using System.Text;  
  7. namespace WcfService {  
  8.     public class StudentWcfService: IStudentWcfService {  
  9.         public StudentLoginSussess LoginStudentAndGetDetail(StudentLogin login) {  
  10.             Student student = new Student();  
  11.             // you can write here your login logic  
  12.             if (login.Token != "12121212") {  
  13.                 string ex = "invalid user";  
  14.                 throw new FaultException < string > (ex);  
  15.             }  
  16.             student.studentName = "Raj";  
  17.             student.studentId = "2";  
  18.             student.studentFees = "5000";  
  19.             StudentLoginSussess ob = new StudentLoginSussess();  
  20.             ob.student = student;  
  21.             return ob;  
  22.         }  
  23.     }  
  24. }  
  25. }  
The code, given above will be fine but what exception will rise, when we pass more than one parameter into an operation, which uses the message contract.

Please have a look on the given code. I am passing two parameters into this operation and this operation returns a Message Contract type.

public StudentLoginSussess LoginStudentAndGetDetail(StudentLogin login,string name) // this code is wrong, as it is only created to show the exception
  1. {  
  2.     Student student = new Student();  
  3.     // you can write here your login logic  
  4.     //if (login.Token != "12121212")  
  5.     //{  
  6.     // string ex = "invalid user";  
  7.     // throw new FaultException<string>(ex);  
  8.     //}  
  9.     student.studentName = "Raj";  
  10.     student.studentId = "2";  
  11.     student.studentFees = "5000";  
  12.     StudentLoginSussess ob = new StudentLoginSussess();  
  13.     ob.student = student;  
  14.     return ob;  
  15. }  
If I pass the second parameter, it is showing the error, given below.

runs

After seeing this error, I altered my code and then started debugging. Subsequently, it runs successfully.