WCF Service Self Hosting And Consuming With Windows Application

In order to consume the WCF Service, you need to host your service somewhere, it can be IIS, WAS or Self Hosted. If you host your service using IIS and WAS then it auto create the instance of the ServiceHost class and calls the service. But Self Hosted WCF Service needs to create instance on demand. We can manage to create instance of ServiceHost.

wcf

So, in this tutorial, my theme is to show how to achieve WCF service self-hosting and consume the service with some other client application.

  1. How to create service application.
  2. How to create service host application.
  3. How to consume service with client application.

solution explorer

Step 1:
How to create service application

To create a new wcf service, open Visual Studio 2015 and go to File menu and choose New > Project, it will open a New Project window, you need to choose WCF Service Library from WCF template and provide the suitable name for the service “MathServiceLibrary” and click OK.

new project

It will create the following WCF Service Library for the service. Here you can see an interface “IService1.cs” and a class “Service1.cs” which has been created as template. Now you need to delete it.
¬
service

After deleting both the files, right click on project and choose Add and then New Item and add an interface as “IMathService.cs” and a class “MathService.cs”.

Inside the Contract “IMathService.cs”, we need to make some changes in the code and add some operation like Add, Subtract and Multiply.

When you are going to add the method named “Add” with OperationContract attribute, it will give you the following error. It means, you need to add System.ServiceModel namespace.

IMathService

IMathService.cs

  1. using System.ServiceModel;  
  2.   
  3. namespace MathServiceLibrary   
  4. {  
  5.     [ServiceContract]  
  6.     public interface IMathService   
  7.     {  
  8.         [OperationContract]  
  9.         int Add(int num1, int num2);  
  10.   
  11.         [OperationContract]  
  12.         int Subtract(int num1, int num2);  
  13.   
  14.         [OperationContract]  
  15.         int Multiply(int num1, int num2);  
  16.     }  
  17. }  
MathService.cs
  1. namespace MathServiceLibrary   
  2. {  
  3.     public class MathService: IMathService   
  4.     {  
  5.   
  6.         public int Add(int num1, int num2)   
  7.         {  
  8.             return num1 + num2;  
  9.         }  
  10.   
  11.         public int Subtract(int num1, int num2)   
  12.         {  
  13.             int result = 0;  
  14.             if (num1 > num2)   
  15.             {  
  16.                 result = num1 - num2;  
  17.             } else   
  18.             {  
  19.                 result = num2 - num1;  
  20.             }  
  21.             return result;  
  22.         }  
  23.   
  24.         public int Multiply(int num1, int num2)   
  25.         {  
  26.             return (num1 * num2);  
  27.         }  
  28.     }  
  29. }  
Please note, it is not doing anything with app.config of MathServiceLibrary.

Step 2: How to create service host application

To create a console application for service host, right click on solution and choose Add > New Project, it will open a Add New Project window, you need to choose Console Application from Window Desktop template and provide the suitable name for the service “MathServiceHost” and click on OK.

MathServiceHost

Now time to add the reference of WCF service library to host application. To do that, right click on References and choose Add Reference. From the Solution Tab, you will find the MathServiceLibrary reference.

MathServiceLibrary

You need to add the reference of System.ServiceModel. See the following image to add this reference into the project inside the References.

refrences

refrences

Made the following code for starting and stopping the wcf service from the host; Here you can see, first you just need to create instance of the ServiceHost and the instance of ServiceHost will contain the MathSerice. For starting the service “serviceHost.Open()” and for stopping the service “serviceHost.Close()”;

Program.cs
  1. using System;  
  2. using System.ServiceModel;  
  3.   
  4.   
  5. namespace MathServiceHost   
  6. {  
  7.     class Program   
  8.     {  
  9.         static void Main(string[] args)   
  10.       {  
  11.             ServiceHost serviceHost = null;  
  12.   
  13.             try   
  14.             {  
  15.                 serviceHost = new ServiceHost(typeof(MathServiceLibrary.MathService));  
  16.                 serviceHost.Open();  
  17.                 Console.WriteLine("Service is started");  
  18.                 if (serviceHost != null) {  
  19.                     Console.WriteLine("Press Any Key to Shutdown the service");  
  20.                     Console.ReadKey();  
  21.                     serviceHost.Close();  
  22.                     serviceHost = null;  
  23.                 }  
  24.             } catch (Exception ex)   
  25.             {  
  26.                 serviceHost = null;  
  27.                 Console.WriteLine("Service can not be started, Error :" + ex.Message);  
  28.                 Console.ReadKey();  
  29.             }  
  30.   
  31.         }  
  32.     }  
  33. }  
App.Config

