Dela via


Åtkomst till tjänster med hjälp av en klient

Klientprogram måste skapa, konfigurera och använda WCF-klient- eller kanalobjekt för att kommunicera med tjänster. Avsnittet Översikt över WCF-klienter ger en översikt över de objekt och steg som ingår i att skapa grundläggande klient- och kanalobjekt och använda dem.

Det här avsnittet innehåller detaljerad information om några av problemen med klientprogram och klient- och kanalobjekt som kan vara användbara beroende på ditt scenario.

Översikt

Det här avsnittet beskriver beteende och problem som rör:

  • Kanal- och sessionslivslängder.

  • Hantera undantag.

  • Förstå blockeringsproblem.

  • Initiera kanaler interaktivt.

Kanal- och sessionslivslängd

Windows Communication Foundation-program (WCF) innehåller två kategorier av kanaler, datagram och sessionskänsliga.

En datagramkanal är en kanal där alla meddelanden inte är korrelerade. Om en in- eller utdataåtgärd misslyckas med en datagramkanal påverkas normalt inte nästa åtgärd och samma kanal kan återanvändas. På grund av detta felar datagramkanaler vanligtvis inte.

Sessionskänsliga kanaler är dock kanaler med en anslutning till den andra slutpunkten. Meddelanden i en session på ena sidan korreleras alltid med samma session på den andra sidan. Dessutom måste båda deltagarna i en session vara överens om att kraven för deras konversation uppfylldes för att sessionen ska anses vara framgångsrik. Om de inte kan komma överens kan den sessionskänsliga kanalen orsaka fel.

Öppna klienter explicit eller implicit genom att anropa den första åtgärden.

Kommentar

Det är vanligtvis inte användbart att försöka identifiera felaktiga sessionskänsliga kanaler, eftersom när du meddelas beror på sessionsimplementeringen. Till exempel, eftersom System.ServiceModel.NetTcpBinding (med den tillförlitliga sessionen inaktiverad) ytbehandlar sessionen för TCP-anslutningen, om du lyssnar ICommunicationObject.Faulted på händelsen på tjänsten eller klienten kommer du sannolikt att meddelas snabbt i händelse av ett nätverksfel. Men tillförlitliga sessioner (som upprättas av bindningar där System.ServiceModel.Channels.ReliableSessionBindingElement är aktiverade) är utformade för att isolera tjänster från små nätverksfel. Om sessionen kan återupprättas inom en rimlig tidsperiod kan samma bindning – som konfigurerats för tillförlitliga sessioner – inte vara fel förrän avbrottet har fortsatt under en längre tidsperiod.

De flesta bindningar som tillhandahålls av systemet (som exponerar kanaler för programskiktet) använder sessioner som standard, men det gör inte det System.ServiceModel.BasicHttpBinding . Mer information finns i Använda sessioner.

Korrekt användning av sessioner

Sessioner är ett sätt att veta om hela meddelandeutbytet är klart och om båda sidor anser att det lyckades. Vi rekommenderar att ett anropande program öppnar kanalen, använder den och stänger kanalen i ett försöksblock. Om en sessionskanal är öppen och ICommunicationObject.Close metoden anropas en gång, och det anropet returnerar korrekt, lyckades sessionen. Lyckad i det här fallet innebär att alla leveransgarantier som den angivna bindningen uppfylldes och att den andra sidan inte anropade ICommunicationObject.Abort kanalen innan den anropade Close.

Följande avsnitt innehåller ett exempel på den här klientmetoden.

Hantera undantag

Det är enkelt att hantera undantag i klientprogram. Om en kanal öppnas, används och stängs i ett försöksblock har konversationen slutförts, såvida inte ett undantag utlöses. Om ett undantag utlöses avbryts vanligtvis konversationen.

Kommentar

Användning av -instruktionen using (Using i Visual Basic) rekommenderas inte. Det beror på att slutet av -instruktionen using kan orsaka undantag som kan maskera andra undantag som du kan behöva känna till. Mer information finns i Använda Stäng och Avbryt för att frigöra WCF-klientresurser.

