Translate

Sunday 14 December 2014

Three ways to do WCF instance management, WCF Session – PerCall, PerSession, Single (Singleton)

WCF service object instancing basics

In normal WCF request and response communication, the following sequence of actions takes place:
  • WCF client makes a request to a WCF service object.
  • WCF service object is instantiated.
  • WCF service instance serves the request and sends the response to the WCF client.
Following is a pictorial representation of how WCF requests and responses work.

Following are different ways by which you can create WCF instances:
  • Create a new WCF service instance on every WCF client method call.
  • Only one WCF service instance should be created for every WCF client session.
  • Only one global WCF service instance should be created for all WCF clients.
To meet the above scenarios, WCF has provided three ways by which you can control WCF service instances:
  • Per call
  • Per session
  • Single instance

Per call instance mode

When we configure a WCF service as per call, new service instances are created for every method call you make via a WCF proxy client. The image below shows this in a pictorial format:
  • The WCF client makes the first method call (method call 1).
  • A new WCF service instance is created on the server for this method call.
  • The WCF service serves the request and sends the response and the WCF instance is destroyed and given to the garbage collector for clean up.
  • Now let’s say the WCF client makes a second method call, a new instance is created, the request is served, and the WCF instance is destroyed.
In other words, for every WCF client method call, a WCF service instance is created, and destroyed once the request is served.


Per session instance mode
Very often we need to maintain state between method calls or for a particular session. For those kinds of scenarios, we will need to configure the service per session. In per session, only one instance of a WCF service object is created for a session interaction. The figure below explains this in pictorial format.
  • The client creates the proxy of the WCF service and makes method calls.
  • A WCF service instance is created which serves the method response.
  • The client makes one more method call in the same session.
  • The same WCF service instance serves the method call.
  • When the client finishes its activity, the WCF instance is destroyed and served to the garbage collector for clean up.

Single instance mode

Often we would like to create one global WCF instance for all WCF clients. To create a single instance of a WCF service, we need to configure the WCF service as Single instance mode. Below is a simple pictorial notation of how the single instance mode will operate:
  • WCF client 1 requests a method call on the WCF service.
  • A WCF service instance is created and the request is served. The WCF service instance is not destroyed, the service instance is persisted to server other requests.
  • Now let’s say some other WCF client, e.g., client 2, requests a method call.
  • The same WCF instance which was created by WCF client 1 is used to serve the request for WCF client 2. In other words, only one global WCF server service instance is created to serve all client requests.



Now you can use following methods to control the WCF service instances-

1. PerCall
2. PerSession
3. Single (Singleton)

You have to specify any of these methods, when you are implementing the service contract.

PerCall-If you configured WCF service as “PerCall” then for each client request new service instance will be created. For this implementation you have to set InstanceContextMode attribute like this-

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]

PerSession- If WCF service is configured as “PerSession” then for each client one service instance will be created and same service instance will deal with all the requests of current client. This is like “[Session]” object in ASP.Net. For this implementation you have to set InstanceContextMode attribute like this-

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
Single(Singleton)- If WCF service is configured as “Single” then for all the clients only one service instance will be created and this service instance will common for all the clients. This is like “[Application]” object in ASP.Net. For this implementation you have to set InstanceContextMode attribute like this-

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single )]

Service Contract (ISessionService.cs)

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Runtime.Serialization;
usingSystem.ServiceModel;
usingSystem.Text;

namespaceWcfSession
{
//Service Contract for Percall
[ServiceContract(SessionMode = SessionMode.Required)]
publicinterface ISessionService_PerCall
{
[OperationContract]
int GetData_PerCall();
}

//Service Contract for Persession
[ServiceContract(SessionMode = SessionMode.Required)]
publicinterface ISessionService_PerSession
{
[OperationContract]
int GetData_PerSession();
}

//Service Contract for Singleton
[ServiceContract(SessionMode = SessionMode.Required)]
publicinterface ISessionService_Singleton
{
[OperationContract]
int GetData_Singleton();
}
}

Implementation of Service Contract

(SessionService.cs)


Here I have implemented service contracts, to increment the value by 1 for each call but based on service instance implementation you will get different values.

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Runtime.Serialization;
usingSystem.ServiceModel;
usingSystem.Text;

namespaceWcfSession
{
//Implementing service contract for Percall
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
publicclassSessionService_PerCall : ISessionService_PerCall
{
publicint value;
publicint GetData_PerCall()
{
value = value + 1;
returnvalue;
}
}

//Implementing service contract for Persession
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
publicclassSessionService_PerSession : ISessionService_PerSession
{
publicint value;
publicint GetData_PerSession()
{
value = value + 1;
returnvalue;
}
}

//Implementing service contract for Singleton
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single )]
publicclassSessionService_Singleton : ISessionService_Singleton
{
publicint value;
publicint GetData_Singleton()
{
value = value + 1;
returnvalue;
}
}
}


Configuration for WCF Service

App.Config File


Here I have set different configuration for each implementation.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" />
</system.web>
<system.serviceModel>
<services>

<!--Configuration for PerCall-->
<service name="WcfSession.SessionService_PerCall">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/WcfSession/SessionService_PerCall/" />
</baseAddresses>
</host>
<endpoint address="PerCall" binding="wsHttpBinding" contract="WcfSession.ISessionService_PerCall">
</endpoint>
</service>

<!--Configuration for PerSession-->
<service name="WcfSession.SessionService_PerSession">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/WcfSession/SessionService_PerSession/" />
</baseAddresses>
</host>
<endpoint address="PerSession" binding="wsHttpBinding" contract="WcfSession.ISessionService_PerSession">
</endpoint>
</service>

