Angeben des Clientlaufzeitverhaltens

Windows Communication Foundation (WCF)-Clients wie Windows Communication Foundation (WCF)-Dienste können so konfiguriert werden, dass das Laufzeitverhalten an die Clientanwendung angepasst wird. Drei Attribute sind zum Angeben des Clientlaufzeitverhaltens verfügbar. Duplexclient-Rückrufobjekte können das CallbackBehaviorAttribute-Attribut und das CallbackDebugBehavior-Attribut verwenden, um ihr Laufzeitverhalten zu ändern. Das andere Attribut, ClientViaBehavior, kann verwendet werden, um das logische Ziel vom unmittelbaren Netzwerkziel zu trennen. Außerdem können Duplexclient-Rückruftypen Teile des Dienstseitenverhaltens verwenden. Weitere Informationen finden Sie unter Angeben des Dienst-Run-Time-Verhaltens.

Verwenden des CallbackBehaviorAttribute

Sie können das Ausführungsverhalten einer Rückrufvertragsimplementierung in einer Clientanwendung mit der CallbackBehaviorAttribute-Klasse konfigurieren oder erweitern. Dieses Attribut führt eine ähnliche Funktion für die Rückrufklasse wie die ServiceBehaviorAttribute-Klasse aus, das Instanziieren von Verhaltens- und Transaktionseinstellungen ausgenommen.

Die CallbackBehaviorAttribute-Klasse muss auf die Klasse angewendet werden, die den Rückrufvertrag implementiert. Beim Anwenden auf eine Nicht-Duplex-Vertragsimplementierung wird zur Laufzeit eine InvalidOperationException-Ausnahme ausgelöst. Das folgende Codebeispiel zeigt eine CallbackBehaviorAttribute-Klasse für ein Rückrufobjekt, das das SynchronizationContext-Objekt zur Bestimmung des Threads für das Marshallen verwendet, die ValidateMustUnderstand-Eigenschaft zum Erzwingen der Nachrichtenvalidierung und die IncludeExceptionDetailInFaults-Eigenschaft zum Zurückgeben von Ausnahmen als FaultException-Objekte an den Dienst zum Debuggen.

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

Verwenden von CallbackDebugBehavior zum Aktivieren des Flusses verwalteter Ausnahmeinformationen

Sie können den Fluss verwalteter Ausnahmeinformationen in einem Client-Rückrufobjekt zurück zum Dienst zum Debuggen aktivieren, indem Sie die IncludeExceptionDetailInFaults-Eigenschaft entweder programmgesteuert oder aus einer Anwendungskonfigurationsdatei auf true festlegen.

Verwaltete Ausnahmeinformationen an Dienste zurückzugeben, kann ein Sicherheitsrisiko darstellen, da Ausnahmedetails Informationen zur internen Clientimplementierung offen legen, die von nicht autorisierten Diensten verwendet werden können. Außerdem wird, obwohl die CallbackDebugBehavior-Eigenschaften auch programmgesteuert festgelegt werden können, bei der Bereitstellung das Deaktivieren von IncludeExceptionDetailInFaults schnell vergessen.

Wegen der damit verbundenen Sicherheitsprobleme wird Folgendes dringend empfohlen:

  • Verwenden Sie eine Anwendungskonfigurationsdatei, um den Wert der IncludeExceptionDetailInFaults-Eigenschaft auf true festzulegen.

  • Führen Sie diesen Vorgang nur in gesteuerten Debugszenarien aus.

Das folgende Codebeispiel zeigt eine Clientkonfigurationsdatei, die WCF anweist, verwaltete Ausnahmeinformationen aus einem Client-Rückrufobjekt in SOAP-Nachrichten zurückzugeben.

  <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>

Verwenden des ClientViaBehavior-Verhaltens

Sie können mit dem ClientViaBehavior-Verhalten den URI (Uniform Resource Identifier) angeben, für den der Transportkanal erstellt werden soll. Verwenden Sie dieses Verhalten, wenn das unmittelbare Netzwerkziel nicht der gewünschte Prozessor der Nachricht ist. Dies ermöglicht Konversationen über mehrere Hops, wenn die aufrufende Anwendung das endgültige Ziel nicht unbedingt kennt oder wenn der Via-Header des Ziels keine Adresse ist.

Siehe auch