Wednesday, March 7, 2012

WCF Sessions in depth

How session works in WCF?
First of all it is different from ASP.Net.
  • ASP.NET sessions are always server-initiated.(WCF session is caller initated)
  • ASP.NET sessions are implicitly unordered(WCF session is processed in the order of reception)
  • ASP.NET sessions provide a general data storage mechanism across requests(not in WCF session except 'durable services')
In ASP.Net you can access session very easily

1) In config: <configuration>
  <sessionstate
      mode="inproc" />
1) and then in code : Session("Stocks") = "MSFT; VRSN; GE"

But in WCF, to manage sessions, we should learn about some concepts:
1) There is an attribute to enable session(SessionMode)
2) We should manage instancing ourselves (which is there for an entirely different purpose)
3) Instancing is related to binding, so we should learn about supporting bindings
4) We might even need to control the execution threads(concurrency)

Say a request comes for the first time in this URL http://someservice/function
then the follwing steps happen
1) an InstanceContext class is created
2) InstanceContext loads the appropriate class associated with the service(service instance)

Tip:The MaxConcurrentInstances(service behaviour) property specifies the maximum number of InstanceContext objects in the service.
When 50 calls come then all the existing InstanceContexts will be used and others will be created instantly
a) So 50 request = 50 InstanceContext + corresponding 50 service instance
      This is called PerCall
b) If for these 50 requests the service identifies the client and always serves it by a dedicated service object, then this type of service will be known as PerSession service as it recognizes the client and serves it by a single instance of service object.
 So 50 request = 1 InstanceContext + 1 service instance
          or
       50 request from one client + 25 request from another client = 2 instanceContext + 2 service instance.
c) if all the requests irrespective of client are served by a single instance of service objects, then the service will be known as Single service
  So 50 request from one client + 25 requests from another client = 1 InstanceContext + 1 service instance

It is worth noting there is an operationBehavior called ReleaseInstanceMode. We should not be bothered about it for now as by default instanceContextMode is taken in to consideration by WCF.
Tip 2: So based on the tip I had given earlier If InstanceContextMode is PerSession, the resulting value of MaxConcurrentInstances is the total number of sessions. And PerCall= number of concurrent calls. If a message arrives while the maximum number of InstanceContext objects already exist, the message is held until an InstanceContext object closes.

To configure sessions in WCF, one should know the following three elements:
1) InstanceContextMode
PerCall , PerSession and Single appears in WCF as service behaviour called InstanceContextMode

2) SessionMode
service contract has a session mode property with the following 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) Binding
Another thing to keep in mind is that all bindings do not support sessions. Only WS-*, NetTcpBinding and NetNamedPipeBinding have session support so selection of appropriate binding is necessary

Let me try to confuse you: if you want asp.net like sessions with cookies then use BasicHttpContextBinding

SessionID
Both client and server has sessionID. When session is enabled these sessionIDs are the same.
string sessionId = OperationContext.Current.SessionId; //server
string sessionId = proxy.InnerChannel.SessionId;///client
string sessionId2 = proxy2.InnerChannel.SessionId;///client (different session id for every proxy/client)

When it is percall there still exists session ID but with null value

you can test this yourself by letting a service method pass the session id and comparing it at client.

Let’s consolidate this. First a suitable binding should be there which makes the ground to support the session. Then SessionMode of service contract should be supportive so that service could allow session based requests and at last InstanceContextMode should be configured such that it responds in a session based manner

Another aspect worth noting is ConcurrenyMode property in ServiceBehavior. If the InstanceContextMode value is set to Single the result is that your service can only process one message at a time(we learned this) unless you also set the ConcurrencyMode value to Multiple(multi-threading). Concurrency is the term given to the control of the number of threads executing in an InstanceContext at the same time

So after learning everything about sessions wouldn't it be annoying to see some other attributes about session else where in WCF?
Yes! I am talking about the two other service behavior attributes

1) AutomaticSessionShutdown
Specifies whether to automatically close a session when a client closes an output session.
2) TransactionAutoCompleteOnSessionClose
Gets or sets a value that specifies whether pending transactions are completed when the current session closes without error.

Relationship with transactions
Only a service with a session can set TransactionAutoComplete to false.
And lastly don't forget to check out my blog on Durable Services to overcome the limitations of sessions in WCF.

Oops! we missed something.. WCF su rocks! It is Reliable Sessions, which supports reliable messaging.
Reliable messaging retries communication on failure and allows delivery assurance. Sessions maintain state for clients between calls. We can implement it like this:
<bindings>
    <wsHttpBinding>
        <binding name="Binding1">
            <reliableSession enabled="true" ordered="true" />
        </binding>
    </wsHttpBinding>
</bindings>

'ordered' is optional and is used to specify the order of arrival of messages(the way they are sent).
To make sure only clients that support reliable messaging access the service, do this:
[ServiceContract(SessionMode=SessionMode.Required)]

And lastly, there is something called ssl sessions which is different from wcf session. (you may also bing establishSecurityContext =false setting to learn more)

Exam Tip:
  • SessionMode is a service contract
  • InstanceContextMode,AutomaticSessionShutdown and TransactionAutoCompleteOnSessionClose are service behaviours (ConcurrenyMode as well)
  • reliableSession is a binding element
 ---The End-- comment your thoughts please

No comments:

Post a Comment