Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why InstanceContextMode.PerSession behave like PerCall when using wsHttpBinding?

I have WCF service consumed by AJAX client using SOAP 1.2

Web.config:

<endpoint address="" binding="wsHttpBinding" 
contract="WcfService1.IService1" bindingConfiguration="wsHttpBin">

<wsHttpBinding>
  <binding name="wsHttpBin">
    <security mode="None"/>          
  </binding>
</wsHttpBinding>

From what I have read, I have to use <security mode="None"/> since a service exposed with “wsHttpBinding” binding implements WS-Security of WS-* family of web service specifications. As the binding uses security, the request will be rejected since AJAX doesn't support the security context.

My WCF service behavior is defined with InstanceContextMode.PerSession:

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, 
                 InstanceContextMode = InstanceContextMode.PerSession)]

but when I consume it, the service behave as PerCall and every call starts a new WCF instance instead of using the current instance.

Why InstanceContextMode.PerSession behave like PerCall when using wsHttpBinding?

What can I do?

like image 897
Dor Cohen Avatar asked Dec 06 '12 14:12

Dor Cohen


1 Answers

Sessions, when used over HTTP, are only supported by WCF when using security sessions or reliable sessions. If you can't use either then you have to implement a session mechanism by yourself. If you control both the client and the server side, it would be quite easy to do it. Here's how:

Create a class that holds all the session data you need stored (let's call it SessionData), plus an additional DateTime for when the session was last used. Then add to your service class (or any other class) a static ConcurrentDictionary<string, SessionData>.

When a client makes a call to your service, require it to pass a unique string that identifies the session (it can be randomly generated on the client side). Whenever a client calls you service, look up the session string in the dictionary and retrieve the session data (and update its content as needed). If it doesn't exist, create a new entry in the dictionary. Also, every time you access the SessionData object, update the 'last used' DateTime to the current time. A background task should periodically clear out old sessions that haven't been used in a while.

That's it - you've implemented sessions on your own. You can now useInstanceContextMode.Single and not worry about WCF correctly creating instances of your service class per session.

EDIT: If you're writing your WCF service with .NET 4.5 and you web application only targets modern browsers, you can use NetHttpBinding on the server side and WebSocket on the client side. NetHttpBinding supports session (when specifying SessionMode.Required).

like image 132
Allon Guralnek Avatar answered Sep 28 '22 22:09

Allon Guralnek