Zugreifen auf Dienste mithilfe eines Clients

Clientanwendungen müssen für die Kommunikation mit Diensten WCF-Client- oder Kanalobjekte erstellen, konfigurieren und verwenden. Das Thema Übersicht über den WCF-Client bietet einen Überblick über die Objekte und Schritte zum Erstellen und Verwenden grundlegender Client- und Kanalobjekte.

Dieses Thema bietet ausführlichere Informationen zu Problemen mit Clientanwendungen sowie Client- und Kanalobjekten, die abhängig von Ihrem Szenario hilfreich sein können.

Übersicht

In diesem Thema werden das Verhalten und die Probleme zu Folgendem beschrieben:

  • Kanal- und Sitzungslebensdauer.

  • Behandeln von Ausnahmen.

  • Grundlagen von Blockierungsproblemen.

  • Interaktives Initialisieren von Kanälen.

Kanal- und Sitzungslebensdauer

Windows Communication Foundation (WCF)-Anwendungen umfassen zwei Kategorien von Kanälen, Datagramm und sitzungsbasiert.

Ein Datagrammkanal ist ein Kanal, in dem alle Nachrichten nicht korreliert sind. Auf einem Datagrammkanal ist normalerweise beim Fehlschlagen eines Eingabe- oder Ausgabevorgangs der nächste Vorgang nicht betroffen, und der gleiche Kanal kann wiederverwendet werden. Daher schlagen Datagrammkanäle in der Regel nicht fehl.

Sitzungsbasierte Kanäle sind hingegen Kanäle mit einer Verbindung zum anderen Endpunkt. Nachrichten in einer Sitzung auf einer Seite korrelieren immer mit der gleichen Sitzung auf der anderen Seite. Außerdem müssen sich beide Teilnehmer einer Sitzung einigen, dass die Anforderungen ihrer Konversation erfüllt wurden, damit diese Sitzung als erfolgreich gilt. Wenn sie sich nicht einigen können, kann der sitzungsbasierte Kanal fehlschlagen.

Öffnen Sie Clients explizit oder implizit, indem Sie den ersten Vorgang aufrufen.

Hinweis

Der Versuch, fehlgeschlagene sitzungsbasierte Kanäle explizit zu erkennen, ist normalerweise nicht sinnvoll, da der Zeitpunkt der Benachrichtigung von der Sitzungsimplementierung abhängt. Da beispielsweise die System.ServiceModel.NetTcpBinding (bei deaktivierter zuverlässiger Sitzung) die Sitzung der TCP-Verbindung anzeigt, wenn Sie das ICommunicationObject.Faulted-Ereignis auf dem Dienst oder dem Client abhören, werden Sie wahrscheinlich bei einem Netzwerkfehler schnell benachrichtigt. Zuverlässige Sitzungen (festgelegt durch Bindungen, in denen System.ServiceModel.Channels.ReliableSessionBindingElement aktiviert ist) sind jedoch so konzipiert, dass sie Dienste von kleineren Netzwerkfehlern isolieren. Wenn die Sitzung innerhalb eines angemessenen Zeitraums wieder eingerichtet werden kann, schlägt die gleiche, für zuverlässige Sitzungen konfigurierte Bindung unter Umständen nicht fehl, bis die Unterbrechung einen längeren Zeitraum andauert.

Die meisten der vom System bereitgestellten Bindungen (die Kanäle für die Anwendungsebene verfügbar machen) verwenden standardmäßig Sitzungen, System.ServiceModel.BasicHttpBinding jedoch nicht. Weitere Informationen finden Sie unter Verwenden von Sitzungen.

Richtige Verwendung von Sitzungen

Sitzungen bieten die Möglichkeit festzustellen, ob der gesamte Nachrichtenaustausch vollständig ist und von beiden Seiten als erfolgreich betrachtet wurde. Es wird empfohlen, dass eine aufrufende Anwendung den Kanal innerhalb eines Try-Blocks öffnet, verwendet und schließt. Wenn ein Sitzungskanal geöffnet ist, die ICommunicationObject.Close-Methode einmal aufgerufen wird und dieser Aufruf erfolgreich beendet wurde, war die Sitzung erfolgreich. Erfolgreich bedeutet in diesem Fall, dass alle von der Bindung angegebenen Zustellungsgarantien d erfüllt wurden und die andere Seite auf dem Kanal nicht ICommunicationObject.Abort vor dem Aufrufen von Close aufgerufen hat.

Der folgende Abschnitt enthält ein Beispiel für diesen Clientansatz.

Behandeln von Ausnahmen

Das Behandeln von Ausnahmen in Clientanwendungen ist einfach. Wird ein Kanal innerhalb eines Try-Blocks geöffnet, verwendet und geschlossen, war die Konversation erfolgreich, wenn keine Ausnahme ausgelöst wird. In der Regel wird die Konversation abgebrochen, wenn eine Ausnahme ausgelöst wird.

