A proper control of messages becomes necessary, when services and their clients are exchanging data outside their designated network and platform. It provides interoperability to clients using other web services such as ASMX.
We have discussed about interoperability in one of our previous articles, describing the advantages of using WCF.
Assuming you have gone through our previous articles on Service Contract and Data Contract, we will now see how to implement Message Contract in our WCF service.
A SOAP message is a packet, also called an Envelope, which has a Header section and a Body section. It makes sense, as the message is in XML format.
XML SOAP envelope (Request)
<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/"> <s:Header> <Action s:mustUnderstand="1" xmlns="https://schemas.microsoft.com/ws/2005/05/addressing/none"> https://tempuri.org/IBook/ShowBookInfo</Action> <h:BookId xmlns:h="https://tempuri.org/">001</h:BookId> </s:Header> <s:Body> <BooksRequest xmlns="https://tempuri.org/" /> </s:Body> </s:Envelope>
XML SOAP envelope (Response)
<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/"> <s:Header /> <s:Body> <BooksResponse xmlns="https://tempuri.org/"> <objBooks xmlns:a="https://schemas.datacontract.org/2004/07/" xmlns:i="https://www.w3.org/2001/XMLSchema-instance"> <a:Catagory>Programming</a:Catagory> <a:Name>Asp.Net 4 Blue Book</a:Name> <a:Price>56</a:Price> </objBooks> </BooksResponse> </s:Body> </s:Envelope>
We will see how to generate the XML file, later in this article.
using System; using System.Collections.Generic; using System.Linq; using System.ServiceModel; using System.Text; using System.Runtime.Serialization; [ServiceContract] public interface IBook { [OperationContract()] BooksBody ShowBookInfo(BooksHeader objBH); } // MessageContract [MessageContract()] public class BooksHeader { [MessageHeader()] public string sBookId; } [MessageContract()] public class BooksBody { [MessageBodyMember()] public BookDetails objBookDetails; } // DataContract [DataContract()] public class BookDetails { string sBookName; string sCategory; double dPrice; [DataMember()] public string Name { get { return sBookName; } set { sBookName = value; } } [DataMember()] public string Catagory { get { return sCategory; } set { sCategory = value; } } [DataMember()] public double Price { get { return dPrice; } set { dPrice = value; } } }
using System; using System.Collections.Generic; using System.Linq; using System.ServiceModel; using System.Text; using System.Runtime.Serialization; public class Book : IBook { public BooksBody ShowBookInfo(BooksHeader objBH) { BooksBody result = new BooksBody(); if (objBH.sBookId == "001") { result.objBookDetails = new BookDetails(); result.objBookDetails.Name = "Asp.Net 4 Blue Book"; result.objBookDetails.Catagory = "Programming"; result.objBookDetails.Price = 56; } return result; } }
Imports System.ServiceModel Imports System.Runtime.Serialization <ServiceContract()> Public Interface IBook <OperationContract()> _ Function ShowBookInfo(objBH As BooksHeader) As BooksBody End Interface <MessageContract()> Public Class BooksHeader <MessageHeader()> Public sBookId As String End Class <MessageContract()> Public Class BooksBody <MessageBodyMember()> Public objBookDetails As BookDetails End Class <DataContract()> _ Public Class BookDetails Dim sBookName As String Dim sCategory As String Dim dPrice As Double <DataMember()> Public Property Name() As String Get Return sBookName End Get Set(value As String) sBookName = value End Set End Property <DataMember()> Public Property Catagory() As String Get Return sCategory End Get Set(value As String) sCategory = value End Set End Property <DataMember()> Public Property Price() As Double Get Return dPrice End Get Set(value As Double) dPrice = value End Set End Property End Class
Public Class Book Implements IBook Public Function ShowBookInfo(objBH As BooksHeader) As BooksBody Implements IBooks.ShowBookInfo Dim result As New BooksBody() If objBH.sBookId = "001" Then result.objBookDetails = New BookDetails() result.objBookDetails.Name = "Asp.Net 4 Blue Book" result.objBookDetails.Catagory = "Programming" result.objBookDetails.Price = 56 End If Return result End Function End Class
While you are done with class file (for C# or Vb.Net), execute the class file or simply press “F5”. If everything you have written is ok, it will show a message on a browser, saying you have successfully created a service.
We have finally created our WCF service using Message Contract. Now, let us check the output using a Client interface. On the wed-page, we will add a textbox control and button control for submission. Finally, display the result returned by the WCF service on an HTML DIV element.
Before writing the submission code or button click event, we need to add a Service Reference to the client interface or application. A service reference allows client applications to access to one of more WCF services. See the image above; which says you have created a WCF service, we have to add the link (service) as a reference.
To add the service reference, open the “Solution Explorer” and right click the project, and click “Add Service Reference…” option.
In the address section add the service (see image), and click the “Go” button. It will download the information regarding the service, you just mentioned.
It automatically modifies the web.config file by adding few sections in the config file. The first change you will notice is that it has added <basicHttpBinding> configuration and settings.
<system.serviceModel> <bindings> <basicHttpBinding> <binding name="BasicHttpBinding_IBook"
This section will define the endpoint and its three important attributes, the address, binding and contract, at the client side. WCF exposes its services using endpoints and its attributes, commonly referred as the ABC’s of WCF.
<client> <endpoint address="https://localhost:1995/csharp/Book.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IBook" contract="ServiceReference_Books.IBook" name="BasicHttpBinding_IBook" /> </client>
<div style="font:15px Arial;"> <h2><strong>WCF Message Contract</strong></h2><br /> <div> <b>Enter Book ID</b>:  <input id="txtID" type="text" runat="server" /> </div> <div id="BooksDetails" runat="server" style="margin:10px 0;"> </div> <div style="margin:10px auto;"> <input type="button" value="Submit" runat="server" onserverclick="Submit" /> </div> </div>
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; public partial class _Default : System.Web.UI.Page { protected void Submit(object sender, EventArgs e) { ServiceReference_Books.BookClient objSR_Books = new ServiceReference_Books.BookClient(); BooksDetails.InnerHtml = "Book: " + objSR_Books.ShowBookInfo(txtID.Value).Name + "<br />" + "Category: " + objSR_Books.ShowBookInfo(txtID.Value).Catagory + "<br />" + "Price: $" + objSR_Books.ShowBookInfo(txtID.Value).Price; objSR_Books.Close(); // CLOSE THE CLIENT. } }
Option Explicit On Partial Class _Default Inherits System.Web.UI.Page Protected Sub Submit(sender As Object, e As EventArgs) Dim objSR_Books As New ServiceReference_Books.BooksClient BooksDetails.InnerHtml = _ "Book: " & objSR_Books.ShowBookInfo(txtID.Value).Name & "<br />" & _ "Category: " & objSR_Books.ShowBookInfo(txtID.Value).Catagory & "<br />" & _ "Price: $" & objSR_Books.ShowBookInfo(txtID.Value).Price objSR_Books.Close() ' CLOSE THE CLIENT. End Sub End Class
Check the XML SOAP envelope
To check the XML SOAP envelope, we will run a test using WcfTestClient application. We test the WCF services (from the client perspective) using this GUI tool, before deploying it at the client. This will ensure the proper execution of each Contract in our service.
See MSDN
You can find wcfTestClient.exe in your computers program files.
Path (VS 2008): C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\
Path (VS 2010): C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\
It is an executable file; you need double click on the file to open it.
On the WCF Test Client window, right click My Service Project to add the service. It will ask for the endpoint address, something like this.
https://localhost:1995/csharp/Book.svc
Double click the method ShowBookInfo() under BasicHttpBinding_IBook to see the Request and Response section.
Add a value for sBookID and click the Invoke button.
The id of the book must be 001, since we have hardcoded the value in our Book.cs class (Book.vb for Visual Basic). Once you have entered the correct value, the Response section will show details of the book with the id 001.
Finally, to check the SOAP envelop, click the XML tab under the response section. You can see the Header and Body of the actual message, which will be sent across the network.
Practically this article covers four major Contracts i.e. the Service Contract, Operation Contract, Data Contract and finally the Message Contract. However, I have tried to explain each Contract separately with simple examples and codes. I am assuming you have checked all of them.
WCF is vast and complex, and we need to dig and understand each method or attribute carefully. I may have missed few things here and there. It is my humble request, if you have found a bug or a mistake; please report it immediately (link contact). Alternatively, you can just pen down a suggestion about a topic or point that you think should have been there but its missing.