WCF Kick Start

In this article I would be describing the simplest form of WCF (Windows Communication Foundation) project which would get you started with the WCF concepts and best practices. The purpose is to minimise the confusion from code and configuration and explain the idea along with the best practice. I would also provide description and links to help you move to a more advanced WCF topics as and when required.

For the sake of kick start I would be using basicHttpBinding for the service and consumer, which does not require any kind of authentication when accessing the service. It is kind of open to all.

Below is an overall image of the solution, projects and project files that I have used to demonstrate the simplest form of WCF implementation.

solution

The solution contains a project WcfServiceOne which defines types for contracts exposed by the service. The person class is the data contract, MyService is the service and IMyService is an interface acting as a service contract. This project acts as an API for the services.

The ServiceOneHost is the service exposed to the client. It references the project WcfServiceOne which the actual implementation of the Service as an API. Though, I could have had the service implementation written in the same project, I preferred following the best practices, by implementing the Service and Service API (contracts and its implementation) in a separate project. One advantage of doing this is that, you have decoupled service and Service API, which simplifies using the API in a non-WCF environment by directly referencing it. The web.config file in this project contains the binding information for the service which I will be explaining later in this article.

The ServiceOneConsumer is a simple ASP.Net web application consuming the service exposed by ServiceOneHost. The web.config in this web application contains the binding information defined by the host.

WcfServiceOne

WcfServiceOne project contains:

  • Data Contract - Person.cs
  • Service Contract - IMyService.cs
  • Service Implementation - IMyService.cs
Also notice that the project references System.ServiceModel and System.Runtime.Serialization which are required to assign attributes like ServiceContract, OperationContract, DataContract and DataMember.

Person.cs

using System.Runtime.Serialization;

 

namespace WcfServiceOne

{

    [DataContract]

    publicclassPerson

    {

        [DataMember]

        publicstring FullName { get; set; }

 

        [DataMember]

        publicstring Gender { get; set; }

    }

}

IMyService.cs

using System.ServiceModel;

 

namespace WcfServiceOne

{

    [ServiceContract]

    publicinterfaceIMyService

    {

        [OperationContract]

        string Callme(Person p);

    }

}

MyService

namespace WcfServiceOne

{

    publicclassMyService : IMyService

    {

        publicstring Callme(Person p)

        {

            return"Hello " + p.FullName + "  " + " you are a " + p.Gender;

        }

    }

}

ServiceOneHost

Add a reference to WcfServiceOne and then right click on the project. Select "Add New Item" from the context menu and select "WCF Service" templates. Name the new file ServiceOneHost.svc. The template would also create the code files for you in the App_Code folder. You can delete it, the code file is not required. Open the ServiceOneHost.svc and change the line to:

<% @ ServiceHost Language ="C#" Debug ="true" Service ="WcfServiceOne.MyService" %>

 

Now open the web.config file in this project and add the following block at the last within the closing of configuration tag.

  < system.serviceModel >

    < behaviors >

      < serviceBehaviors >

        < behavior name ="ServiceOneHostBehavior">

          < serviceMetadata httpGetEnabled ="true"/>

          < serviceDebug includeExceptionDetailInFaults ="false"/>

        </ behavior >

      </ serviceBehaviors >

    </ behaviors >

    < services >

      < service behaviorConfiguration ="ServiceOneHostBehavior"name="WcfServiceOne.MyService">

        < endpoint address =""binding="basicHttpBinding"contract="WcfServiceOne.IMyService">

          < identity >

            < dns value ="localhost"/>

          </ identity >

        </ endpoint >

        < endpoint address ="mex"binding="mexHttpBinding"contract="IMetadataExchange"/>

      </ service >

    </ services >

  </ system.serviceModel >

system.servicemodeltag defines how the consumer is going to connect to the service exposed here. When you add a "WCF service" to the project using template, it responds with adding the above system.servicemodel in the web.config, except the following two lines.

      < service behaviorConfiguration ="ServiceOneHostBehavior"name="WcfServiceOne.MyService">

        < endpoint address =""binding="basicHttpBinding"contract="WcfServiceOne.IMyService">

Change the name, contract and binding information as shown above. The wsHttpBinding is used to provide more secured communication using certificate. Visit The pattern and practices for WCF security at Codeplex for further guidance on how to implement wsHttpBinding using certificates.