Hinweis

Die Verwendung der using-Anweisung (Using in Visual Basic) wird nicht empfohlen. Das liegt daran, dass das Ende der using-Anweisung möglicherweise Ausnahmen verursacht, die andere Ausnahmen maskieren können, von denen Sie wissen sollten. Weitere Informationen finden Sie unter Vermeiden von Problemen mit der Using-Anweisung.

Im folgenden Codebeispiel verwendet das empfohlene Clientmuster einen Try\/Catch-Block und nicht die using-Anweisung.

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using Microsoft.WCF.Documentation;

public class Client
{
  public static void Main()
  {
    // Picks up configuration from the config file.
    SampleServiceClient wcfClient = new SampleServiceClient();
    try
    {
      // Making calls.
      Console.WriteLine("Enter the greeting to send: ");
      string greeting = Console.ReadLine();
      Console.WriteLine("The service responded: " + wcfClient.SampleMethod(greeting));

      Console.WriteLine("Press ENTER to exit:");
      Console.ReadLine();

      // Done with service. 
      wcfClient.Close();
      Console.WriteLine("Done!");
    }
    catch (TimeoutException timeProblem)
    {
      Console.WriteLine("The service operation timed out. " + timeProblem.Message);
      Console.ReadLine();
      wcfClient.Abort();
    }
    catch (FaultException<GreetingFault> greetingFault)
    {
      Console.WriteLine(greetingFault.Detail.Message);
      Console.ReadLine();
      wcfClient.Abort();
    }
    catch (FaultException unknownFault)
    {
      Console.WriteLine("An unknown exception was received. " + unknownFault.Message);
      Console.ReadLine();
      wcfClient.Abort();
    }
    catch (CommunicationException commProblem)
    {
      Console.WriteLine("There was a communication problem. " + commProblem.Message + commProblem.StackTrace);
      Console.ReadLine();
      wcfClient.Abort();
    }
  }
}

Imports System
Imports System.ServiceModel
Imports System.ServiceModel.Channels
Imports Microsoft.WCF.Documentation

Public Class Client
  Public Shared Sub Main()
	' Picks up configuration from the config file.
	Dim wcfClient As New SampleServiceClient()
	Try
	  ' Making calls.
	  Console.WriteLine("Enter the greeting to send: ")
	  Dim greeting As String = Console.ReadLine()
	  Console.WriteLine("The service responded: " & wcfClient.SampleMethod(greeting))

	  Console.WriteLine("Press ENTER to exit:")
	  Console.ReadLine()

	  ' Done with service. 
	  wcfClient.Close()
	  Console.WriteLine("Done!")
	Catch timeProblem As TimeoutException
	  Console.WriteLine("The service operation timed out. " & timeProblem.Message)
	  Console.ReadLine()
	  wcfClient.Abort()
	Catch greetingFault As FaultException(Of GreetingFault)
	  Console.WriteLine(greetingFault.Detail.Message)
	  Console.ReadLine()
	  wcfClient.Abort()
	Catch unknownFault As FaultException
	  Console.WriteLine("An unknown exception was received. " & unknownFault.Message)
	  Console.ReadLine()
	  wcfClient.Abort()
	Catch commProblem As CommunicationException
	  Console.WriteLine("There was a communication problem. " & commProblem.Message + commProblem.StackTrace)
	  Console.ReadLine()
	  wcfClient.Abort()
	End Try
  End Sub
End Class
Hinweis

Das Überprüfen des Werts der ICommunicationObject.State-Eigenschaft ist eine Racebedingung und wird beim Feststellen, ob ein Kanal wiederverwendet oder geschlossen werden soll, nicht empfohlen.

Datagrammkanäle schlagen nie fehl, auch wenn beim Schließen Ausnahmen auftreten. Außerdem lösen Nichtduplex-Clients, bei denen keine Authentifizierung über eine sichere Konversation möglich ist, in der Regel eine System.ServiceModel.Security.MessageSecurityException aus. Wenn jedoch für den Duplexclient, der eine sichere Konversation verwendet, keine Authentifizierung möglich ist, erhält der Client stattdessen eine System.TimeoutException.

Weitere Informationen zum Arbeiten mit Fehlerinformationen auf der Anwendungsebene finden Sie unter Angeben und Behandeln von Fehlern in Verträgen und Diensten. In Erwartete Ausnahmen werden erwartete Ausnahmen und ihre Behandlung erläutert. Weitere Informationen finden Sie unter zur Fehlerbehandlung beim Entwickeln von Kanälen finden Sie unter Behandeln von Ausnahmen und Fehlern.

