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 要素は、メッセージを順番に 1 回だけ配信するように構成できる信頼できるセッションのサポートを提供し、メッセージが会話中に複数のノード間を移動した場合でもメッセージを確実に受信できるようにします。 詳細については、「 信頼できるセッション」を参照してください。
System.ServiceModel.NetMsmqBinding バインディングは、MSMQ データグラム セッションを提供します。 詳細については、「 WCF のキュー」を参照してください。
SessionMode プロパティを設定しても、コントラクトに必要なセッションの種類は指定されず、必要なものだけが指定されます。
セッションを必要とするコントラクトの作成
セッションを必要とするコントラクトを作成すると、サービス コントラクトが宣言する操作のグループはすべて同じセッション内で実行する必要があり、メッセージを順番に配信する必要があることを示します。 サービス コントラクトが必要とするセッションのサポート レベルをアサートするには、サービス コントラクト インターフェイスまたはクラスの ServiceContractAttribute.SessionMode プロパティを System.ServiceModel.SessionMode 列挙値に設定して以下を指定します。
セッションが必要です。
クライアントがセッションを確立できるようにします。
セッションを禁止します。
ただし、 SessionMode プロパティを設定しても、コントラクトに必要なセッション ベースの動作の種類は指定されません。 WCF は、サービスの構成されたバインディング (通信チャネルを作成する) が、サービスを実装するときにセッションを確立したり、確立したりしないことを実行時に確認するように指示します。 ここでも、バインディングは、選択した任意の種類のセッション ベースの動作 (セキュリティ、トランスポート、信頼性、またはいくつかの組み合わせ) でその要件を満たすことができます。 正確な動作は、選択した System.ServiceModel.SessionMode 値によって異なります。 構成されたサービスのバインドが SessionModeの値に準拠していない場合は、例外がスローされます。 セッションをサポートするバインディングと、それによって作成されるチャネルは、セッションベースであると言われています。
次のサービス コントラクトは、 ICalculatorSession
内のすべての操作をセッション内で交換する必要があることを指定します。
Equals
メソッドを除き、どの操作も呼び出し元に値を返しません。 ただし、 Equals
メソッドはパラメーターを受け取らないため、他の操作に既にデータが渡されているセッション内でのみ 0 以外の値を返すことができます。 このコントラクトでは、セッションが正常に機能する必要があります。 セッションが特定のクライアントに関連付けられていない場合、サービス インスタンスは、このクライアントが送信した以前のデータを把握する方法がありません。
[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 クライアント オブジェクト参照に対する後続の呼び出しはすべて、同じオブジェクト インスタンスによって処理されます。
デストラクターは、オブジェクト参照が破棄されるときに呼び出されます。
セッションでは、既定のサービス インスタンスの動作が使用されている限り、クライアントとサービスの間で同様の動作が有効になります。 サービス コントラクトでセッションが必要またはサポートされている場合、1 つ以上のコントラクト操作は、 IsInitiating プロパティと IsTerminating プロパティを設定することで、セッションの開始または終了としてマークできます。
開始操作 は、新しいセッションの最初の操作として呼び出す必要がある操作です。 非開始操作は、少なくとも 1 つの開始操作が呼び出された後にのみ呼び出すことができます。 そのため、サービス インスタンスの先頭に適したクライアントからの入力を受け取るように設計された開始操作を宣言することで、サービスの一種のセッション コンストラクターを作成できます。 (ただし、状態は、サービス オブジェクトではなく、セッションに関連付けられています)。
逆に、終了操作は、既存のセッションで最後のメッセージとして呼び出す必要がある操作です。 既定のケースでは、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
に設定した場合、すべての呼び出しはデータグラム チャネルを通過する必要があるため、一度に処理される呼び出しは 1 つだけです。 その後、1 つ以上のクライアントがタイムアウトになる可能性があります。この問題を回避するには、サービス オブジェクトの InstanceContextMode
を PerCall
に設定するか、コンカレンシーを複数に設定します。
注
MaxConcurrentSessions は、使用可能な "セッション" が 1 つしかないため、この場合は効果がありません。