ServiceOneConsumer

Before you proceed with consumer, you need to generate a proxy for the service and define how it connects, in the web.config file. To generate the proxy and the configuration block we would use svcutil. Open the Visual studio command prompt from Visual Studio Tools and use the following command to generate the proxy and configuration.

svcutil http://localhost/ServiceOneHost/ServiceOneHost.svc /Language:C# /out:ServiceHostProxy.cs /config:ServiceHost.config

This will create a ServiceHostProxy.cs and ServiceHost.config. Open the ServiceHost.config and copy the block. Now open the web.config file and paste the block at the end before the closing tag of configuration. The endpoint address might differ depending your host and consumer address URL.

    < system.serviceModel >

        < bindings >

            < basicHttpBinding >

                < binding name ="BasicHttpBinding_IMyService"closeTimeout="00:01:00"

                        openTimeout ="00:01:00"receiveTimeout="00:10:00"

                        sendTimeout ="00:01:00"allowCookies="false"

                        bypassProxyOnLocal ="false"

                        hostNameComparisonMode ="StrongWildcard"

                        maxBufferSize ="65536"maxBufferPoolSize="524288"

                        maxReceivedMessageSize ="65536"

                        messageEncoding ="Text"textEncoding="utf-8"

                        transferMode ="Buffered"

                        useDefaultWebProxy ="true">

                    < readerQuotas maxDepth ="32"maxStringContentLength="8192"

                                 maxArrayLength ="16384"

                                 maxBytesPerRead ="4096"

                                 maxNameTableCharCount ="16384"/>

                    < security mode ="None">

                        < transport clientCredentialType ="None"proxyCredentialType="None"

                           realm =""/>

                        < message clientCredentialType ="UserName"algorithmSuite="Default"/>

                    </ security >

                </ binding >

            </ basicHttpBinding >

        </ bindings >

        < client >

            < endpoint address ="http://localhost/ServiceOneHost/ServiceOneHost.svc"

               binding ="basicHttpBinding"bindingConfiguration="BasicHttpBinding_IMyService"

               contract ="IMyService"name="BasicHttpBinding_IMyService"/>

        </ client >

    </ system.serviceModel >

Default.aspx

Now add the following UI in the home page of your consumer site. In this case it is Default.aspx.

< table style =" width: 400px;"cellspacing="0"cellpadding="0">

    <tr>

        <tdstyle="width:100px; vertical-align:top; text-align:left;">

            Your Name

        </td>

        <tdstyle="width:10px; vertical-align:top; text-align:left;">

            :

        </td>

        <tdstyle="width:290px; vertical-align:top; text-align:left;">

            <asp:TextBoxID="txtName"runat="server"Width="200"></asp:TextBox>

        </td>

    </tr>

    <tr>

        <tdstyle="vertical-align:top; text-align:left;">

            Gender

        </td>

        <tdstyle="vertical-align:top; text-align:left;">

            :

        </td>

        <tdstyle="vertical-align:top; text-align:left;">

            <asp:DropDownListID="ddlGender"runat="server">

                <asp:ListItemSelected="True"Text="Male"Value="male"/>

                <asp:ListItemText="Female"Value="female"/>

            </asp:DropDownList>

            <asp:ButtonID="btnSubmit"runat="server"Text="Submit"

                onclick="btnSubmit_Click"/>

        </td>

    </tr>

    <tr>

        <tdcolspan="3">

            <br/>

            <asp:LabelID="lblResult"runat="server"Text=""Font-Bold="true"
                    Font-Size="Large"></asp:Label>

        </td>

    </tr>

</ table >

Default.aspx.cs - Code Behind

using System;

using WcfServiceOne;

 

public partial class _Default : System.Web.UI.Page

{

    protectedvoid Page_Load(object sender, EventArgs e)

    {

        txtName.Text = "Manish Kumar Singh";

    }

    protectedvoid btnSubmit_Click(object sender, EventArgs e)

    {

        var p = newPerson {FullName = txtName.Text, Gender = ddlGender.SelectedValue};

 

        var proxy = newMyServiceClient();

        lblResult.Text = proxy.Callme(p);

    }

}

That's it. Now run the consumer site and give it a try.

Enjoy!
Manish