Windows Communication Foundation (WCF) 客户端(如 Windows Communication Foundation (WCF) 服务)可配置为修改运行时行为以适应客户端应用程序。 有三个属性可用于指定客户端运行时行为。 双工客户端回调对象可以使用 CallbackBehaviorAttribute 和 CallbackDebugBehavior 属性来修改其运行时行为。 另一个属性 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
。仅在受控调试场景中进行此操作。
下面的代码示例演示了一个客户端配置文件,它指示 WCF 从 SOAP 消息中的客户端回调对象返回托管异常信息。
<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行为指定统一资源标识符,以便为其创建传输通道。 当即时网络目标不是消息的预期处理器时,请使用此行为。 当调用应用程序不一定知道最终目的地或目的地 Via
标头不是地址时,这将允许多跳对话。