Praveen Katiyar' Blog

Learning along the way . . . .

Creating a Self Hosted WCF Service

In this post I am going to explain how to create a simple WCF Service, with Self Hosting and consume it, there will be 4 parts of the project.

  1. A Class Library (MyMathServiceLib.dll): which will implement our business logic.
  2. Service Host Application (MathServiceHost.exe): Application which will host this class library as a WCF Service.
  3. A Windows Client Application (MyMathServiceClient.exe): Client Application which will use this service.
  4. A Web Client, that will use this Service.

Note:

part 1 and 2 can be merged into one, if one like so, but, for the sake of portability, keep them as separate modules. let’s start with creating the Class Library.

Part 1: Creating the Class Library

Start the Visual Studio, and click File->New->Project . Select the project template ‘Class Library" click OK.

image

Now let’s analyse the project created by wizard for us, and do little house keeping, before we write any code.

  • Class1.cs (The default class, created by wizard).

Assumption

We are going to create a Service as per following assumptions.

  • Interface will named as IMyMathService (IMyMathService.cs)
  • Service will be implemented as MyMathService (MyMathService.cs)

Little house keeping. (just to keep things organized)

  • Delete Class1.cs the project workspace.
  • Add an Interface (IMyMathService) IMyMathService.cs to the project.
  • Add an Class (MyMathService) MyMathService.cs to the project.
  • Add reference of System.ServiceModel to the  project.

Now, let’s define the Interface and its implementation of our old familiar class Library.

//  Listing of IMyMathService.cs,

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

namespace MyMathServiceLib
{
    [ServiceContract]
    public interface IMyMathService
    {
        [OperationContract]
        double Add(double dblNum1, double dblNum2);

        [OperationContract]
        double Subtract(double dblNum1, double dblNum2);

        [OperationContract]
        double Multiply(double dblNum1, double dblNum2);

        [OperationContract]
        double Divide(double dblNum1, double dblNum2);
    }
}

//  Listing of MyMathService.cs,

using System;
using System.ServiceModel;
using System.Text;
using System.ServiceModel;

namespace MyMathServiceLib
{
    public class MyMathService : IMyMathService
    {
        public double Add(double dblNum1, double dblNum2)
        {
            return (dblNum1 + dblNum2);
        }

        public double Subtract(double dblNum1, double dblNum2)
        {
            return (dblNum1 – dblNum2);
        }

        public double Multiply(double dblNum1, double dblNum2)
        {
            return (dblNum1 * dblNum2);
        }

        public double Divide(double dblNum1, double dblNum2)
        {
            return ((dblNum2 == 0) ? 0 : (dblNum1 / dblNum2));
        }
    }
}

Part 2: Creating the Host Application

Our class library is ready, let’s write an Host application, which will expose this facility to the world as a WCF Service. lets’ Create a Console based application, for the sake of simplicity, name it MyMathServiceHost, as shown below.

image

a new Project MyMathServiceHost will be added to the workspace.

Assumption

The Host application will expose the following endpoints for the service.

  • Service will implement HTTP endpoint at Port 9001
  • Corresponding mex End Point  (IMetadatExchange) for the HTTP end point.  
  • Service will implement TCP endpoint at Port 9002
  • Corresponding mex End Point  (IMetadatExchange) for the TCP end point.  

Adding reference of the class library to the Host project

  • Add reference of the class library to the console project,as shown below.

image

  • Add reference of System.ServiceModel to the  project.

Creating the Service Configuration

Add a Application configuration file (App.config) to the Host Project. define the End Points and bindings according to the assumptions made at the start of the project.

  • will expose an end point with HTTP Binding at 9001
  • will expose an end point with TCP Binding at 9002
  • will expose, required mex (one for each binding) end points

below is he listing of the app.config file.

<?xml versio="1.0"?>
<configuration>

    <system.serviceModel>
      <services>
        <service name="MyMathServiceLib.MyMathService" behaviorConfiguration="myMathServiceBehave">
          <host>
            <baseAddresses>
              <add baseAddress="http://localhost:9001/MyMathService"/>
              <add baseAddress="net.tcp://localhost:9002/MyMathService"/>
            </baseAddresses>
          </host>
          <endpoint address="http://localhost:9001/MyMathService" binding="basicHttpBinding" contract="MyMathServiceLib.IMyMathService"/>
          <endpoint address="net.tcp://localhost:9002/MyMathService" binding="netTcpBinding" contract="MyMathServiceLib.IMyMathService"/>
          <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
          <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
        </service>
      </services>
      <behaviors>
        <serviceBehaviors>
          <behavior name="myMathServiceBehave">
            <serviceMetadata httpGetEnabled="true"/>
          </behavior>
        </serviceBehaviors>
      </behaviors>
    </system.serviceModel>