I följande kodexempel visas det rekommenderade klientmönstret med hjälp av ett try/catch-block och inte -instruktionen using .

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

Kommentar

Att kontrollera värdet för ICommunicationObject.State egenskapen är ett konkurrenstillstånd och rekommenderas inte att avgöra om en kanal ska återanvändas eller stängas.

Datagramkanaler felar aldrig även om undantag inträffar när de stängs. Dessutom genererar icke-duplex-klienter som inte kan autentiseras med en säker konversation vanligtvis en System.ServiceModel.Security.MessageSecurityException. Men om duplex-klienten som använder en säker konversation inte kan autentiseras får klienten en System.TimeoutException i stället.

Mer fullständig information om hur du arbetar med felinformation på programnivå finns i Ange och hantera fel i Kontrakt och tjänster. Förväntade undantag beskriver förväntade undantag och visar hur du hanterar dem. Mer information om hur du hanterar fel när du utvecklar kanaler finns i Hantera undantag och fel.

Klientblockering och prestanda

När ett program synkront anropar en begäran-svar-åtgärd blockerar klienten tills ett returvärde tas emot eller ett undantag (till exempel ett System.TimeoutException) genereras. Det här beteendet liknar det lokala beteendet. När ett program synkront anropar en åtgärd på ett WCF-klientobjekt eller en kanal, returneras inte klienten förrän kanallagret kan skriva data till nätverket eller tills ett undantag utlöses. Och även om mönstret för envägsmeddelandeutbyte (som anges genom att markera en åtgärd med OperationContractAttribute.IsOneWay inställd på true) kan göra vissa klienter mer dynamiska, kan enkelriktade åtgärder också blockeras, beroende på bindningen och vilka meddelanden som redan har skickats. Enkelriktade åtgärder handlar bara om meddelandeutbytet, varken mer eller mindre. Mer information finns i One-Way Services.

Stora datasegment kan göra klientbearbetningen långsammare oavsett mönstret för meddelandeutbyte. Information om hur du hanterar dessa problem finns i Stora data och strömning.

Om programmet måste utföra mer arbete medan en åtgärd slutförs bör du skapa ett asynkront metodpar i tjänstkontraktsgränssnittet som WCF-klienten implementerar. Det enklaste sättet att göra detta är att använda växeln /asyncServiceModel Metadata Utility Tool (Svcutil.exe). Ett exempel finns i How to: Call Service Operations Asynchronously (Så här anropar du tjänståtgärder asynkront).

Mer information om hur du ökar klientprestanda finns i Klientprogram på mellannivå.

Aktivera användaren att välja autentiseringsuppgifter dynamiskt

Gränssnittet IInteractiveChannelInitializer gör det möjligt för program att visa ett användargränssnitt som gör att användaren kan välja autentiseringsuppgifter som en kanal skapas med innan timeout-timern startar.

Programutvecklare kan använda en infogad IInteractiveChannelInitializer på två sätt. Klientprogrammet kan anropa antingen ClientBase<TChannel>.DisplayInitializationUI eller IClientChannel.DisplayInitializationUI (eller en asynkron version) innan du öppnar kanalen (den explicita metoden) eller anropa den första åtgärden (implicit metod).

Om du använder den implicita metoden måste programmet anropa den första åtgärden för en ClientBase<TChannel> eller IClientChannel ett tillägg. Om den anropar något annat än den första åtgärden utlöses ett undantag.

Om du använder den explicita metoden måste programmet utföra följande steg i ordning:

  1. Anropa antingen ClientBase<TChannel>.DisplayInitializationUI eller IClientChannel.DisplayInitializationUI (eller en asynkron version).

  2. När initierarna har returnerats anropar du antingen Open metoden för IClientChannel objektet eller på objektet IClientChannel som returneras från ClientBase<TChannel>.InnerChannel egenskapen.

  3. Anropsåtgärder.

Vi rekommenderar att program av produktionskvalitet styr användargränssnittsprocessen genom att använda den explicita metoden.

Program som använder den implicita metoden anropar initierarna för användargränssnittet, men om användaren av programmet inte svarar inom tidsgränsen för bindningen utlöses ett undantag när användargränssnittet returneras.

Se även