WCF Sessions

Posted: September 7, 2008 in .NET, WCF
Tags: , ,

Whenever web developers hear the term session, we think of Http Session which is used to store data between multiple HTTP requests.That’s why many of us first get confused , when we hear about WCF Sessions.If we think in a more general term we can define session as something which correlates several messages together into a single conversation.

ASP.NET Sessions are:

  1. Always server-initiated.
  2. Implicitly unordered.
  3. Provide a way to preserve data across multiple requests.There is unique session id generated at the server and passed back and forth between client and server via URL or cookies.

WCF Sessions are

  1. Initiated and terminated by the calling application.
  2. Ordered message delivery
  3. Sessions correlate a group of messages into a conversation.This correlation depdending upon the binding can be taken care at message or transport level.
  4. No data storage is involved with WCF Session

To enable session for a WCF Service first thing that needs to be done is to set the SessionMode property of the ServiceContract attribute.
The three possible values of SessionMode are
1)NotAllowed – Session is prohibited.
2)Required – Session is mandatory.
3)Allowed – Session can be allowed.

Just setting this property is not sufficient to make the service, session enabled.The bindings of the exposed endpoints needs to support session.I developed a sample application to test out the features of WCF Session.I exposed an endpoint with BasicHttpBinding and set SessionMode to Allowed.The application was not throwing up any error but the session was not working.As I changed the SessionMode to Required I got the following error:

{“Contract requires Session, but Binding ‘BasicHttpBinding’ doesn’t support it or isn’t configured properly to support it.”}

This is because BasicHttpBinding does not support sessions.For this we have to choose wsHttpBinding or NetTcpBinding.WSHttpBinding binding, which contains support for both security sessions and reliable sessions.By default it uses only a secure session.The System.ServiceModel.NetTcpBinding binding supports transport level TCP/IP-based sessions.If we specifically turn off the message/transport level security of wsHttpBinding/NetTcpBinding and try to implement session the following exception message will appear:

Contract requires Session, but Binding ‘WSHttpBinding’ doesn’t support it or isn’t configured properly to support it.

As per default behaviour WCF uses the same service object to cater to all the requests within a session.This can be achieved through the attribute [ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)] We can mark some of the operations as Initiating/Terminating the session by using IsInitiating and IsTerminating properties of the OperationContract attribute.If IsInitiating/IsTerminating property is set then the SessionMode of the service has to Required.otherwise following exception message will appear:

{“The contract ‘ISessionDemo’ is not self-consistent — it has one or more IsTerminating or non-IsInitiating operations, but it does not have the SessionMode property set to SessionMode.Required.  The IsInitiating and IsTerminating attributes can only be used in the context of a session.”}

Initiating operations are those that must be called first. Non-initiating operations has to be be called only after at least one initiating operation has been called. Otherwise following exception message will come:

{“The operation ‘StartSession’ cannot be the first operation to be called because IsInitiating is false.”}

If I mark more than one method as Initiating then no exception will occur all of them will execute as part of the same session.Terminating operations, must be called as the last message in an existing session.After calling the Terminating method the service object and its context after the session with which the service was associated is closed. So if we try to invoke anyother method after the Terminating method the following exception message will come:

{“An operation marked as IsTerminating has already been invoked on this channel, causing the channel’s connection to terminate.  No more operations may be invoked on this channel.  Please re-create the channel to continue communication.”}

So we need to re-initilaize the proxy and related channel to invoke any other operations.

Another thing worth noting is how sessions behave when there is an exception.If there is an exception then the server channel will be faulted and the session will be destroyed along with that.This exception will be propagated to the client channel which in turn becomes faulted and proxy object instance cannot be used any further.If we try to invoke a method using this faulted channel following exception will occur

{“The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.”}

So as a good practice we should check the state of the proxy prior to making a method call.e.g.

if (proxy!=null && proxy.State == CommunicationState.Faulted)
{
   //call the method
}
else
{
 //Recreate the proxy
}

But if the exception is handled at the service end and FaultException is generated, then the channel is not faulted and session works fine for subsequent method calls.

These are things I have noted till now working with WCF sessions.I need to check how exactly message correlation is done by checking the traces.I will discuss that in my next post.

Comments
  1. Yogesh Goel says:

    Hey,

    Here is my write up for the Kolkata Bloggers Meet – 21/09/08.

    The url is
    http://yogeshgoel.blogspot.com/2008/09/kolkata-blogger-meet-my-1st-experience.html

    Do visit and don’t forget to leave in ur feedback on the same.

    Regards n love
    Yogesh
    9433009321
    123net.blogspot.com

  2. Ahmed M. Gamil says:

    Well, Thank You very much Yogesh for sharing this valuable information, but I wanted to ask about something ..

    First : about the faulted channel … It came to my mind that reinstantiating the proxy object would solve the problem but for me actually it didn’t work .. To get that clear I’ll show you the code segment:
    try
    { client.GetBestPerformersByPrice(Convert.ToInt32(nud_numberOfRows.Value));
    }
    catch
    {
    client = new StockClient(new InstanceContext(this));
    client.GetBestPerformersByPrice(Convert.ToInt32(nud_numberOfRows.Value));
    }

    but unfortunately it throws another exception with this message:

    Could not connect to net.tcp://localhost:8731/Service1. The connection attempt lasted for a time span of 00:00:01.0625000. TCP error code 10061: No connection could be made because the target machine actively refused it 127.0.0.1:8731.

    I don’t know what to do … Please help .. Thanks in advance

  3. This is quite a up-to-date info. I’ll share it on Delicious.
    p.s. Year One is already on the Internet and you can watch it for free.

  4. lunna says:

    finally I got the right vision of how to implement SessionMode.Required 🙂 thanks a lot.

    and what about IsTerminating, have I mark at least one of the operation, or I can just call Close() method for the channel?

  5. Vinod says:

    Hey Yogesh…
    Thanks, this is a good write-up about WCF session management.

    I want to correct the condition, I believe it should be written as-
    if (proxy!=null && proxy.State == CommunicationState.Opened)
    {
    //call the method
    }
    else
    {
    //Recreate the proxy
    }

  6. asthanarht says:

    nice

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.