在 Windows Communication Foundation (WCF) 應用程式中,會話 將一組訊息關聯成一次對話。 WCF 會話與 ASP.NET 應用程式中提供的會話物件不同,支援不同的行為,並以不同的方式控制。 本主題描述會話在 WCF 應用程式中啟用的功能,以及如何使用這些功能。
Windows Communication Foundation 應用程式中的會話
當服務合約指定它需要會話時,該合約會指定所有呼叫(也就是支援呼叫的基礎訊息交換)都必須是相同交談的一部分。 如果合約指定允許會話,但不需要會話,則用戶端可以連線並建立會話,或不建立會話。 如果會話結束後透過相同的通道傳送訊息,則會拋出例外狀況。
WCF 會話具有以下主要概念性功能:
呼叫端應用程式會明確起始和終止它們(WCF 用戶端)。
會話期間傳遞的訊息會依照接收的順序進行處理。
會話會將一組訊息整合成一個交談。 可能有不同的相互關聯類型。 例如,一個會話型通道可能會根據共用網路連線將訊息相互關聯,而另一個會話型通道可能會根據訊息本文中的共用標記來關聯訊息。 可以從會話衍生的功能取決於相互關聯的性質。
沒有與 WCF 會話相關聯的一般數據存放區。
如果您熟悉 ASP.NET 應用程式中的 System.Web.SessionState.HttpSessionState 類別及其提供的功能,您可能會注意到該會話類型與 WCF 會話之間的下列差異:
ASP.NET 工作階段始終由伺服器起始。
ASP.NET 工作階段是隱含地未經排序。
ASP.NET 工作階段會提供一個跨要求的通用資料儲存機制。
本主題說明:
在服務模型層中使用會話型系結時的預設執行行為。
WCF 會話型、系統提供的系結所提供的功能類型。
如何建立定義會話需求的合約。
如何瞭解及控制會話的建立和終止,以及會話與服務實例的關聯性。
使用會話的預設執行行為
嘗試起始會話的系結稱為 會話型 系結。 服務合約指定他們需要、允許或拒絕會話型系結,是透過在服務合約介面(或類別)上設定 ServiceContractAttribute.SessionMode 屬性為 System.ServiceModel.SessionMode 其中一個列舉值來完成的。 根據預設,這個屬性的值是 Allowed,這表示如果用戶端使用會話型系結搭配WCF服務實作,則服務會建立並使用提供的會話。
當 WCF 服務接受用戶端連線階段時,預設會啟動下列功能:
WCF 用戶端對象之間的所有呼叫都會由相同的服務實例處理。
不同的會話型系結提供額外功能。
System-Provided 工作階段類型
會話型系結支援服務實例與特定會話的默認關聯。 不過,除了啟用先前所述的會話型實例控件之外,不同的會話型系結也支援不同的功能。
WCF 提供下列工作階段型應用程式行為類型:
System.ServiceModel.Channels.SecurityBindingElement支援以安全性為基礎的會話,其中通訊的兩端都已就特定安全交談達成一致。 如需詳細資訊,請參閱 保護服務。 例如, System.ServiceModel.WSHttpBinding 系結包含安全性會話和可靠會話的支持,預設只會使用加密和數位簽署訊息的安全會話。
系 System.ServiceModel.NetTcpBinding 結支援 TCP/IP 型會話,以確保所有訊息都與套接字層級的連線相互關聯。
實作 WS-ReliableMessaging 規格的 System.ServiceModel.Channels.ReliableSessionBindingElement 元素提供對可靠會話的支持,確保訊息可以按順序且僅傳遞一次,即使在交談期間訊息跨越多個節點傳輸時,也能收到訊息。 如需詳細資訊,請參閱 Reliable Sessions。
System.ServiceModel.NetMsmqBinding 結提供 MSMQ 數據報會話功能。 如需詳細資訊,請參閱 WCF 中的佇列。
SessionMode設定 屬性不會指定合約所需的會話類型,只需要一個。
建立需要會話的合約
建立需要會話的合約,表明服務合約中宣告的所有作業群組必須在同一會話中執行,並且必須按順序傳遞訊息。 若要確認服務合約所需的會話支援層級,請將您服務合約介面或類別上的 ServiceContractAttribute.SessionMode 屬性設定為 System.ServiceModel.SessionMode 列舉的值,以指定合約:
需要會話。
允許用戶端建立會話。
禁止會話。
不過,設定SessionMode屬性並不會指定合約所需的會話行為。 它會指示 WCF 在運行時間確認服務所設定的系結(這會建立通訊通道)在實作服務時是否能夠建立、不能建立或可以建立會話。 同樣地,綁定可以透過它選擇的任何類型的會話型行為來滿足該需求,例如安全性、傳輸、可靠性或其組合。 確切的行為取決於 System.ServiceModel.SessionMode 選取的值。 如果服務的設定系結不符合 SessionMode 的值,則會擲回例外狀況。 系結及其所建立支援會話的通道據說是以會話為基礎。
下列服務合約指定所有 ICalculatorSession
中的作業必須在會話內交換。 除了 Equals
方法之外,其他的作業都不會將值傳回給呼叫端。 不過, Equals
方法不會採用任何參數,因此,只能在會話內傳回非零值,其中數據已傳遞至其他作業。 此合約需要會話才能正常運作。 如果沒有與特定客戶端相關聯的會話,服務實例就無法知道此用戶端先前傳送的數據。
[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required)]
public interface ICalculatorSession
{
[OperationContract(IsOneWay=true)]
void Clear();
[OperationContract(IsOneWay = true)]
void AddTo(double n);
[OperationContract(IsOneWay = true)]
void SubtractFrom(double n);
[OperationContract(IsOneWay = true)]
void MultiplyBy(double n);
[OperationContract(IsOneWay = true)]
void DivideBy(double n);
[OperationContract]
double Equals();
}
<ServiceContract(Namespace:="http://Microsoft.ServiceModel.Samples", SessionMode:=SessionMode.Required)> _
Public Interface ICalculatorSession
<OperationContract(IsOneWay:=True)> _
Sub Clear()
<OperationContract(IsOneWay:=True)> _
Sub AddTo(ByVal n As Double)
<OperationContract(IsOneWay:=True)> _
Sub SubtractFrom(ByVal n As Double)
<OperationContract(IsOneWay:=True)> _
Sub MultiplyBy(ByVal n As Double)
<OperationContract(IsOneWay:=True)> _
Sub DivideBy(ByVal n As Double)
<OperationContract()> _
Function Equal() As Double
End Interface
如果服務允許會話,則會建立會話,並在用戶端起始會話時使用;否則,不會建立任何會話。
會話和服務實例
如果您在 WCF 中使用預設實例行為,WCF 用戶端對象之間的所有呼叫都會由相同的服務實例處理。 因此,在應用層級,您可以將會話視為支援類似本機呼叫行為的應用程式功能。 例如,當您創建一個本地物件時:
呼叫建構函式。
對 WCF 用戶端對象參考進行的所有後續呼叫都會由相同的物件實例處理。
當物件引用被銷毀時,會呼叫解構函式。
只要使用預設服務實例行為,會話就會啟用用戶端與服務之間的類似行為。 如果服務合約需要或支援會話,可以藉由設定 IsInitiating 和 IsTerminating 屬性,將一或多個合約作業標示為起始或終止會話。
起始作業 是必須呼叫為新會話第一個作業的作業。 只有在至少呼叫一個起始作業之後,才能呼叫非起始作業。 因此,您可以宣告一種會話建構函式,透過設計專門用來從客戶端獲取輸入的起始作業,以適應服務實例的開頭。 (不過,狀態與會話相關聯,而不是服務物件。
相反地,終止作業是必須在現有會話中呼叫為最後一則訊息的作業。 在預設案例中,WCF 會在服務相關聯的會話關閉之後,回收服務物件及其內容。 因此,您可以通過宣告結束操作來建立一種解構函式,這些操作旨在執行適合服務實例結尾的功能。
備註
雖然預設行為與本機建構函式和解構函式相似,但它僅只是相似。 任何 WCF 服務作業都可以是起始或終止作業,或同時兩者。 此外,在預設案例中,可以任意次數、順序呼叫啟動作業;除非您明確控制服務實例的存留期(藉由操作 System.ServiceModel.InstanceContext 物件),否則一旦會話建立並與實例建立關聯,就不會建立其他會話。 最後,狀態會與會話相關聯,而不是服務物件。
例如, ICalculatorSession
上述範例中使用的合約會要求 WCF 用戶端對象在呼叫作業之前先呼叫 Clear
作業,而且與這個 WCF 用戶端物件的會話在呼叫 Equals
作業時應該終止。 下列程式代碼範例示範強制執行這些需求的合約。 必須先呼叫 Clear
才能起始會話,而當呼叫 Equals
時該會話便結束。
[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required)]
public interface ICalculatorSession
{
[OperationContract(IsOneWay=true, IsInitiating=true, IsTerminating=false)]
void Clear();
[OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
void AddTo(double n);
[OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
void SubtractFrom(double n);
[OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
void MultiplyBy(double n);
[OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
void DivideBy(double n);
[OperationContract(IsInitiating = false, IsTerminating = true)]
double Equals();
}
<ServiceContract(Namespace:="http://Microsoft.ServiceModel.Samples", SessionMode:=SessionMode.Required)> _
Public Interface ICalculatorSession
<OperationContract(IsOneWay:=True, IsInitiating:=True, IsTerminating:=False)> _
Sub Clear()
<OperationContract(IsOneWay:=True, IsInitiating:=False, IsTerminating:=False)> _
Sub AddTo(ByVal n As Double)
<OperationContract(IsOneWay:=True, IsInitiating:=False, IsTerminating:=False)> _
Sub SubtractFrom(ByVal n As Double)
<OperationContract(IsOneWay:=True, IsInitiating:=False, IsTerminating:=False)> _
Sub MultiplyBy(ByVal n As Double)
<OperationContract(IsOneWay:=True, IsInitiating:=False, IsTerminating:=False)> _
Sub DivideBy(ByVal n As Double)
<OperationContract(IsInitiating:=False, IsTerminating:=True)> _
Function Equal() As Double
End Interface
服務不會啟動用戶端的會話。 在 WCF 用戶端應用程式中,會話型通道的存留期與會話本身的存留期之間存在直接關聯性。 因此,用戶端會藉由建立新的會話型通道來建立新的會話,並依正常方式關閉會話型通道來終止現有的會話。 客戶端開始與服務端點的會話,方法是呼叫以下其中一項指令:
在通過呼叫 ICommunicationObject.Open 所傳回的通道上,使用 ChannelFactory<TChannel>.CreateChannel。
ClientBase<TChannel>.Open 在 ServiceModel 元數據公用程式工具 (Svcutil.exe) 所產生的 WCF 用戶端物件上。
WCF 用戶端物件的任一類型的啟動操作(預設情況下,所有操作皆為啟動)。 呼叫第一個作業時,WCF 用戶端物件會自動開啟通道並起始會話。
用戶端通常透過呼叫以下其中一項方法來結束與服務端點的會話:
在通過呼叫 ICommunicationObject.Close 所傳回的通道上,使用 ChannelFactory<TChannel>.CreateChannel。
ClientBase<TChannel>.Close 在 Svcutil.exe產生的 WCF 用戶端物件上。
WCF 用戶端物件的任一類型終止作業(根據預設,沒有任何作業正在終止;合約必須明確指定終止作業)。 呼叫第一個作業時,WCF 用戶端物件會自動開啟通道並起始會話。
如需範例,請參閱 如何:建立需要會話的服務,以及 預設服務行為 和 實例化 範例。
如需用戶端和會話的詳細資訊,請參閱 使用 WCF 用戶端存取服務。
會話與 InstanceContext 設定互動
契約中的SessionMode列舉與ServiceBehaviorAttribute.InstanceContextMode屬性之間有互動,該屬性控制通道與特定服務對象之間的關聯。 如需更多資訊,請參閱 工作階段、實例和並行。
共用 InstanceContext 物件
您也可以自行執行該關聯,來控制哪些會話型通道或呼叫與哪個 InstanceContext 對象相關聯。
會話和串流
當您需要傳輸大量數據時,WCF 中的串流傳輸模式是一種可行的替代方式,以取代在記憶體中緩衝和處理訊息的預設行為。 使用會話型系結進行串流呼叫時,您可能會收到非預期的行為。 所有串流呼叫都是透過不支援會話的單一通道(數據報通道)進行,即使所使用的系結設定為使用會話也一樣。 如果多個用戶端透過會話型系結對相同的服務對象進行串流呼叫,且服務物件的並行模式設定為單一,且其實例內容模式設定 PerSession
為 ,則所有呼叫都必須經過數據報通道,因此一次只會處理一個呼叫。 然後,一或多個用戶端可能會逾時。您可以將服務對象的 InstanceContextMode
設定為 PerCall
或將並行設為多個,來解決此問題。
備註
在這種情況下,MaxConcurrentSessions 沒有任何影響,因為只有一個「會話」可用。