Zugreifen auf Dienste mithilfe eines Clients
Client-Anwendungen müssen WCF-Client- oder Channel-Objekte erstellen, konfigurieren und verwenden, um mit Diensten zu kommunizieren. Das Thema WCF Client Overview 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 Datagramm-Kanal 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 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: Freigeben von WCF-Clientressourcen mit „Close“ und „Abort“
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.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.
Ausführlichere Informationen zum Arbeiten mit Fehlerinformationen auf Anwendungsebene finden Sie unter Angeben und Behandeln von Fehlern in Verträgen und Diensten. In Expected Exceptions werden erwartete Ausnahmen und ihre Behandlung erläutert. Weitere Informationen zum Behandeln von Fehlern 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 Duplexdienste.
Große Datensegmente können die Clientverarbeitung verlangsamen, egal, welches Nachrichtenaustauschmuster verwendet wird. Informationen zum Behandeln dieser Probleme finden Sie unter Große 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. Am einfachsten ist es, den /async
-Schalter im ServiceModel Metadata Utility Tool (Svcutil.exe) zu verwenden. Ein Beispiel finden Sie unter Vorgehensweise: Asynchrones Aufrufen von Dienstvorgängen.
Weitere Informationen zum Erhöhen der Clientleistung finden Sie unter Clientanwendungen der mittleren 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:
Rufen Sie ClientBase<TChannel>.DisplayInitializationUI oder IClientChannel.DisplayInitializationUI (oder eine asynchrone Version) auf.
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.
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