WCF會話狀態功能特點解析
WCF是一個.NET Framework 3.5的重要組成部件,可以幫助我們成功創建出一個安全性強的開發解決方案。我們在這里會為大家介紹一下WCF會話狀態的相關概念。WCF會話狀態和兩個端點(EndPoint)之間的一系列消息交換相關聯,它實際上是 "實例上下文(Instance Context)”,控制著服務對象實例的創建方式和生存期。和 ASP.NET Session 有很大不同。#t#
WCF會話狀態特點:
由調用程序(Calling Application)發起初始化和終止操作。
由具體的 Binding 類型實現,因此它們之間的細節可能有所不同。
不提供 ASP.NET Session 那樣的數據容器。
啟動WCF會話狀態的方法包括:
調用 Channel 的 Open 方法。我們可以使用 ChannelFactory 來創建 Channel。
調用客戶端代理對象的 Open 方法(ClientBase.Open)。
調用任何允許初始化會話服務方法(缺省情況下所有的服務方法都自動初始化Session,也就是 IsInitiating=true)。
結束WCF會話狀態的方法包括:
調用 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(SessionModeSessionMode:=SessionMode.Required)> _
- Public Interface IService1
- < OperationContract(isinitiating:=False)> _
- Function GetData(ByVal value As Integer) As String
- End Interface
2. 使用 ServiceBehaviorAttribute 和 InstanceContextMode 在服務契約的實現類型上指定服務對象的 "實例上下文模式"。
InstanceContextMode 可選擇的方式包括:PerSession、PerCall、Single。PerSession 表示為每個連接(每個客戶端代理對象) 創建一個會話(服務對象);PerCall 則為每次調用(Operate)創建一個會話(服務對象);Single 則表示所有的客戶端共享一個會話(服務對象)。
- < ServiceBehavior(InstanceContextModeInstanceContextMode:
=InstanceContextMode.PerSession)> _- Public Class Service1
- Implements IService1
- Public Function GetData(ByVal value As Integer) As 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 屬性來控制每次調用對WCF會話狀態的操控。
IsInitiating 表示該方法是否可以初始化 Session,IsTerminating 表示該方法是否可以終止 Session。默認設置 IsInitiating=true,IsTerminating=false。
我們將上面的例子改一下:
- < ServiceContract(SessionModeSessionMode:=SessionMode.Required)> _
- Public Interface IService1
- < OperationContract(isinitiating:=False)> _
- Function GetData(ByVal value As Integer) As String
- End Interface
客戶第一次調用時會出現異常
ContractDescription“IService1”沒有 IsInitiating=true 操作;協定必須至少有一個 IsInitiating=true 操作。
我們可以增加一個額外的方法來初始化會話,如下。OK,這次沒問題了。
- < ServiceContract(SessionModeSessionMode:=SessionMode.Required)> _
- Public Interface IService1
- < OperationContract(isinitiating:=False)> _
- Function GetData(ByVal value As Integer) As String
- < OperationContract(isinitiating:=True)> _
- Sub Init()
- End Interface
- < ServiceBehavior(InstanceContextModeInstanceContextMode
:=InstanceContextMode.PerSession)> _- Public Class Service1
- Implements IService1
- Public Function GetData(ByVal value As Integer)
As 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(SessionModeSessionMode=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
以上就是對WCF會話狀態的相關介紹。