</configuration>

Description
  • Application configuration files defines 2 endpoints, one for TCP and one for HTTP. and 1 mex end point for each.
  • Service behavior define, <serviceMetadata httpGetEnabled="true"/> that meta data should be available through a HTTP get request.

Write code to Host the Service.

Write the code to Host the Service in the Main function of the Open Program.cs, and let’s write the code.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace CalcServiceHost
{
    class Program
    {
        static void Main(string[] args)
        {
            ServiceHost svcHost = null;
            try
            {
                svcHost = new ServiceHost(typeof(MyMathServiceLib.MyMathService));
                svcHost.Open();
                Console.WriteLine("\n\nService is Running  at following address" );
                Console.WriteLine("\nhttp://localhost:9001/MyMathService");
                Console.WriteLine("\nnet.tcp://localhost:9002/MyMathService");
            }
            catch (Exception eX)
            {
                svcHost = null;
                Console.WriteLine("Service can not be started \n\nError Message [" + eX.Message + "]");
            }

            if (svcHost != null)
            {
                Console.WriteLine("\nPress any key to close the Service");
                Console.ReadKey();
                svcHost.Close();
                svcHost = null;
            }
        }
    }
}

explanation

as you can see from the above code,

  • Class Library is simply hosted inside a ServiceHost object, as all the End Points are defined in App.config file.

Part 3: Creating the Windows Client

Now when our service is self hosted and running, let us write a client Application, which can use this Service. lets’ Create a Console based application, for the sake of simplicity, name it MyMathServiceClient, as shown below.

image

newly created project will be added to the work space.

Generating proxy and config file.

Before we write the Client application, we need to generate the proxy for our Service, open a command prompt in Administrator mode. and execute the Host Application.

image

Open another command prompt, switch to the folder, where client project has been created, and generate the proxy and configuration file using the SVCUtil.exe utility. as shown below.

image

add both these files to the client project.

Calling the Service

Now write the code to use the proxy and call the service, here is the listing of the Program.cs.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyMathClient
{
    class Program
    {
        static void Main(string[] args)
        {
            double dblX = 2000.0;
            double dblY = 100.0;
            double dblResult = 0;

            try
            {
                Console.WriteLine("Using TCP Binding", dblX, dblY, dblResult);

                MyMathServiceClient mathClient1 = new MyMathServiceClient("NetTcpBinding_IMyMathService");

                dblResult = mathClient1.Add(dblX, dblY);
                Console.WriteLine("Calling Add >>  X : {0:F2}  Y : {1:F2}  Result : {2:F2}", dblX, dblY, dblResult);

                dblResult = mathClient1.Subtract(dblX, dblY);
                Console.WriteLine("Calling Sub >>  X : {0:F2}  Y : {1:F2}  Result : {2:F2}", dblX, dblY, dblResult);

                dblResult = mathClient1.Multiply(dblX, dblY);
                Console.WriteLine("Calling Mul >>  X : {0:F2}  Y : {1:F2}  Result : {2:F2}", dblX, dblY, dblResult);

                dblResult = mathClient1.Divide(dblX, dblY);
                Console.WriteLine("Calling Sub >>  X : {0:F2}  Y : {1:F2}  Result : {2:F2}", dblX, dblY, dblResult);

                Console.WriteLine("Using Basic HTTP Binding", dblX, dblY, dblResult);

                MyMathServiceClient mathClient2 = new MyMathServiceClient("BasicHttpBinding_IMyMathService");

                dblResult = mathClient2.Add(dblX, dblY);
                Console.WriteLine("Calling Add >>  X : {0:F2}  Y : {1:F2}  Result : {2:F2}", dblX, dblY, dblResult);

                dblResult = mathClient2.Subtract(dblX, dblY);
                Console.WriteLine("Calling Sub >>  X : {0:F2}  Y : {1:F2}  Result : {2:F2}", dblX, dblY, dblResult);

                dblResult = mathClient2.Multiply(dblX, dblY);
                Console.WriteLine("Calling Mul >>  X : {0:F2}  Y : {1:F2}  Result : {2:F2}", dblX, dblY, dblResult);

                dblResult = mathClient2.Divide(dblX, dblY);
                Console.WriteLine("Calling Sub >>  X : {0:F2}  Y : {1:F2}  Result : {2:F2}", dblX, dblY, dblResult);
            }
            catch (Exception eX)
            {
                Console.WriteLine("There was an error while calling Service [" + eX.Message + "]");
            }
        }
    }
}

and here is the output.

image

Part 4: Creating a Web Client

Create a New Web Site, using the File –> New Web Site as shown below. name it MyMathWebClient.

