Instance management is the technique WCF uses to bind client requests to service instances, governing which service instance handles which client request, and when. WCF supports 3 types of instance activation.
- Per Call: per call services allocate and destroy a new service instance for each client request
- Per Session: session full services allocate a service instance for each client connection
- Singleton: singleton services share the same service instance for all clients, across all connections and activations
By and large, the service instance mode is strictly a server side implementation detail, that should not manifest itself on the client side in any way.
Now let’s define a service that demonstrates the instance management in real life.
Creating the Class Library
Let’s create a service, create a new project, take a Class Library template, name it InstanceLib
, let’s do some house keeping with the newly created project.
- Delete the file Class1.cs from the project workspace.
- Add a new Interface named
ISingleCallService
to the project, a new file ISingleCallService.cs will be added to the project. - Add a new Class named
SingleCallService
, to the project. That will implement the ISingleCallService
interface, a new file SingleCallService.cs will be added to the project. - Add a new Interface named
ISessionService
to the project, a new file ISessionService.cs will be added to the project. - Add a new Class named
SessionService
, to the project. that will implement the ISessionService
interface, a new file SessionService.cs will be added to the project. <!--EndFragment--> - Add a new Interface named
ISingletonService
to the project, a new file ISingletonService.cs will be added to the project. - Add a new Class named
SingletonService
, to the project. that will implement the ISingletonService
interface, a new file SingletonService.cs will be added to the project.
To keep things simple, let’s assume that each interface defines only one method, which simply adds a passed value to its member variable.
Defining Interfaces
So let’s define interface for each service.
using System;
using System.Text;
using System.ServiceModel;
namespace InstanceLib
{
[ServiceContract]
interface ISingleCallService
{
[OperationContract]
double AddValue (double dblNum);
}
}
using System;
using System.Text;
using System.ServiceModel;
namespace InstanceLib
{
[ServiceContract]
interface ISessionService
{
[OperationContract]
double AddValue (double dblNum);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace InstanceLib
{
[ServiceContract]
interface ISingletonService
{
[OperationContract]
double AddValue (double dblNum);
}
}
- <!--EndFragment--><!--EndFragment-->
Implementing Interfaces
Let’s implement each interface, as shown below:
using System;
using System.Text;
using System.ServiceModel ;
namespace InstanceLib
{
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
public class SingleCallService : ISingleCallService
{
private double m_dblTotal = 0 ;
public double AddValue(double dblVal)
{
m_dblTotal += dblVal;
return m_dblTotal;
}
}
}
Important
You can notice ServiceBehavior
attribute of the class, which has been defined as InstanceContextMode.PerCall
, it specifies that a new InstanceContext
object is created prior to and recycled subsequent to each call. If you omit this attribute or do not specify, then InstanceContextMode.PerCall
is assumed by default.
using System;
using System.Text;
using System.ServiceModel;
namespace InstanceLib
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class SessionService : ISessionService
{
private double m_dblTotal = 0 ;
public double AddValue(double dblVal)
{
m_dblTotal += dblVal;
return m_dblTotal;
}
}
}
Important
You can notice ServiceBehavior
attribute of the class, which has been defined as InstanceContextMode.PerSession
, it specifies that InstanceContext
object is created for each session.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace InstanceLib
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class SingletonService : ISingletonService
{
private double m_dblTotal = 0 ;
public double AddValue(double dblVal)
{
m_dblTotal += dblVal;
return m_dblTotal;
}
}
}
Important
You can notice ServiceBehavior
attribute of the class, which has been defined as InstanceContextMode.Singlel
, it specifies that only one InstanceContext
object is used for all incoming calls and is not recycled to the calls. If the service object does not exist, one is created.
If you notice the all 3 service implementation, you will notice the difference in ServiceBehavior
class attribute of each class, apart from that, all interfaces that have been implemented have the same implementation. They simply add a passed value to a member variable of the class.
Build the project and your Class Library is ready.
Hosting the Service
For the sake of simplicity, I have hosted this service as a self hosted service, to create the Host application, create a new Console based application.
Before we write any code for the Host application, let’s define the configuration file for the Service(s).
="1.0"="utf-8"
<configuration>
<system.serviceModel>
<services>
<!–************************ Single Call Service ************************ –>
<service name="InstanceLib.SingleCallService"
behaviorConfiguration="SingleCallServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:9011/SingleCallService"/>
<add baseAddress="net.tcp://localhost:9012/SingleCallService"/>
</baseAddresses>
</host>
<endpoint address="http://localhost:9011/SingleCallService"
binding="wsHttpBinding" contract="InstanceLib.ISingleCallService"/>
<endpoint address="net.tcp://localhost:9012/SingleCallService"
binding="netTcpBinding" contract="InstanceLib.ISingleCallService"/>
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange"/>
<endpoint address="mex" binding="mexTcpBinding"
contract="IMetadataExchange"/>
</service>
<!—************************ Single Session Service ************************–>
<service name="InstanceLib.SessionService"
behaviorConfiguration="SessionServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:9013/SessionService"/>
<add baseAddress="net.tcp://localhost:9014/SessionService"/>
</baseAddresses>
</host>
<endpoint address="http://localhost:9013/SessionService"
binding="wsHttpBinding" contract="InstanceLib.ISessionService"/>
<endpoint address="net.tcp://localhost:9014/SessionService"
binding="netTcpBinding" contract="InstanceLib.ISessionService"/>
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange"/>
<endpoint address="mex" binding="mexTcpBinding"
contract="IMetadataExchange"/>
</service>
<!—************************** Singleton Service **************************–>
<service name="InstanceLib.SingletonService"
behaviorConfiguration="SingletonServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:9015/SingletonService"/>
<add baseAddress="net.tcp://localhost:9016/SingletonService"/>
</baseAddresses>
</host>
<endpoint address="http://localhost:9015/SingletonService"
binding="wsHttpBinding" contract="InstanceLib.ISingletonService"/>
<endpoint address="net.tcp://localhost:9016/SingletonService"
binding="netTcpBinding" contract="InstanceLib.ISingletonService"/>
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange"/>
<endpoint address="mex" binding="mexTcpBinding"
contract="IMetadataExchange"/>
</service>
</services>
<!– **************************** behaviors ************************** –>
<behaviors>
<serviceBehaviors>
<!– Single Call Service Behavior –>
<behavior name="SingleCallServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
<!–Single Session Service Behavior –>
<behavior name="SessionServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
<!–Singleton Service Behavior –>
<behavior name="SingletonServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Now let’s analyze the Configuration file.
Single Call Service
<!–******************* Single Call Service ************************** –>
<service name="InstanceLib.SingleCallService"
behaviorConfiguration="SingleCallServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:9011/SingleCallService"/>
<add baseAddress="net.tcp://localhost:9012/SingleCallService"/>
</baseAddresses>
</host>
<endpoint address="http://localhost:9011/SingleCallService"
binding="wsHttpBinding" contract="InstanceLib.ISingleCallService"/>
<endpoint address="net.tcp://localhost:9012/SingleCallService"
binding="netTcpBinding" contract="InstanceLib.ISingleCallService"/>
<endpoint address="mex"
binding="mexHttpBinding" contract="IMetadataExchange"/>
<endpoint address="mex"
binding="mexTcpBinding" contract="IMetadataExchange"/>
</service>
Session Service
<!—************************* Single Session Service ************************* –>
<service name="InstanceLib.SessionService"
behaviorConfiguration="SessionServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:9013/SessionService"/>
<add baseAddress="net.tcp://localhost:9014/SessionService"/>
</baseAddresses>
</host>
<endpoint address="http://localhost:9013/SessionService"
binding="wsHttpBinding" contract="InstanceLib.ISessionService"/>
<endpoint address="net.tcp://localhost:9014/SessionService"
binding="netTcpBinding" contract="InstanceLib.ISessionService"/>
<endpoint address="mex"
binding="mexHttpBinding" contract="IMetadataExchange"/>
<endpoint address="mex"
binding="mexTcpBinding" contract="IMetadataExchange"/>
</service>
Singleton Service
<!—************************** Singleton Service **************************–>
<service name="InstanceLib.SingletonService"
behaviorConfiguration="SingletonServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:9015/SingletonService"/>
<add baseAddress="net.tcp://localhost:9016/SingletonService"/>
</baseAddresses>
</host>
<endpoint address="http://localhost:9015/SingletonService"
binding="wsHttpBinding" contract="InstanceLib.ISingletonService"/>
<endpoint address="net.tcp://localhost:9016/SingletonService"
binding="netTcpBinding" contract="InstanceLib.ISingletonService"/>
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"/>
<endpoint address="mex"
binding="mexTcpBinding"
contract="IMetadataExchange"/>
</service>
Writing Code to Host the Service
using System;
using System.Text;
using System.ServiceModel;
namespace InstanceLibHost
{
class Program
{
static void Main(string[] args)
{
ServiceHost m_SingleCallHost = null;
ServiceHost m_SingleSessHost = null;
ServiceHost m_SingletonHost = null;
Console.WriteLine("\nHosting Single Call Service at >> " );
Console.WriteLine(" http://localhost:9011/SingleCallService");
Console.WriteLine(" net.tcp://localhost:9012/SingleCallService");
try
{
m_SingleCallHost = new ServiceHost(typeof(InstanceLib.SingleCallService));
m_SingleCallHost.Open();
}
catch (Exception eX)
{
Console.WriteLine("Failed while starting
Single Call Service Service [" + eX.Message + "]");
m_SingleCallHost = null;
}
if ( m_SingleCallHost!= null )
Console.WriteLine("Single Call Service hosted successfully . . .");
Console.WriteLine("\nHosting Single Session Service at >> ");
Console.WriteLine(" http://localhost:9013/SessionService");
Console.WriteLine(" net.tcp://localhost:9014/SessionService");
try
{
m_SingleSessHost = new ServiceHost(typeof(InstanceLib.SessionService));
m_SingleSessHost.Open();
}
catch (Exception eX)
{
Console.WriteLine("Failed while starting Single
Session Service [" + eX.Message + "]");
m_SingleSessHost = null;
}
if (m_SingleSessHost != null) Console.WriteLine
("Single Session Service hosted successfully . . .");
Console.WriteLine("\nHosting Singlton Service at >> " );
Console.WriteLine(" http://localhost:9015/SingletonService" );
Console.WriteLine(" net.tcp://localhost:9016/SingletonService");
try
{
m_SingletonHost = new ServiceHost(new InstanceLib.SingletonService());
m_SingletonHost.Open();
}
catch (Exception eX)
{
Console.WriteLine("Failed while starting Service [" + eX.Message + "]");
m_SingletonHost = null;
}
if (m_SingletonHost != null) Console.WriteLine("Singleton Service hosted successfully . . .");
Console.WriteLine("Press any key to close . . ." );
Console.ReadKey();
m_SingleCallHost.Close ();
m_SingleSessHost.Close ();
m_SingletonHost.Close () ;
m_SingleCallHost = null;
m_SingleSessHost = null;
m_SingletonHost = null;
}
}
}
Build and Execute the Service
Open a command prompt and execute the host. Here is the output.
Now when the service is hosted and running, let’s now create a client, which is actually going to use this service.
Creating Client
Creating the Base Project
Take a console based application.
Generating Proxies
While the host application is running, right click on the client application project, click on:
Generate Proxy for SingleCallService.
References –> Add Service Reference
In the address bar, type the address of the mex endpoint address of SingleCallService
as shown below.
In the namespace, type some good name, let’s say SingleCallServiceReference
for instance.
Hit OK, this will simply add a new file app.config to the project. and a new item in the Service Reference node of the project.
Generate Proxy for SessionService.
References –> Add Service Reference
In the address bar, type the address of the mex endpoint address of SessionService
as shown below.
In the namespace, type some good name, let’s say SessionServiceReference
for instance.
Generate Proxy for SingletonService.
References –> Add Service Reference
In the address bar, type the address of the mex endpoint address of SingletonService
as shown below.
In the namespace, type some good name, let’s say SingletonServiceReference
for instance.
Now when you have added references of all 3 services, let’s write code for the client to use these services.
using System;
using System.Text;
namespace InstanceClient
{
class Program
{
static void Main(string[] args)
{
SingleCallServiceReference.SingleCallServiceClient objSvc1 =
new SingleCallServiceReference.SingleCallServiceClient("WSHttpBinding_ISingleCallService");
SingleCallServiceReference.SingleCallServiceClient objSvc2 =
new SingleCallServiceReference.SingleCallServiceClient("NetTcpBinding_ISingleCallService");
Console.WriteLine("Client 1 Calling Single Call Service 3 times Using Http Binding");
for (int nI = 0; nI < 3; nI++)
{
double dblValue1 = 10;
double dblResult1 = objSvc1.AddValue(dblValue1);
Console.WriteLine("Using HTTP Binding >>
Input Value : {0:F2} Return value : {1:F2}", dblValue1, dblResult1);
}
Console.WriteLine("Client 2 Calling Single Call Service 3 times using TCP Binding");
for (int nI = 0; nI < 3; nI++)
{
double dblValue2 = 10;
double dblResult2 = objSvc2.AddValue(dblValue2);
Console.WriteLine("Using TCP Binding >>
Input Value : {0:F2} Return value : {1:F2}", dblValue2, dblResult2);
}
SessionServiceReference.SessionServiceClient objSvc3 =
new SessionServiceReference.SessionServiceClient("WSHttpBinding_ISessionService");
SessionServiceReference.SessionServiceClient objSvc4 =
new SessionServiceReference.SessionServiceClient("NetTcpBinding_ISessionService");
Console.WriteLine("\n\nClient 1 Calling Single Session Service 3 times Using Http Binding");
for (int nI = 0; nI < 3; nI++)
{
double dblValue1 = 10;
double dblResult1 = objSvc3.AddValue(dblValue1);
Console.WriteLine("Using HTTP Binding >>
Input Value : {0:F2} Return value : {1:F2}", dblValue1, dblResult1);
}
Console.WriteLine("Client 2 Calling Single Session Service 3 times using TCP Binding");
for (int nI = 0; nI < 3; nI++)
{
double dblValue2 = 10;
double dblResult2 = objSvc4.AddValue(dblValue2);
Console.WriteLine("Using TCP Binding >>
Input Value : {0:F2} Return value : {1:F2}", dblValue2, dblResult2);
}
SingletonServiceReference.SingletonServiceClient objSvc5 =
new SingletonServiceReference.SingletonServiceClient("WSHttpBinding_ISingletonService");
SingletonServiceReference.SingletonServiceClient objSvc6 =
new SingletonServiceReference.SingletonServiceClient("NetTcpBinding_ISingletonService");
Console.WriteLine("\n\nClient 1 Calling Singleton Service 3 times Using Http Binding");
for (int nI = 0; nI < 3; nI++)
{
double dblValue1 = 10;
double dblResult1 = objSvc5.AddValue(dblValue1);
Console.WriteLine("Using HTTP Binding >>
Input Value : {0:F2} Return value : {1:F2}", dblValue1, dblResult1);
}
Console.WriteLine("Client 2 Calling Singleton Service 3 times using TCP Binding");
for (int nI = 0; nI < 3; nI++)
{
double dblValue2 = 10;
double dblResult2 = objSvc6.AddValue(dblValue2);
Console.WriteLine("Using TCP Binding >>
Input Value : {0:F2} Return value : {1:F2}", dblValue2, dblResult2);
}
Console.WriteLine("Press any key to close . . . ");
Console.ReadKey();
}
}
}
Open command prompt and execute the client to see the output.
Open one more command prompt, and execute another instance of client.
As you can see from the output, all the instance mode in action.