Tutorial on wcf message contract by example

This article gives you a walkthrough on WCF message contract by example, when to use WCF message contract, comparison of DataContract and MessageContract and finally some constraint on using WCF Message Contracts.


When to use WCF Message Contracts.

By default WCF takes care of creating SOAP messages according to service DataContracts and OperationContracts. However some time you required full control on SOAP messages structure and how serialization happens specially when your service needs to be interoperable for consuming by different types of clients or service needs to provide extra layer of security on messages and message parts. Messages are exchanged in different way of Message Exchange Patterns in WCF .


WCF DataContract vs MessageContract

Northwind system which is used for Order Entry web application with order details is running on Windows server which might have effect on the Product inventory back office application running on unix machine and payment application with customer details on mainframe machine. At the same time Product details need to send to your marketing campaign through API.

For accomplishing all those requirements you might create different DataContracts which will give you the XML xsd for communication with clients and other services. Such XSDs are tightly coupled which faces versioning issues and do not give you any control. For any last minute change on serialized object you will have to use events like OnSerializing or OnDeserializing. For example each of these operation requires to validate the private license key. This validation needs to be done in OnSerializing and if validation is sucessful then serilize the object.

You can also choose to create MessageContracts which will give you more control over the SOAP and no need for handling any extra events. SOAP headers are the reasonable place to keep the private keys like license key which can be use for validation.

ServiceContract never changes in case of MessageContracts in case of modification in data structure just need to change the message contract and no need for the regenerating proxies. In case of change in DataContracts you need to regenerate the proxy. So MessageContract is the good choice if your entity changes often.


Implementation of MessageContract

Below is an implementation of MessageContract where Northwind WCF service has heterogeneous client ask for the customer info. Only clients with specific license key will get the required response else WCF FaultException will be thrown.


  1. Create New Service library

    Create a new service using Create new WCF service library and test using WCFTestClient

  2. Customer DataContract

    Add new Customer DataContract to handle the Customer related info by adding new class to Service library. Add below code to the class and reference to System.Runtime.Serialization

                    
    namespace NorthwindServices
    {
        [DataContract]
        public class Customer
        {
            [DataMember]
            public string CustomerName;
    
            [DataMember]
            public string PhoneNumber;
    
            [DataMember]
            public string Email;
        }
    }
                
  3. Request MessageContract

    Create a new MessageContract for request by adding new class to Service library. Name it as CustomerContactRequest. Add reference to System.ServiceModel

                    
    namespace NorthwindServices
    {
        [MessageContract(IsWrapped=false)]
        public class CustomerContactRequest
        {
            [MessageHeader] 
            public string LicenseKey;
    
            [MessageBodyMember] 
            public int CustomerID;
        }
    }
            
  4. Response MessageContract

    Create a MessageContract for response.

                    
    namespace NorthwindServices
    {
        [MessageContract(IsWrapped = false)]
        public class CustomerContactResponse
        {
            [MessageBodyMember] 
            public Customer Contact;
        }
    }
                
  5. Add ServiceContract

    Add a service contract to handle customer message request and response.

                    
    [ServiceContract]
    public class ICustomerService
    {
        [OperationContract]
        [FaultContract(typeof(string)]  
        CustomerContactResponse 
            GetCustomerContact(CustomerContactRequest request);
    }
               
  6. Implementation of ICustomerService

    Implement ICustomerService as below. If LicenseKey is matching return the contact information else throw FaultException.

                    
    public class CustomerService : ICustomerService 
    {
        /// <summary>
        /// App key to validate
        /// In real time application this key can be reside
        ///      in config files or in data base.
        /// </summary>
        private string AppKey
        {
            get
            {
                return "northwind-xxx-1234-abc";
            }
        }
    
        public CustomerContactResponse 
            GetCustomerContact(CustomerContactRequest request)
        {
            if (request.LicenseKey != AppKey)
                throw new FaultException<string>("Invalid Key");
    
            // Get a record from your data store based on request.CustomerID 
            //    and set it to  CustomerContactResponse  as below.
    
            CustomerContactResponse response = new CustomerContactResponse();
            response.Contact = new Customer();
            response.Contact.CustomerName = "Abc";
            response.Contact.Email = "abc@xyz.com";
            response.Contact.PhoneNumber = "91 77 980 91 000";
            return response; 
        }
    }
                
  7. Add service endpoint

    Add CustomerService endpoint in app.config of NorthwindServices wcf service library under <system.serviceModel><services>

                    
    <service name="NorthwindServices.CustomerService">
        <host>
            <baseAddresses>
            <add baseAddress = "http://localhost:7741/NorthwindServices/
                CustomerService" />
            </baseAddresses>
        </host>        
        <endpoint address ="" binding="wsHttpBinding" 
            contract="NorthwindServices.ICustomerService">
            <identity>
            <dns value="localhost"/>
            </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" 
            contract="IMetadataExchange"/>
    </service>
                        
                
  8. Host CustomerService

    Host the CustomerService in hosting WCF service in IIS or in hosting in Windows service.

  9. CustomerService client

    Add client application for WCF CustomerService as suggested by article in previous. step.

    Add ServiceReference to CustomerService to NorthwindApp client application by right clicking on Service References -> Enter http://localhost:7741/NorthwindServices/CustomerService in address box and click Go.

    Add a reference to NorthwindApp.CustomerServiceRef in Program.cs

    Add below client code in Program.cs of client application.

                    
    static void Main(string[] args)
    {
        CustomerServiceClient client = new CustomerServiceClient();
        try
        {
            CustomerContactResponse response = new CustomerContactResponse();
                    
            //response.Contact = client.GetCustomerContact("abcd", 1234);
    
            response.Contact = client.GetCustomerContact
                ("northwind-xxx-1234-abc", 1234);
    
            Console.WriteLine(response.Contact.CustomerName);
            Console.WriteLine(response.Contact.Email);
            Console.WriteLine(response.Contact.PhoneNumber);
        }
        catch (FaultException<string> ex)
        {
            Console.WriteLine(ex.Detail);   
        }
        Console.Read(); 
    }
                

Download source code.

Speak your mind :
Leave a comment for this article on dotnetbloogers.com