image

 

Click OK,

Now we need to add a reference to our service to this web site, right click on the newly created web site project, and click on Add Service Reference. a dialog box will pop up.

  • Enter any (TCP/HTTP) endpoint address in the address box.
  • Name the namespace, where Service Proxy will be added to the project.

image

click OK, some changes will be made to your web.config file, and App_WebReferences folder will be added, under which a Service reference "MathServiceReference" will be added.

  • a Service reference named MyMathServiceReference will be added in Service References node of the client project.
  • some changes will be made to the web.config file,

let’s analyse the changes made to web.config. open the web.config, you will find the changes at the end of the file, see the <system.ServiceModel> section, as shown below.

<system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_IMyMathService"/>
      </basicHttpBinding>
      <netTcpBinding>
        <binding name="NetTcpBinding_IMyMathService"/>
      </netTcpBinding>
    </bindings>
    <client>
      <endpoint address="
http://localhost:9001/MyMathService&quot; binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IMyMathService" contract="MathServiceReference.IMyMathService" name="BasicHttpBinding_IMyMathService"/>
      <endpoint address="net.tcp://localhost:9002/MyMathService" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IMyMathService" contract="MathServiceReference.IMyMathService" name="NetTcpBinding_IMyMathService">
        <identity>

          <!—this value will be different on your machine –!>
          <userPrincipalName value="PRAVEEN-WIN7\BriskTech"/>
        </identity>
      </endpoint>
    </client>
</system.serviceModel>

Open the Main page of the site (Default.aspx page), double click, that will create the Page_Load  handler for the Page, lets call our service in the page load handler.

protected void Page_Load(object sender, EventArgs e)
    {
        double dblX = 10000.0 ;
        double dblY = 2000.0 ;
        Response.Write ( "<p>Value 1 : " + dblX.ToString ( "F2"));
        Response.Write ( "<br>Value 2 : " + dblY.ToString ( "F2"));

        try
        {
            Response.Write("<p>Using TCP Binding");

            MathServiceReference.MyMathServiceClient mathProxy1 = new MathServiceReference.MyMathServiceClient("NetTcpBinding_IMyMathService");

            double dblResult = mathProxy1.Add(dblX, dblY);
            Response.Write("<br>Calling Add >>  X : " + dblX.ToString("F2") + "  Y : " + dblY.ToString("F2") + " Result : " + dblResult.ToString("F2"));

            dblResult = mathProxy1.Subtract(dblX, dblY);
            Response.Write("<br>Calling Add >>  X : " + dblX.ToString("F2") + "  Y : " + dblY.ToString("F2") + " Result : " + dblResult.ToString("F2"));

            dblResult = mathProxy1.Multiply(dblX, dblY);
            Response.Write("<br>Calling Add >>  X : " + dblX.ToString("F2") + "  Y : " + dblY.ToString("F2") + " Result : " + dblResult.ToString("F2"));

            dblResult = mathProxy1.Divide(dblX, dblY);
            Response.Write("<br>Calling Add >>  X : " + dblX.ToString("F2") + "  Y : " + dblY.ToString("F2") + " Result : " + dblResult.ToString("F2"));

            Response.Write("<p>Using Basic HTTP Binding");

            MathServiceReference.MyMathServiceClient mathProxy2 = new MathServiceReference.MyMathServiceClient("BasicHttpBinding_IMyMathService");

            dblResult = mathProxy2.Add(dblX, dblY);
            Response.Write("<br>Calling Add >>  X : " + dblX.ToString("F2") + "  Y : " + dblY.ToString("F2") + " Result : " + dblResult.ToString("F2"));

            dblResult = mathProxy2.Subtract(dblX, dblY);
            Response.Write("<br>Calling Add >>  X : " + dblX.ToString("F2") + "  Y : " + dblY.ToString("F2") + " Result : " + dblResult.ToString("F2"));

            dblResult = mathProxy2.Multiply(dblX, dblY);
            Response.Write("<br>Calling Add >>  X : " + dblX.ToString("F2") + "  Y : " + dblY.ToString("F2") + " Result : " + dblResult.ToString("F2"));

            dblResult = mathProxy2.Divide(dblX, dblY);
            Response.Write("<br>Calling Add >>  X : " + dblX.ToString("F2") + "  Y : " + dblY.ToString("F2") + " Result : " + dblResult.ToString("F2"));
        }
        catch (Exception eX)
        {
            Response.Write("There was an error while calling Service <p> <b>[" + eX.Message + "] </b>");
        }
    }

Build and run the web site, following output will be displayed.

image

that’s all folks.

Advertisements

September 9, 2013 Posted by | CodeProject, SOA, WCF | , , | Leave a comment