【问题标题】:Why InstanceContextMode.PerSession behave like PerCall when using wsHttpBinding?为什么使用 wsHttpBinding 时 InstanceContextMode.PerSession 的行为类似于 PerCall?
【发布时间】:2012-12-06 14:52:53
【问题描述】:

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

Web.config:

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

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

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

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

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

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

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

我能做什么?

【问题讨论】:

  • @ErnieL 谢谢,但使用 对我来说不是一个选项,因为它不适用于我的 AJAX 客户端。
  • wsHttpBinding 本身不支持会话。
  • @ErnieL 那么我该怎么做才能从 Ajax 使用 Wcf 并使用会话?

标签: ajax wcf soap wshttpbinding wcf-sessions


【解决方案1】:

通过 HTTP 使用的会话仅在使用安全会话或可靠会话时受 WCF 支持。如果你不能使用,那么你必须自己实现一个会话机制。如果您同时控制客户端和服务器端,那将很容易做到。方法如下:

创建一个包含您需要存储的所有会话数据的类(我们称之为SessionData),加上一个额外的DateTime,用于表示上次使用会话的时间。然后将staticConcurrentDictionary&lt;string, SessionData&gt; 添加到您的服务类(或任何其他类)中。

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

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

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

【讨论】:

  • +1:并不是说您的建议一开始就有缺陷,而是要实施生产就绪的会话机制,需要考虑或处理一大堆问题:例如会话劫持(意外或故意)、对您的应用程序有意义的实际会话超时、会话(数据)持久性/弹性,以防服务器重新启动(计划内或计划外/崩溃)、多个并发请求对会话(数据)的并发修改等。
  • @Christian.K:非常正确。我不相信最后两件事是由 WCF 提供的。安全确实是一个需要考虑的问题,至于线程安全,我假设每个客户端都会生成一个唯一的会话密钥,并且在任何给定时间最多会执行一次对服务的调用,但如果不是这样的话,线程安全和正确性也需要注意。
  • @AllonGuralnek 没有使用 InstanceContextMode.Single 会对我的性能产生重大影响吗?
  • @Dor:如果您使用ConcurrencyMode.Multiple,则不会。无论如何,您的服务应该只使用来自SessionData 对象的数据,因为(如果您不使用Single)任何实例字段都是每次调用的(因此它们也可能是局部变量/参数)。这就是为什么 Single 在你的情况下有意义 - 一切都是本地的或在 SessionData 中,你的服务类的实例是没有意义的。
  • 那么为什么不使用 InstanceContextMode.PerCall 呢?这样我就可以使用静态变量,它会有更好的性能,你觉得呢?
【解决方案2】:

link 为您提供了您需要了解的几乎所有信息(当然,一般来说)。

但要准确。 Msdn 谈到 WCF 会话:

它们由调用显式启动和终止 应用

我必须说,我不知道任何 JS 代码/框架可以让您显式存储打开的 WCF 通信通道以保持您的“会话”处于活动状态。 (您还没有提供您的客户端代码,所以我必须做出一些假设)。 WCF 会话不是“基于 cookie”的。它不像 ASP.NET Web 应用程序那样在浏览器中“开箱即用”。

设置InstanceContextMode.PerSession 使您的 WCF 服务“会话就绪”,但不足以“强制”会话。

【讨论】:

  • ASP.NET 的“基于 cookie”是什么意思?如果我要添加 那么我可以使用它吗?我可以有“开箱即用”的解决方案吗?
猜你喜欢
  • 1970-01-01
  • 2018-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-20
  • 1970-01-01
  • 2017-05-28
相关资源
最近更新 更多