To configure your service, you can define the endpoint for the service as well as behavior or the service. You can also define the base address for accessing the service from browser. In my project I am using basicHttpBinding, you can use any other binding, to configure one more binding here, you need to add one more endpoint.
  1. <?xml version="1.0" encoding="utf-8" ?>  
  2.     <configuration>  
  3.         <startup>  
  4.             <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />  
  5.         </startup>  
  6.         <system.serviceModel>  
  7.             <services>  
  8.                 <service name="MathServiceLibrary.MathService" behaviorConfiguration="MathServiceBehaviors">  
  9.                     <host>  
  10.                         <baseAddresses>  
  11.                             <add baseAddress="http://localhost:8080/MathService" />  
  12.                         </baseAddresses>  
  13.                     </host>  
  14.                     <endpoint address="http://localhost:8080/MathService" binding="basicHttpBinding" contract="MathServiceLibrary.IMathService">  
  15.                     </endpoint>  
  16.                     <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"></endpoint>  
  17.                 </service>  
  18.   
  19.             </services>  
  20.             <behaviors>  
  21.                 <serviceBehaviors>  
  22.                     <behavior name="MathServiceBehaviors">  
  23.                         <serviceMetadata httpGetEnabled="true" />  
  24.                     </behavior>  
  25.                 </serviceBehaviors>  
  26.             </behaviors>  
  27.         </system.serviceModel>  
  28.     </configuration>  
Now your WCF service is ready for hosting the service, to check, press F5 to run the service host project. You can see the following error will come.

error

It is because before running the host, you need to confirm the service host project set to “Set as Startup Project”.

Set as Startup Project

You can uncheck the “Start WCF Service Host when debugging another project in the same solution” to run the service host from the WCF Option from the project properties.

debug

Now press F5 to run the service host, It will run perfectly fine.

run

So, above two steps are used to create your service library as well as WCF service host for self hosting the service. You have self hosted your service successfully.

Step 3: How to consume service with client application,

To create client application, I am taking a Windows Application as client application. Right click on solution and choose Add > New Project, it will open a Add New Project window, you need to choose Windows Forms Application from Window Desktop template and provide the suitable name for the service “MathClient” and click OK.

MathClient

Create the following structure for math operation like Add, Subtract and Multiply.

operation

Before proceeding ahead, you need to create proxy class to call the service from host. To do that open Command Prompt in Administrator Mode and execute the host application,

cmd

Open another Visual Studio Command Prompt where client application is going to run and generate the proxy class and configuration for the service. You need to use SVCUtil.exe tools to create this.

cmd

It will create a proxy class “MathServiceProxy.cs” and “output.config”.

