使用wsHttpBinding时,为什么InstanceContextMode.PerSession的行为与PerCall类似?

Dor*_*hen 8 ajax wcf soap wshttpbinding wcf-sessions

我有使用SOAP 1.2的AJAX客户端使用的WCF服务

Web.config文件:

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

<wsHttpBinding>
  <binding name="wsHttpBin">
    <security mode="None"/>          
  </binding>
</wsHttpBinding>
Run Code Online (Sandbox Code Playgroud)

根据我的阅读,我必须使用,<security mode="None"/>因为使用"wsHttpBinding"绑定公开的服务实现了WS-*Web服务规范系列的WS-Security.由于绑定使用安全性,因此请求将被拒绝,因为AJAX不支持安全上下文.

我的WCF服务行为定义为InstanceContextMode.PerSession:

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, 
                 InstanceContextMode = InstanceContextMode.PerSession)]
Run Code Online (Sandbox Code Playgroud)

但是当我使用它时,该服务表现为PerCall,并且每次调用都会启动一个新的WCF实例,而不是使用当前实例.

使用wsHttpBinding时,为什么InstanceContextMode.PerSession的行为与PerCall类似?

我能做什么?

All*_*nek 4

通过 HTTP 使用会话时,仅当使用安全会话或可靠会话时,WCF 才支持会话。如果你都不能使用,那么你必须自己实现会话机制。如果你同时控制客户端和服务器端,那就很容易做到了。就是这样:

创建一个类来保存您需要存储的所有会话数据(我们称之为),以及上次使用会话时的SessionData附加数据。DateTime然后添加到您的服务类(或任何其他类)中static ConcurrentDictionary<string, SessionData>

当客户端调用您的服务时,要求它传递标识会话的唯一字符串(可以在客户端随机生成)。每当客户端调用您的服务时,请在字典中查找会话字符串并检索会话数据(并根据需要更新其内容)。如果不存在,则在字典中创建一个新条目。此外,每次访问该SessionData对象时,请将“上次使用”更新DateTime为当前时间。后台任务应定期清除一段时间未使用的旧会话。

就是这样 - 您已经自己实现了会话。您现在可以使用 WCF InstanceContextMode.Single,而不必担心 WCF 在每个会话中正确创建服务类的实例。

编辑:如果您使用 .NET 4.5 编写 WCF 服务,并且您的 Web 应用程序仅针对现代浏览器,则可以NetHttpBinding在服务器端使用,在客户端使用 WebSocket。NetHttpBinding支持会话(当指定时SessionMode.Required)。