• 4. WCF 会话状态


    原文:http://www.rainsts.net/article.asp?id=431

    WCF 会话状态和两个端点(EndPoint)之间的一系列消息交换相关联,它实际上是 "实例上下文(Instance Context)”,控制着服务对象实例的创建方式和生存期。和 ASP.NET Session 有很大不同。

    WCF Session 特点:

    • 由调用程序(Calling Application)发起初始化和终止操作。
    • 由具体的 Binding 类型实现,因此它们之间的细节可能有所不同。
    • 不提供 ASP.NET Session 那样的数据容器。

    启动 Session 的方法包括:

    • 调用 Channel 的 Open 方法。我们可以使用 ChannelFactory 来创建 Channel。
    • 调用客户端代理对象的 Open 方法(ClientBase.Open)。
    • 调用任何允许初始化会话服务方法(缺省情况下所有的服务方法都自动初始化Session,也就是 IsInitiating=true)。

    结束 Session 的方法包括:

    • 调用 Channel 的 Close 方法。
    • 调用客户端代理对象的 Close 方法(ClientBase.Close)。
    • 调用任何包含 "IsTerminating=true" 声明的服务方法(缺省情况下所有的服务方法 IsTerminating=false,需要我们显示声明)。

    要使用 WCF Session,我们一般按如下步骤进行。

    1. 开启服务契约的 Session。

    可以选择的模式包括:Required、Allowed、NotAllowed。Required 表示必须使用 Session,如果 Binding 不支持,则会抛出异常;Allowed 表示如果 Binding 支持 Session 则开启会话;NotAllowed 表示停用 Session。多数 Binding 缺省就会开始 Session,而 BaseHttpBinding 不支持 Session。

    <ServiceContract(SessionMode:=SessionMode.Required)> _
    Public Interface IService1


        
    <OperationContract(isinitiating:=False)> _
        
    Function GetData(ByVal value As IntegerAs String


    End Interface

    2. 使用 ServiceBehaviorAttribute 和 InstanceContextMode 在服务契约的实现类型上指定服务对象的 "实例上下文模式"。

    InstanceContextMode 可选择的方式包括:PerSession、PerCall、Single。PerSession 表示为每个连接(每个客户端代理对象) 创建一个会话(服务对象);PerCall 则为每次调用(Operate)创建一个会话(服务对象);Single 则表示所有的客户端共享一个会话(服务对象)。

    <ServiceBehavior(InstanceContextMode:=InstanceContextMode.PerSession)> _
    Public Class Service1
        
    Implements IService1

        
    Public Function GetData(ByVal value As IntegerAs String Implements IService1.GetData
            Console.WriteLine(OperationContext.Current.SessionId)

            
    Return String.Format("You entered: {0}", value)
        
    End Function

    End Class

    客户端调用:

        Sub Main()

            
    Dim url As String = "http://localhost:8731/Design_Time_Addresses/WcfServiceLibrary1/Service1/mex"

            
    Dim host As New System.ServiceModel.ServiceHost(GetType(WcfServiceLibrary1.Service1))
            host.AddServiceEndpoint(
    GetType(WcfServiceLibrary1.IService1), New System.ServiceModel.WSHttpBinding, url)
            host.Open()
            Console.WriteLine(host.State.ToString)


            
    Dim f As New System.ServiceModel.ChannelFactory(Of WcfServiceLibrary1.IService1)(New System.ServiceModel.WSHttpBinding, url)
            
    Dim s As WcfServiceLibrary1.IService1 = f.CreateChannel

            Console.WriteLine(s.GetData(
    1))
            Console.WriteLine(s.GetData(
    1))
            Console.WriteLine(s.GetData(
    1))


            Console.ReadKey()


        
    End Sub

    输出:

    urn:uuid:e801a8b5-8419-4ec4-bfc7-a850f408a42a

    urn:uuid:e801a8b5-8419-4ec4-bfc7-a850f408a42a

    urn:uuid:e801a8b5-8419-4ec4-bfc7-a850f408a42a

    3. 如果有必要,可以使用 OperationContractAttribute 的 IsInitiating 和 IsTerminating 属性来控制每次调用对 Session 的操控。

    IsInitiating 表示该方法是否可以初始化 Session,IsTerminating 表示该方法是否可以终止 Session。默认设置 IsInitiating=true,IsTerminating=false。

    我们将上面的例子改一下:

    <ServiceContract(SessionMode:=SessionMode.Required)> _
    Public Interface IService1


        
    <OperationContract(isinitiating:=False)> _
        
    Function GetData(ByVal value As IntegerAs String


    End Interface
    客户第一次调用时会出现异常
    ContractDescription“IService1”没有 IsInitiating=true 操作;协定必须至少有一个 IsInitiating=true 操作。
    我们可以增加一个额外的方法来初始化会话,如下。OK,这次没问题了。
    <ServiceContract(SessionMode:=SessionMode.Required)> _
    Public Interface IService1


        
    <OperationContract(isinitiating:=False)> _
        
    Function GetData(ByVal value As IntegerAs String

        
    <OperationContract(isinitiating:=True)> _
        
    Sub Init()



    End Interface
    <ServiceBehavior(InstanceContextMode:=InstanceContextMode.PerSession)> _
    Public Class Service1
        
    Implements IService1


        
    Public Function GetData(ByVal value As IntegerAs String Implements IService1.GetData
            Console.WriteLine(OperationContext.Current.SessionId)
            Debug.WriteLine(OperationContext.Current.SessionId)

            
    Return String.Format("You entered: {0}", value)
        
    End Function

        
    Public Sub Init() Implements IService1.Init

        
    End Sub
    End Class

    客户端

       Sub Main()

            
    Dim url As String = "http://localhost:8731/Design_Time_Addresses/WcfServiceLibrary1/Service1/mex"

            
    Dim host As New System.ServiceModel.ServiceHost(GetType(WcfServiceLibrary1.Service1))
            host.AddServiceEndpoint(
    GetType(WcfServiceLibrary1.IService1), New System.ServiceModel.WSHttpBinding, url)
            host.Open()
            Console.WriteLine(host.State.ToString)


            
    Dim f As New System.ServiceModel.ChannelFactory(Of WcfServiceLibrary1.IService1)(New System.ServiceModel.WSHttpBinding, url)
            
    Dim s As WcfServiceLibrary1.IService1 = f.CreateChannel
            s.Init()  
    '初始化

            Console.WriteLine(s.GetData(
    1))
            Console.WriteLine(s.GetData(
    1))
            Console.WriteLine(s.GetData(
    1))


            Console.ReadKey()


        
    End Sub
    这个示例就到这里了,对于原文有一个地方:
    我们将上面例子改一下。
    [ServiceContract(SessionMode=SessionMode.Required)]
    public interface ICalculate
    {
      [OperationContract(IsTerminating=true)]
      int Add(int a, int b);
    }

    在客户端第二次调用 Add 方法时会抛出异常。
    未处理 System.InvalidOperationException
      Message="This channel cannot send any more messages because IsTerminating operation 'Add' has already been called."
      Source="mscorlib"
      StackTrace:
      Server stack trace: 
        在 System.ServiceModel.Channels.ServiceChannel.PrepareCall(ProxyOperationRuntime operation, Boolean oneway, ProxyRpc& rpc)
        

    我在测试的过程,没有发现这个问题!我用的是vs2008+sp1

  • 相关阅读:
    侯捷STL课程及源码剖析学习1
    路边拾遗之其他模块(struct/csv/xlwt/smtp)
    面向对象之内置方法(简单)、组合。以及接口归一化设计与抽象类
    面向对象之继承与派生
    面向对象之类属性实例属性及其增删改查
    python中常用模块详解二
    函数之命名空间、作用域、闭包、装饰器四剑客。
    文件操作之1,2,3
    python中常用模块详解一
    python内置常用内置方法详解
  • 原文地址:https://www.cnblogs.com/zqonline/p/1605528.html
Copyright © 2020-2023  润新知