クライアントのランタイム動作の指定
Windows Communication Foundation (WCF) クライアントは、Windows Communication Foundation (WCF) サービスと同様に、クライアント アプリケーションに合わせてランタイム動作を変更するように構成できます。 クライアントのランタイム動作を指定する際には、3 つの属性を使用できます。 双方向クライアント コールバック オブジェクトは、CallbackBehaviorAttribute 属性と CallbackDebugBehavior 属性を使用して、そのランタイム動作を変更できます。 もう 1 つの属性 ClientViaBehavior は、論理送信先を直接のネットワーク送信先と区別するために使用できます。 さらに、双方向クライアントのコールバック型では、サービス側の動作の一部を使用できます。 詳細については、「サービスのランタイム動作の指定」を参照してください。
CallbackBehaviorAttribute の使用
CallbackBehaviorAttribute クラスを使用して、クライアント アプリケーションのコールバック コントラクト実装の実行動作を構成または拡張できます。 この属性は、インスタンス化動作とトランザクションの設定を除き、ServiceBehaviorAttribute クラスと同様の機能をコールバック クラスに対して実行します。
CallbackBehaviorAttribute クラスは、コールバック コントラクトを実装するクラスに適用する必要があります。 双方向以外のコントラクト実装に適用した場合は、実行時に InvalidOperationException 例外がスローされます。 CallbackBehaviorAttribute オブジェクトを使用してマーシャリングするスレッドを決定するコールバック オブジェクトの SynchronizationContext クラス、メッセージ検証を実施する ValidateMustUnderstand プロパティ、およびデバッグのために例外を IncludeExceptionDetailInFaults オブジェクトとしてサービスに返す FaultException プロパティのコード例を次に示します。
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Threading;
namespace Microsoft.WCF.Documentation
{
[CallbackBehaviorAttribute(
IncludeExceptionDetailInFaults= true,
UseSynchronizationContext=true,
ValidateMustUnderstand=true
)]
public class Client : SampleDuplexHelloCallback
{
AutoResetEvent waitHandle;
public Client()
{
waitHandle = new AutoResetEvent(false);
}
public void Run()
{
// Picks up configuration from the configuration file.
SampleDuplexHelloClient wcfClient
= new SampleDuplexHelloClient(new InstanceContext(this), "WSDualHttpBinding_SampleDuplexHello");
try
{
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("Enter a greeting to send and press ENTER: ");
Console.Write(">>> ");
Console.ForegroundColor = ConsoleColor.Green;
string greeting = Console.ReadLine();
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("Called service with: \r\n\t" + greeting);
wcfClient.Hello(greeting);
Console.WriteLine("Execution passes service call and moves to the WaitHandle.");
this.waitHandle.WaitOne();
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine("Set was called.");
Console.Write("Press ");
Console.ForegroundColor = ConsoleColor.Red;
Console.Write("ENTER");
Console.ForegroundColor = ConsoleColor.Blue;
Console.Write(" to exit...");
Console.ReadLine();
}
catch (TimeoutException timeProblem)
{
Console.WriteLine("The service operation timed out. " + timeProblem.Message);
Console.ReadLine();
}
catch (CommunicationException commProblem)
{
Console.WriteLine("There was a communication problem. " + commProblem.Message);
Console.ReadLine();
}
}
public static void Main()
{
Client client = new Client();
client.Run();
}
public void Reply(string response)
{
Console.WriteLine("Received output.");
Console.WriteLine("\r\n\t" + response);
this.waitHandle.Set();
}
}
}
Imports System.ServiceModel
Imports System.ServiceModel.Channels
Imports System.Threading
Namespace Microsoft.WCF.Documentation
<CallbackBehaviorAttribute(IncludeExceptionDetailInFaults:=True, UseSynchronizationContext:=True, ValidateMustUnderstand:=True)> _
Public Class Client
Implements SampleDuplexHelloCallback
Private waitHandle As AutoResetEvent
Public Sub New()
waitHandle = New AutoResetEvent(False)
End Sub
Public Sub Run()
' Picks up configuration from the configuration file.
Dim wcfClient As New SampleDuplexHelloClient(New InstanceContext(Me), "WSDualHttpBinding_SampleDuplexHello")
Try
Console.ForegroundColor = ConsoleColor.White
Console.WriteLine("Enter a greeting to send and press ENTER: ")
Console.Write(">>> ")
Console.ForegroundColor = ConsoleColor.Green
Dim greeting As String = Console.ReadLine()
Console.ForegroundColor = ConsoleColor.White
Console.WriteLine("Called service with: " & Constants.vbCrLf & Constants.vbTab & greeting)
wcfClient.Hello(greeting)
Console.WriteLine("Execution passes service call and moves to the WaitHandle.")
Me.waitHandle.WaitOne()
Console.ForegroundColor = ConsoleColor.Blue
Console.WriteLine("Set was called.")
Console.Write("Press ")
Console.ForegroundColor = ConsoleColor.Red
Console.Write("ENTER")
Console.ForegroundColor = ConsoleColor.Blue
Console.Write(" to exit...")
Console.ReadLine()
Catch timeProblem As TimeoutException
Console.WriteLine("The service operation timed out. " & timeProblem.Message)
Console.ReadLine()
Catch commProblem As CommunicationException
Console.WriteLine("There was a communication problem. " & commProblem.Message)
Console.ReadLine()
End Try
End Sub
Public Shared Sub Main()
Dim client As New Client()
client.Run()
End Sub
Public Sub Reply(ByVal response As String) Implements SampleDuplexHelloCallback.Reply
Console.WriteLine("Received output.")
Console.WriteLine(Constants.vbCrLf & Constants.vbTab & response)
Me.waitHandle.Set()
End Sub
End Class
End Namespace
CallbackDebugBehavior を使用したマネージド例外情報のフローの有効化
アプリケーション構成ファイルまたはプログラムで、IncludeExceptionDetailInFaults プロパティを true
に設定すると、デバッグのためにクライアント コールバック オブジェクト内のマネージド例外情報をサービスに戻すフローを有効にできます。
マネージド例外情報をサービスに戻すのは、セキュリティ リスクになるおそれがあります。これは、例外の詳細により、非承認のサービスで使用可能な内部クライアントの実装についての情報が公開されるからです。 さらに、CallbackDebugBehavior プロパティをプログラムで設定することはできますが、配置するときに IncludeExceptionDetailInFaults を無効にすることを忘れがちになります。
セキュリティの問題にかかわるので、以下を強くお勧めします。
IncludeExceptionDetailInFaults プロパティの値を
true
に設定するには、アプリケーション構成ファイルを使用します。これは、制御されたデバッグ シナリオの場合に限って行います。
SOAP メッセージのクライアント コールバック オブジェクトからマネージド例外情報を返すように WCF に指示するクライアント構成ファイルを次のコード例に示します。
<client>
<endpoint
address="http://localhost:8080/DuplexHello"
binding="wsDualHttpBinding"
bindingConfiguration="WSDualHttpBinding_SampleDuplexHello"
contract="SampleDuplexHello"
name="WSDualHttpBinding_SampleDuplexHello"
behaviorConfiguration="enableCallbackDebug">
</endpoint>
</client>
<behaviors>
<endpointBehaviors>
<behavior name="enableCallbackDebug">
<callbackDebug includeExceptionDetailInFaults="true"/>
</behavior>
</endpointBehaviors>
</behaviors>
ClientViaBehavior 動作の使用
ClientViaBehavior 動作を使用して、トランスポート チャネルを作成する対象の URI (Uniform Resource Identifier) を指定できます。 この動作は、直接のネットワーク送信先が、メッセージの処理先と異なる場合に使用します。 これにより、呼び出し側のアプリケーションが最終的な送信先を知っているとは限らないとき、または送信先の Via
ヘッダーがアドレスでないときに、複数のホップを経由するメッセージ交換が可能になります。