Why InstanceContextMode.PerSession behave like Per

2019-04-24 12:31发布

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?

2条回答
姐就是有狂的资本
2楼-- · 2019-04-24 13:20

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).

查看更多
The star\"
3楼-- · 2019-04-24 13:20

This link gives You pretty much all You need to know about this (in general of course).

But to precise. Msdn says about WCF session:

They are explicitly initiated and terminated by the calling application

I must say that I don't know about any JS code/framework that would allow You to store explicitly opened WCF communication channel to keep Your "session" alive. (You haven't provided your client code so I must make some assumptions). WCF session is not "cookie-based". It doesn't work "out of the box" from your browser like it would for ASP.NET web application.

Setting InstanceContextMode.PerSession makes Your WCF service "session-ready" but it is not enough to "force" a session.

查看更多
登录 后发表回答