WCF 同一个代理共享全局变量

我们用VS默认创建一个WCF服务,定义一个全局变量,如

private string _appName = string.Empty; 

假如我们在服务端创建两个方法,第一个方法给_appName赋值,第二个方法读取_appName:

 public void SetValue(string name)
        {
            _appName = name;
        }
        public string GetValue()
        {
            return _appName;
        }

同样,用VS创建一个代理来调用这个服务,先赋值再取值

NServices.LogServiceClient client = new NServices.LogServiceClient();
            client.SetValue("OK");
            string s = client.GetValue();

 这时,我们发现,调用GetValue方法的返回值竟然是空的!!!这是怎么回事?

问了园子里的大牛Artech,答曰:采用PerSession实例化模式 + 开启Session + 采用支持Session的绑定

于是,自己就逐个击破。

服务有三种实例模式:分别是PerSession、PerCall、Single ,关于这些模式的区别可以看这篇文

http://www.cnblogs.com/tyb1222/archive/2012/10/12/2721252.html

其实服务的默认模式就是PerSession,要显示的将服务改PerSession模式成只要在服务的类前面加一个

 [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]

默认情况下,服务也是会启动会话的,显示的做法则在每个方法接口前加下面这两个属性:

[OperationContract(IsTerminating = false, IsInitiating = true)] 

所以,罪魁祸首还是服务的绑定。

VS自建的默认服务绑定是basicHttpBinding ,而basicHttpBinding不支持会话。所以,每调用一次方法完成后,会话都会结束掉,调用另一个方法又要重新实例化。

 关于哪些绑定支持会话,可以看这篇文章:http://www.cnblogs.com/jillzhang/archive/2008/02/03/1063406.html,里面有一个很全面直观的表。

要让服务支持会话,要称在服务接口中加一个属性:

 [ServiceContract(SessionMode=SessionMode.Required,Name="LogServices")]
    public interface ILogService
   {}

然后再修改服务的配置文件:

<system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="metadataBehavior">
          <!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false 并删除上面的元数据终结点 -->
          <serviceMetadata httpGetEnabled="true" />
          <!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息 -->
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="metadataBehavior" name="LogServices.LogService">
        <endpoint  binding="wsHttpBinding" 
                  contract="LogServices.ILogService" /> 
      </service>
    </services>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>

这里我采用的是wsHttpBinding.
这样就成功解决这个问题了。

原文地址:https://www.cnblogs.com/Gyoung/p/2731519.html