<!--Configuration for Singleton-->
<service name="WcfSession.SessionService_Singleton">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/WcfSession/SessionService_Singleton/" />
</baseAddresses>
</host>
<endpoint address="Singleton" binding="wsHttpBinding" contract="WcfSession.ISessionService_Singleton">
</endpoint>
</service>

</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>

In above example, I have created three different endpoints-

http://localhost:8732/WcfSession/SessionService_PerCall/
http://localhost:8732/WcfSession/SessionService_PerSession/
http://localhost:8732/WcfSession/SessionService_Singleton/


Consuming service

To test these services, I have created one client application, here I have added the reference of these services. Check the below code for client application.



usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Web;
usingSystem.Web.UI;
usingSystem.Web.UI.WebControls;
usingPerCall_ServiceRef;usingPerSession_ServiceRef;usingSingleton_ServiceRef;

publicpartialclassfrmPerSession : System.Web.UI.Page
{
protectedvoidbtnPerCall_Click(object sender, EventArgs e)
{
try
{
//Creating object for SessionService_PerCallClient class
SessionService_PerCallClient objPerCall =newSessionService_PerCallClient();
//Call1
lblPerCall.Text = lblPerCall.Text + objPerCall.GetData_PerCall().ToString() +", ";
//Call2
lblPerCall.Text = lblPerCall.Text + objPerCall.GetData_PerCall().ToString() +", ";
//Call3
lblPerCall.Text = lblPerCall.Text + objPerCall.GetData_PerCall().ToString();
}
catch (Exception ex)
{
Response.Write("Unable to access WCF service. Details-"+ ex.Message);
}
}

protectedvoidbtnPerSession_Click(object sender, EventArgs e)
{
try
{
//Creating object for SessionService_PerSessionClient class
SessionService_PerSessionClient objPerSession =newSessionService_PerSessionClient();
//Call1
lblPerSession.Text = lblPerSession.Text + objPerSession.GetData_PerSession().ToString() +", ";
//Call2
lblPerSession.Text = lblPerSession.Text + objPerSession.GetData_PerSession().ToString() +", ";
//Call3
lblPerSession.Text = lblPerSession.Text + objPerSession.GetData_PerSession().ToString();
}
catch (Exception ex)
{
Response.Write("Unable to access WCF service. Details-"+ ex.Message);
}
}

protectedvoidbtnSingleton_Click(object sender, EventArgs e)
{
try
{
//Creating object for SessionService_SingletonClient class
SessionService_SingletonClient objSingleton =newSessionService_SingletonClient();
//Call1
lblSingleton.Text = lblSingleton.Text + objSingleton.GetData_Singleton().ToString() +", ";
//Call2
lblSingleton.Text = lblSingleton.Text + objSingleton.GetData_Singleton().ToString() +", ";
//Call3
lblSingleton.Text = lblSingleton.Text + objSingleton.GetData_Singleton().ToString();
}
catch (Exception ex)
{
Response.Write("Unable to access WCF. Details-"+ ex.Message);
}
}
}


I have written code to test each implementation, just execute the code you will get output-


Browser -1



Browser -2

PerCall-For this implementation every time we are getting value-1, 1, 1. It means that for each client request service instance is created.

PerCall-For this implementation we are getting incremented value-1, 2, 3 (for Browser-1 and Browser-2).It means for each client it is maintaining different service instance.

Singleton-For this implementation we are getting incremented value-1,2,3 (for Browser-1) and 4,5,6 (forBrowser-2).It means for all clients it is maintaining single service instance.


WCF Session Mode:

WCF framework provides support to handle session in WCF service. You can use “SessionModeattribute to maintain the session in WCF service. This attribute can be set while defining the service contract. There are following values for this attribute.

1. SessionMode.Allowed
2. SessionMode.NotAllowed
3. SessionMode.Required

SessionMode.Allowed - It means Session is allowed but is not mandatory.

[ServiceContract(SessionMode = SessionMode.Allowed)]

SessionMode.NotAllowed- It means Session is not allowed for service contract.

[ServiceContract(SessionMode = SessionMode.NotAllowed )]

SessionMode.Required- It means Session is required for service contract.

[ServiceContract(SessionMode = SessionMode.Required)]

-----------------------------------------------------------------------------------------------------------------------

To configure sessions in WCF, one should know the following three elements:
  1. Binding – Because all bindings do not support sessions. Only WS-*, NetTcpBinding andNetNamedPipeBinding have session support so selection of appropriate binding is necessary.
  2. SessionMode – This service contract specifies service’s possible expectation for session from incoming client request. It has three self describing values:
    • Allowed – Service can accept sessionful clients as well as sessionless.
    • Required – Service will entertain only those clients who have session, sessionless client cannot connect to service.
    • NotAllowed – Service can interact only with sessionless clients. Just opposite to Required.
  3. InstanceContextMode – This is a service behavior that controls instantiation of actual service class. It has the following values:
    • PerCall – Each request made to server will be served by a new instance of service class.
    • PerSession – A Session will have its dedicated service instance and all requests pertaining to the session will be served by that instance only. All sessions will have their individual dedicated service instances.
    • Single –All requests to the service will be served by a single unique instance of service class.

At last, just recapitulate once - There are 3 things to remember for WCF session:
  1. Sessionful binding
  2. SessionMode service contract
  3. InstanceContextMode service behavior
Demarcation defines first and last operation in execution order.
WCF session is somewhat different than ASP.NET sessions in the following ways as in WCF:
  1. Sessions are created and terminated by clients.
  2. Server does not use session to store some general data.
  3. Session does not heavily rely on Session Id, a group of messages having particular field in their header or body can also be considered part of session.
  4. Session Id may not be same at client and server.