MathServiceProxy.cs
  1. //------------------------------------------------------------------------------  
  2. // <auto-generated>  
  3. // This code was generated by a tool.  
  4. // Runtime Version:4.0.30319.18408  
  5. //  
  6. // Changes to this file may cause incorrect behavior and will be lost if  
  7. // the code is regenerated.  
  8. // </auto-generated>  
  9. //------------------------------------------------------------------------------  
  10. [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel""4.0.0.0")]  
  11. [System.ServiceModel.ServiceContractAttribute(ConfigurationName = "IMathService")]  
  12. public interface IMathService   
  13. {  
  14.   
  15.     [System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IMathService/Add", ReplyAction = "http://tempuri.org/IMathService/AddResponse")]  
  16.     int Add(int num1, int num2);  
  17.   
  18.     [System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IMathService/Add", ReplyAction = "http://tempuri.org/IMathService/AddResponse")]  
  19.     System.Threading.Tasks.Task < int > AddAsync(int num1, int num2);  
  20.   
  21.     [System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IMathService/Subtract", ReplyAction = "http://tempuri.org/IMathService/SubtractResponse")]  
  22.     int Subtract(int num1, int num2);  
  23.   
  24.     [System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IMathService/Subtract", ReplyAction = "http://tempuri.org/IMathService/SubtractResponse")]  
  25.     System.Threading.Tasks.Task < int > SubtractAsync(int num1, int num2);  
  26.   
  27.     [System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IMathService/Multiply", ReplyAction = "http://tempuri.org/IMathService/MultiplyResponse")]  
  28.     int Multiply(int num1, int num2);  
  29.   
  30.     [System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IMathService/Multiply", ReplyAction = "http://tempuri.org/IMathService/MultiplyResponse")]  
  31.     System.Threading.Tasks.Task < int > MultiplyAsync(int num1, int num2);  
  32. }  
  33.   
  34. [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel""4.0.0.0")]  
  35. public interface IMathServiceChannel: IMathService, System.ServiceModel.IClientChannel   
  36. {}  
  37.   
  38. [System.Diagnostics.DebuggerStepThroughAttribute()]  
  39. [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel""4.0.0.0")]  
  40. public partial class MathServiceClient: System.ServiceModel.ClientBase < IMathService > , IMathService   
  41. {  
  42.   
  43.     public MathServiceClient() {}  
  44.   
  45.     public MathServiceClient(string endpointConfigurationName):  
  46.         base(endpointConfigurationName) {}  
  47.   
  48.     public MathServiceClient(string endpointConfigurationName, string remoteAddress):  
  49.         base(endpointConfigurationName, remoteAddress) {}  
  50.   
  51.     public MathServiceClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress):  
  52.         base(endpointConfigurationName, remoteAddress) {}  
  53.   
  54.     public MathServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress):  
  55.         base(binding, remoteAddress) {}  
  56.   
  57.     public int Add(int num1, int num2)   
  58.     {  
  59.         return base.Channel.Add(num1, num2);  
  60.     }  
  61.   
  62.     public System.Threading.Tasks.Task < int > AddAsync(int num1, int num2)   
  63.     {  
  64.         return base.Channel.AddAsync(num1, num2);  
  65.     }  
  66.   
  67.     public int Subtract(int num1, int num2)   
  68.     {  
  69.         return base.Channel.Subtract(num1, num2);  
  70.     }  
  71.   
  72.     public System.Threading.Tasks.Task < int > SubtractAsync(int num1, int num2)   
  73.     {  
  74.         return base.Channel.SubtractAsync(num1, num2);  
  75.     }  
  76.   
  77.     public int Multiply(int num1, int num2)   
  78.     {  
  79.         return base.Channel.Multiply(num1, num2);  
  80.     }  
  81.   
  82.     public System.Threading.Tasks.Task < int > MultiplyAsync(int num1, int num2)   
  83.     {  
  84.         return base.Channel.MultiplyAsync(num1, num2);  
  85.     }  
  86. }  
App.config

For accessing the service, you need to define the endpoint inside the app.config. So copy the configuration from output.config and add into the app.config,
  1. <?xml version="1.0" encoding="utf-8" ?>  
  2.     <configuration>  
  3.         <startup>  
  4.             <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />  
  5.         </startup>  
  6.         <system.serviceModel>  
  7.             <bindings>  
  8.                 <basicHttpBinding>  
  9.                     <binding name="BasicHttpBinding_IMathService" />  
  10.                 </basicHttpBinding>  
  11.             </bindings>  
  12.             <client>  
  13.                 <endpoint address="http://localhost:8080/MathService" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IMathService" contract="IMathService" name="BasicHttpBinding_IMathService" />  
  14.             </client>  
  15.         </system.serviceModel>  
  16.     </configuration>  
See the following code, for implement the code to perform the math operation to call the service from host.
  1. using System;  
  2. using System.Windows.Forms;  
  3.   
  4. namespace MathClient {  
  5.     public partial class Form1: Form {  
  6.         MathServiceClient myClient = new MathServiceClient();  
  7.         public Form1() {  
  8.             InitializeComponent();  
  9.   
  10.   
  11.         }  
  12.   
  13.         private void btnAdd_Click(object sender, EventArgs e)   
  14.         {  
  15.   
  16.             int firstNumber = Convert.ToInt32(txtFirstNumber.Text);  
  17.             int secondNumber = Convert.ToInt32(txtSecondNumber.Text);  
  18.   
  19.             int result = myClient.Add(firstNumber, secondNumber);  
  20.             txtResult.Text = result.ToString();  
  21.         }  
  22.   
  23.         private void btnSubtract_Click(object sender, EventArgs e)   
  24.         {  
  25.             int firstNumber = Convert.ToInt32(txtFirstNumber.Text);  
  26.             int secondNumber = Convert.ToInt32(txtSecondNumber.Text);  
  27.   
  28.             int result = myClient.Subtract(firstNumber, secondNumber);  
  29.             txtResult.Text = result.ToString();  
  30.         }  
  31.   
  32.         private void btnMultiply_Click(object sender, EventArgs e)   
  33.         {  
  34.             int firstNumber = Convert.ToInt32(txtFirstNumber.Text);  
  35.             int secondNumber = Convert.ToInt32(txtSecondNumber.Text);  
  36.   
  37.             int result = myClient.Multiply(firstNumber, secondNumber);  
  38.             txtResult.Text = result.ToString();  
  39.         }  
  40.   
  41.         private void btnReset_Click(object sender, EventArgs e)   
  42.         {  
  43.             txtFirstNumber.Text = "";  
  44.             txtSecondNumber.Text = "";  
  45.             txtResult.Text = "";  
  46.         }  
  47.     }  
  48. }  
Press F5 to run the program, the following will be output for their operation.

output

output

output

Thanks for reading this article, hope you enjoyed it.