Clientblockierung und Leistung

Wenn eine Anwendung synchron einen Anforderungs-\/Antwortvorgang aufruft, wird der Client blockiert, bis ein Rückgabewert empfangen oder eine Ausnahme (wie System.TimeoutException) ausgelöst wird. Dieses Verhalten ähnelt lokalem Verhalten. Ruft eine Anwendung synchron einen Vorgang auf einem WCF-Clientobjekt oder -kanal auf, wird der Client erst dann zurückgegeben, wenn die Kanalebene die Daten an das Netzwerk schreiben kann oder bis eine Ausnahme ausgelöst wird. Und während das unidirektionale Nachrichtenaustauschmuster (angegeben durch die Markierung eines Vorgangs, wobei OperationContractAttribute.IsOneWay auf true festgelegt ist) die Reaktionsgeschwindigkeit einiger Clients verbessern kann, können unidirektionale Vorgänge abhängig von der Bindung und den bisher gesendeten Nachrichten auch blockiert werden. Bei unidirektionalen Vorgängen geht es nur um den Nachrichtenaustausch. Weitere Informationen finden Sie unter Unidirektionale Dienste.

Große Datensegmente können die Clientverarbeitung verlangsamen, egal, welches Nachrichtenaustauschmuster verwendet wird. Informationen zur Behandlung dieser Probleme finden Sie unter Umfangreiche Daten und Streaming.

Wenn die Anwendung beim Abschluss eines Vorgangs mehr arbeiten muss, sollten Sie ein asynchrones Methodenpaar an der Dienstvertragschnittstelle erstellen, das der WCF-Client implementiert. Die einfachste Methode dazu ist die Verwendung des /async-Schalters im ServiceModel Metadata Utility-Tool (Svcutil.exe). Ein Beispiel finden Sie unter Vorgehensweise: Asynchrones Aufrufen von Dienstvorgängen.

Weitere Informationen finden Sie unter zum Verbessern der Clientleistung finden Sie unter Clientanwendungen mittlerer Ebene.

Dynamisches Auswählen von Anmeldeinformationen durch den Benutzer

Über die IInteractiveChannelInitializer-Schnittstelle können Anwendungen eine Benutzeroberfläche anzeigen, auf der der Benutzer Anmeldeinformationen zum Erstellen eines Kanals auswählen kann, bevor die Timeout-Zeitgeber starten.

Es gibt zwei Methoden, wie Anwendungsentwickler ein eingefügtes IInteractiveChannelInitializer nutzen können. Die Clientanwendung kann entweder ClientBase<TChannel>.DisplayInitializationUI oder IClientChannel.DisplayInitializationUI (oder eine asynchrone Version) vor dem Öffnen des Kanals aufrufen (expliziter Ansatz) oder den ersten Vorgang aufrufen (impliziter Ansatz).

Bei Verwendung des impliziten Ansatzes muss die Anwendung den ersten Vorgang für eine ClientBase<TChannel>-Erweiterung oder eine IClientChannel-Erweiterung aufrufen. Wenn ein anderes Element als der erste Vorgang aufgerufen wird, wird eine Ausnahme ausgelöst.

Bei Verwendung des expliziten Ansatzes müssen durch die Anwendung die folgenden Schritte in dieser Reihenfolge ausgeführt werden:

  1. Rufen Sie ClientBase<TChannel>.DisplayInitializationUI oder IClientChannel.DisplayInitializationUI (oder eine asynchrone Version) auf.

  2. Wenn die Initialisierer zurückgegeben wurden, rufen Sie entweder die Open-Methode für das IClientChannel-Objekt oder für das IClientChannel-Objekt auf, das durch die ClientBase<TChannel>.InnerChannel-Eigenschaft zurückgegeben wird.

  3. Aufrufen von Vorgängen.

Es wird empfohlen, dass Anwendungen mit Produktionsqualität den Prozess der Benutzeroberfläche mithilfe des expliziten Ansatzes steuern.

Anwendungen, die den impliziten Ansatz verwenden, rufen die Initialisierer der Benutzeroberfläche auf, aber wenn der Benutzer nicht innerhalb des Sendetimeouts der Bindung antwortet, wird bei Zurückgeben der Benutzeroberfläche eine Ausnahme ausgelöst.

Siehe auch

Duplexdienste
Vorgehensweise: Zugreifen auf Dienste mit unidirektionalen und Anforderung-Antwort-Verträgen
Vorgehensweise: Zugreifen auf Dienste mit einem Duplexvertrag
Vorgehensweise: Zugriff auf einen WSE3.0-Dienst
Vorgehensweise: Verwenden der ChannelFactory
Vorgehensweise: Asynchrones Aufrufen von Dienstvorgängen
Clientanwendungen mittlerer Ebene