Tutorial: Verfügbarmachen eines lokalen WCF REST-Diensts für einen externen Client mithilfe von Azure WCF Relay

In diesem Tutorial wird die Erstellung einer Clientanwendung und eines Diensts für WCF Relay mithilfe von Azure Relay beschrieben. Wie die ursprünglichen WCF-Entsprechungen ist ein Dienst ein Konstrukt, mit dem ein oder mehrere Endpunkte verfügbar gemacht werden. Jeder Endpunkt macht mindestens einen Dienstvorgang verfügbar. Der Endpunkt eines Diensts gibt eine Adresse an, unter der der Dienst gefunden werden kann, eine Bindung, die die Information enthält, dass ein Client mit dem Dienst kommunizieren muss, und einen Vertrag, der die Funktionen definiert, die der Dienst für seine Clients bereitstellt. Der Hauptunterschied zwischen WCF und WCF-Relay besteht darin, dass der Endpunkt in der Cloud und nicht lokal auf Ihrem Computer bereitgestellt wird.

Nachdem Sie die Abschnitte in diesem Tutorial der Reihe nach durchgearbeitet haben, verfügen Sie über einen ausgeführten Dienst. Außerdem verfügen Sie über einen Client, mit dem die Vorgänge des Diensts aufgerufen werden können.

In diesem Tutorial führen Sie die folgenden Aufgaben durch:

  • Installieren der erforderlichen Komponenten für das Tutorial
  • Erstellen eines Relaynamespace
  • Erstellen eines WCF-Dienstvertrags
  • Implementieren des WCF-Vertrags
  • Hosten und Ausführen des WCF-Diensts für die Registrierung beim Relaydienst
  • Erstellen eines WCF-Clients für den Dienstvertrag
  • Konfigurieren des WCF-Clients
  • Implementieren des WCF-Clients
  • Ausführen der Anwendungen

Voraussetzungen

Zum Durchführen dieses Tutorials benötigen Sie Folgendes:

Erstellen eines Relaynamespace

Der erste Schritt umfasst die Einrichtung eines Namespaces und das Abrufen eines Shared Access Signature-Schlüssels (SAS). Ein Namespace stellt eine Anwendungsgrenze für jede Anwendung bereit, die über den Relaydienst verfügbar gemacht wird. Es wird automatisch ein SAS-Schlüssel generiert, wenn ein Dienstnamespace erstellt wird. Dienstnamespace und SAS-Schlüssel bilden gemeinsam die Anmeldeinformationen, mit denen sich Azure für den Zugriff auf die Anwendung authentifiziert.

  1. Melden Sie sich beim Azure-Portal an.

  2. Wählen Sie im Menü links Alle Dienste aus. Wählen Sie Integration aus, suchen Sie nach Relays, zeigen Sie mit der Maus auf Relays, und wählen Sie dann Erstellen.

    Screenshot: Auswahl von Relays > Schaltfläche „Erstellen“

  3. Führen Sie die folgenden Schritte auf der Seite Namespace erstellen aus:

    1. Wählen Sie ein Azure-Abonnement aus, in dem der Namespace erstellt werden soll.

    2. Wählen Sie unter Ressourcengruppe eine vorhandene Ressourcengruppe aus, in der der Namespace platziert werden soll, oder erstellen Sie eine neue Ressourcengruppe.

    3. Geben Sie einen Namen für den Relay-Namespace ein.

    4. Wählen Sie die Region aus, in dem bzw. in der Ihr Namespace gehostet werden soll.

    5. Wählen Sie am unteren Rand der Seite die Option Bewerten + erstellen aus.

      Screenshot: Seite „Namespace erstellen“

    6. Wählen Sie auf der Seite Überprüfen + erstellen die Option Erstellen aus.

    7. Nach ein paar Minuten sehen Sie die Seite Vermittlung für den Namespace.

      Screenshot: Startseite für den Relay-Namespace

Abrufen von Anmeldeinformationen für die Verwaltung

  1. Wählen Sie auf der Seite Vermittlung die Option Freigegebene Zugriffsrichtlinien im linken Menü aus. `

  2. Wählen Sie auf der Seite Freigegebene Zugriffsrichtlinien die Option RootManageSharedAccessKey aus.

  3. Klicken Sie unter SAS-Richtlinie: RootManageSharedAccessKey neben Primäre Verbindungszeichenfolge auf die Schaltfläche Kopieren. Dadurch wird die Verbindungszeichenfolge zur späteren Verwendung in die Zwischenablage kopiert. Fügen Sie diesen Wert in den Editor oder an einem anderen temporären Speicherort ein.

  4. Wiederholen Sie den vorherigen Schritt, um den Wert von Primärschlüssel zu kopieren und zur späteren Verwendung an einem temporären Speicherort einzufügen.

    Screenshot: Verbindungsinformationen für den Relay-Namespace

Definieren eines WCF-Dienstvertrags

Im Dienstvertrag ist angegeben, welche Vorgänge vom Dienst unterstützt werden. Vorgänge sind Webdienstmethoden oder -funktionen. Verträge werden durch die Definition einer C++-, C#- oder Visual Basic-Schnittstelle erstellt. Jede Methode in der Schnittstelle entspricht einem bestimmten Dienstvorgang. Auf jede Schnittstelle muss das Attribut ServiceContractAttribute und auf jeden Vorgang das Attribut OperationContractAttribute angewendet werden. Wenn eine Methode in einer Schnittstelle das Attribut ServiceContractAttribute, aber nicht das Attribut OperationContractAttribute besitzt, wird diese Methode nicht verfügbar gemacht. Der Code für diese Aufgaben wird im Beispiel im Anschluss an das Verfahren bereitgestellt. Eine ausführlichere Darstellung von Verträgen und Diensten finden Sie unter Entwerfen und Implementieren von Diensten.

Erstellen eines Relayvertrags mit einer Schnittstelle

  1. Starten Sie Microsoft Visual Studio als Administrator. Klicken Sie hierzu mit der rechten Maustaste auf das Visual Studio-Programmsymbol, und wählen Sie Als Administrator ausführen aus.

  2. Wählen Sie in Visual Studio Neues Projekt erstellen aus.

  3. Wählen Sie unter Neues Projekt erstellen die Option Konsolen-App (.NET Framework) für C# und dann Weiter aus.

  4. Geben Sie dem Projekt den Namen EchoService, und wählen Sie Erstellen aus.

    Erstellen einer Konsolenanwendung

  5. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen Sie NuGet-Pakete verwalten aus. Wählen Sie im NuGet-Paket-Manager die Option Durchsuchen aus, suchen Sie nach WindowsAzure.ServiceBus, und wählen Sie diese Option aus. Wählen Sie Installieren aus, und akzeptieren Sie die Nutzungsbedingungen.

    Service Bus-Paket

    Mit diesem Paket werden automatisch Verweise auf die Service Bus-Bibliotheken und das WCF-Element System.ServiceModel hinzugefügt. System.ServiceModel ist der Namespace, der den programmgesteuerten Zugriff auf die grundlegenden Funktionen von WCF ermöglicht. Service Bus verwendet viele Objekte und Attribute von WCF, um Dienstverträge zu definieren.

  6. Fügen Sie am Anfang von Program.cs die folgenden using-Anweisungen hinzu:

    using System.ServiceModel;
    using Microsoft.ServiceBus;
    
  7. Ändern Sie den Namespacenamen vom Standardnamen EchoService in Microsoft.ServiceBus.Samples.

    Wichtig

    In diesem Tutorial wird der C#-Namespace Microsoft.ServiceBus.Samples verwendet. Hierbei handelt es sich um den Namespace des über den Vertrag verwalteten Typs, der in der Konfigurationsdatei im Abschnitt Konfigurieren des WCF-Clients verwendet wird. Sie können bei der Erstellung dieses Beispiels einen beliebigen Namespace angeben. Das Tutorial funktioniert aber nur, wenn Sie dann in der Anwendungskonfigurationsdatei die Namespaces des Vertrags und des Diensts entsprechend ändern. Der in der Datei App.config angegebene Namespace muss mit dem in Ihren C#-Dateien angegebenen Namespace identisch sein.

  8. Definieren Sie direkt nach der Namespacedeklaration Microsoft.ServiceBus.Samples (jedoch innerhalb des Namespaces) eine neue Schnittstelle namens IEchoContract, und wenden Sie das Attribut ServiceContractAttribute mit dem Namespacewert https://samples.microsoft.com/ServiceModel/Relay/ auf die Schnittstelle an. Fügen Sie nach der Namespacedeklaration den folgenden Code ein:

    [ServiceContract(Name = "IEchoContract", Namespace = "https://samples.microsoft.com/ServiceModel/Relay/")]
    public interface IEchoContract
    {
    }
    

    Der Namespacewert unterscheidet sich von dem Namespace, den Sie im gesamten Codebereich verwenden. Der Namespacewert wird stattdessen als eindeutiger Bezeichner für diesen Vertrag verwendet. Das explizite Angeben des Namespace verhindert, dass der Standardwert für den Namespace dem Vertragsnamen hinzugefügt wird.

    Hinweis

    In der Regel enthält der Dienstvertragsnamespace ein Benennungsschema, das Versionsinformationen umfasst. Durch das Einbeziehen von Versionsinformationen im Dienstvertragsnamespace können Dienste größere Änderungen isolieren, indem ein neuer Dienstvertrag mit einem neuen Namespace definiert und an einem neuen Endpunkt bereitgestellt wird. Auf diese Weise können Clients weiterhin den alten Dienstvertrag verwenden, ohne dass sie aktualisiert werden müssen. Versionsinformationen können aus einer Datumsangabe oder einer Buildnummer bestehen. Weitere Informationen finden Sie unter Dienstversionsverwaltung. In diesem Tutorial umfasst das Benennungsschema des Dienstvertragsnamespace keine Versionsinformationen.

  9. Deklarieren Sie innerhalb der Schnittstelle IEchoContract eine Methode für den einzelnen Vorgang, den der Vertrag IEchoContract in der Schnittstelle bereitstellt, und wenden Sie das Attribut OperationContractAttribute auf die Methode an, die Sie als Teil des öffentlichen WCF-Relayvertrags bereitstellen möchten:

    [OperationContract]
    string Echo(string text);
    
  10. Deklarieren Sie direkt im Anschluss an die IEchoContract-Schnittstellendefinition einen Kanal mit Vererbung von IEchoContract und Vererbung an die IClientChannel-Schnittstelle, wie im folgenden Beispiel gezeigt:

    public interface IEchoChannel : IEchoContract, IClientChannel { }
    

    Ein Kanal ist das WCF-Objekt, über das der Host und der Client einander Informationen übergeben. Später schreiben Sie Code für den Kanal, um ein Echo der Informationen zwischen den beiden Anwendungen zu erzeugen.

  11. Wählen Sie Erstellen>Projektmappe erstellen aus (oder STRG+UMSCHALT+B), um die Korrektheit Ihrer bisherigen Arbeit zu bestätigen.

Beispiel für einen WCF-Vertrag

Das folgende Codebeispiel zeigt eine Basisschnittstelle, die einen WCF-Relayvertrag definiert.

using System;
using System.ServiceModel;

namespace Microsoft.ServiceBus.Samples
{
    [ServiceContract(Name = "IEchoContract", Namespace = "https://samples.microsoft.com/ServiceModel/Relay/")]
    public interface IEchoContract
    {
        [OperationContract]
        String Echo(string text);
    }

    public interface IEchoChannel : IEchoContract, IClientChannel { }

    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}

Nachdem nun die Schnittstelle erstellt ist, können Sie die Schnittstelle implementieren.

Implementieren des WCF-Vertrags

Zum Erstellen eines Azure-Relays müssen Sie zuerst den Vertrag erstellen, indem Sie eine Schnittstelle verwenden. Weitere Informationen zum Erstellen der Schnittstelle finden Sie im vorherigen Abschnitt. Mit der nächsten Prozedur wird die Schnittstelle implementiert. Diese Aufgabe umfasst das Erstellen einer Klasse mit dem Namen EchoService, mit der die benutzerdefinierte IEchoContract-Schnittstelle implementiert wird. Nachdem Sie die Schnittstelle implementiert haben, konfigurieren Sie die Schnittstelle mit einer App.config-Konfigurationsdatei. Die Konfigurationsdatei enthält die erforderlichen Informationen für die Anwendung. Dies sind der Name des Diensts, der Name des Vertrags und der Protokolltyp, der für die Kommunikation mit dem Relaydienst verwendet wird. Der für diese Aufgaben verwendete Code ist im Beispiel enthalten, das auf die Prozedur folgt. Eine allgemeinere Darstellung der Implementierung eines Dienstvertrags finden Sie unter Implementieren von Dienstverträgen.

  1. Erstellen Sie eine neue Klasse namens EchoService direkt unterhalb der Definition der IEchoContract-Schnittstelle. Die EchoService-Klasse implementiert die IEchoContract-Schnittstelle.

    class EchoService : IEchoContract
    {
    }
    

    Ähnlich wie bei anderen Schnittstellenimplementierungen können Sie die Definition in einer anderen Datei implementieren. In diesem Tutorial befindet sich die Implementierung allerdings in derselben Datei wie die Schnittstellendefinition und die Main()-Methode.

  2. Wenden Sie das ServiceBehaviorAttribute-Attribut auf die IEchoContract-Schnittstelle an. Das Attribut gibt den Dienstnamen und den Namespace an. Die EchoService-Klasse sieht dann wie folgt aus:

    [ServiceBehavior(Name = "EchoService", Namespace = "https://samples.microsoft.com/ServiceModel/Relay/")]
    class EchoService : IEchoContract
    {
    }
    
  3. Implementieren Sie die Echo-Methode, die in der IEchoContract-Schnittstelle in der EchoService-Klasse definiert ist.

    public string Echo(string text)
    {
        Console.WriteLine("Echoing: {0}", text);
        return text;
    }
    
  4. Wählen Sie Erstellen>Projektmappe erstellen aus (oder STRG+UMSCHALT+B).

Definieren der Konfiguration für den Diensthost

Die Konfigurationsdatei ähnelt einer WCF-Konfigurationsdatei. Sie enthält den Dienstnamen, den Endpunkt und die Bindung. Der Endpunkt ist der Ort, der von Azure Relay für Clients und Hosts verfügbar gemacht wird, um die Kommunikation zu ermöglichen. Die Bindung ist der Protokolltyp, der für die Kommunikation verwendet wird. Der Hauptunterschied besteht darin, dass dieser konfigurierte Dienstendpunkt auf eine NetTcpRelayBinding-Bindung verweist, die nicht Bestandteil von .NET Framework ist. NetTcpRelayBinding ist eine der Bindungen, die durch den Dienst definiert werden.

  1. Doppelklicken Sie im Projektmappen-Explorer auf App.config, um die Datei im Visual Studio-Editor zu öffnen.

  2. Ersetzen Sie im Element <appSettings> die Platzhalter durch den Namen Ihres Azure Relay-Namespace und den SAS-Schlüssel, den Sie in einem vorherigen Schritt kopiert haben.

  3. Fügen Sie innerhalb der <system.serviceModel>-Tags ein <services>-Element hinzu. Sie können mehrere Relayanwendungen in einer einzigen Konfigurationsdatei definieren. In diesem Tutorial wird jedoch nur eine Anwendung definiert.

    <?xmlversion="1.0" encoding="utf-8"?>
    <configuration>
      <system.serviceModel>
        <services>
    
        </services>
      </system.serviceModel>
    </configuration>
    
  4. Fügen Sie im <services>-Element ein <service>-Element hinzu, um den Namen des Diensts zu definieren.

    <service name="Microsoft.ServiceBus.Samples.EchoService">
    </service>
    
  5. Definieren Sie im <service>-Element den Speicherort des Endpunktvertrags sowie den Bindungstyp für den Endpunkt.

    <endpoint contract="Microsoft.ServiceBus.Samples.IEchoContract" binding="netTcpRelayBinding"/>
    

    Der Endpunkt definiert, wo der Client nach der Hostanwendung sucht. Dieser Schritt wird später in diesem Tutorial verwendet, um einen URI zu erstellen, der den Host über Azure Relay uneingeschränkt verfügbar macht. Die Bindung deklariert die Verwendung von TCP als Protokoll für die Kommunikation mit dem Relaydienst.

  6. Wählen Sie Erstellen>Projektmappe erstellen aus (oder STRG+UMSCHALT+B), um die Korrektheit Ihrer bisherigen Arbeit zu bestätigen.

Beispiel für die Implementierung eines Dienstvertrags

Der folgende Code zeigt die Implementierung des Dienstvertrags.

[ServiceBehavior(Name = "EchoService", Namespace = "https://samples.microsoft.com/ServiceModel/Relay/")]

    class EchoService : IEchoContract
    {
        public string Echo(string text)
        {
            Console.WriteLine("Echoing: {0}", text);
            return text;
        }
    }

Der folgende Code veranschaulicht das grundlegende Format der Datei App.config, die dem Diensthost zugeordnet ist.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="Microsoft.ServiceBus.Samples.EchoService">
        <endpoint contract="Microsoft.ServiceBus.Samples.IEchoContract" binding="netTcpRelayBinding" />
      </service>
    </services>
    <extensions>
      <bindingExtensions>
        <add name="netTcpRelayBinding"
                    type="Microsoft.ServiceBus.Configuration.NetTcpRelayBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      </bindingExtensions>
    </extensions>
  </system.serviceModel>
</configuration>

Hosten und Ausführen des WCF-Diensts für die Registrierung beim Relaydienst

Dieser Schritt beschreibt, wie ein Azure Relay-Dienst ausgeführt wird.

Erstellen der Relayanmeldeinformationen

  1. Erstellen Sie in Main() zwei Variablen zum Speichern des Namespace und des SAS-Schlüssels, die aus dem Konsolenfenster gelesen werden.

    Console.Write("Your Service Namespace: ");
    string serviceNamespace = Console.ReadLine();
    Console.Write("Your SAS key: ");
    string sasKey = Console.ReadLine();
    

    Der SAS-Schlüssel wird später für den Zugriff auf Ihr Projekt verwendet. Der Namespace wird als Parameter an CreateServiceUri übergeben, um einen Dienst-URI zu erstellen.

  2. Deklarieren Sie mithilfe eines TransportClientEndpointBehavior-Objekts, dass ein SAS-Schlüssel als Anmeldeinformationstyp verwendet wird. Fügen Sie den folgenden Code direkt unter dem Code hinzu, den Sie im letzten Schritt hinzugefügt haben.

    TransportClientEndpointBehavior sasCredential = new TransportClientEndpointBehavior();
    sasCredential.TokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider("RootManageSharedAccessKey", sasKey);
    

Erstellen einer Basisadresse für den Dienst

Erstellen Sie nach dem Code, den Sie im vorherigen Abschnitt hinzugefügt haben, eine Uri-Instanz für die Basisadresse des Diensts. Dieser URI gibt das Service Bus-Schema, den Namespace und den Pfad der Dienstschnittstelle an.

Uri address = ServiceBusEnvironment.CreateServiceUri("sb", serviceNamespace, "EchoService");

Der Wert „sb“ ist eine Abkürzung für das Service Bus-Schema. Gibt an, dass TCP als Protokoll verwendet wird. Dieses Schema wurde zuvor bereits in der Konfigurationsdatei durch das Angeben von NetTcpRelayBinding als Bindung festgelegt.

Für dieses Tutorial lautet der URI sb://putServiceNamespaceHere.windows.net/EchoService.

Erstellen und Konfigurieren des Diensthosts

  1. Legen Sie unter Main() den Konnektivitätsmodus auf AutoDetect fest.

    ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.AutoDetect;
    

    Der Verbindungsmodus beschreibt das Protokoll, das der Dienst für die Kommunikation mit dem Relaydienst verwendet: HTTP oder TCP. Mithilfe der Standardeinstellung AutoDetect versucht der Dienst, falls verfügbar, eine Verbindung mit Azure Relay über TCP herzustellen. Wenn TCP nicht verfügbar ist, wird HTTP verwendet. Dieses Ergebnis unterscheidet sich von dem Protokoll, das vom Dienst für die Clientkommunikation angegeben wird. Dieses Protokoll wird durch die verwendete Bindung festgelegt. Ein Dienst kann z.B. die Bindung BasicHttpRelayBinding verwenden, die angibt, dass ihr Endpunkt über HTTP mit Clients kommuniziert. Derselbe Dienst kann auch ConnectivityMode.AutoDetect angeben, sodass der Dienst per TCP mit Azure Relay kommuniziert.

  2. Erstellen Sie den Diensthost unter Verwendung des URIs, den Sie zuvor in diesem Abschnitt erstellt haben.

    ServiceHost host = new ServiceHost(typeof(EchoService), address);
    

    Der Diensthost ist das WCF-Objekt, das den Dienst instanziiert. Hier wird der Diensttyp übergeben, den Sie erstellen möchten – ein EchoService-Typ –, sowie die Adresse, unter der der Dienst bereitgestellt werden soll.

  3. Fügen Sie am Anfang der Datei Program.cs Verweise auf System.ServiceModel.Description und Microsoft.ServiceBus.Description hinzu.

    using System.ServiceModel.Description;
    using Microsoft.ServiceBus.Description;
    
  4. Konfigurieren Sie in Main() den Endpunkt so, dass öffentlicher Zugriff ermöglicht wird.

    IEndpointBehavior serviceRegistrySettings = new ServiceRegistrySettings(DiscoveryType.Public);
    

    In diesem Schritt wird der Relaydienst darüber informiert, dass Ihre Anwendung durch das Untersuchen des Atom-Feeds für Ihr Projekt öffentlich ermittelbar ist. Wenn Sie DiscoveryType auf private festlegen, kann ein Client trotzdem auf den Dienst zugreifen. Der Dienst wird aber nicht angezeigt, wenn der Relay-Namespace durchsucht wird. Der Client muss stattdessen bereits vorher den Endpunktpfad kennen.

  5. Wenden Sie die Dienstanmeldeinformationen auf die in der Datei App.config definierten Dienstendpunkte an:

    foreach (ServiceEndpoint endpoint in host.Description.Endpoints)
    {
        endpoint.Behaviors.Add(serviceRegistrySettings);
        endpoint.Behaviors.Add(sasCredential);
    }
    

    Wie bereits erwähnt, können Sie in der Konfigurationsdatei mehrere Dienste und Endpunkte deklarieren. Wenn dies der Fall ist, durchläuft der Code die Konfigurationsdatei und sucht nach jedem Endpunkt, auf den die Anmeldeinformationen angewendet werden sollen. Für dieses Tutorial weist die Konfigurationsdatei nur einen Endpunkt auf.

Öffnen des Diensthosts

  1. Fügen Sie in Main() die folgende Zeile hinzu, um den Dienst zu öffnen.

    host.Open();
    
  2. Informieren Sie den Benutzer, dass der Dienst ausgeführt wird, und erläutern Sie, wie der Dienst heruntergefahren wird.

    Console.WriteLine("Service address: " + address);
    Console.WriteLine("Press [Enter] to exit");
    Console.ReadLine();
    
  3. Schließen Sie danach den Diensthost.

    host.Close();
    
  4. Wählen Sie STRG+UMSCHALT+B aus, um das Projekt zu erstellen.

Beispiel: Hosten eines Diensts in einer Konsolenanwendung

Der abgeschlossene Dienstcode sollte folgendermaßen aussehen. Der Code schließt den Dienstvertrag und die Implementierung aus früheren Schritten des Tutorials ein und hostet den Dienst in einer Konsolenanwendung.

using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using Microsoft.ServiceBus;
using Microsoft.ServiceBus.Description;

namespace Microsoft.ServiceBus.Samples
{
    [ServiceContract(Name = "IEchoContract", Namespace = "https://samples.microsoft.com/ServiceModel/Relay/")]
    public interface IEchoContract
    {
        [OperationContract]
        String Echo(string text);
    }

    public interface IEchoChannel : IEchoContract, IClientChannel { };

    [ServiceBehavior(Name = "EchoService", Namespace = "https://samples.microsoft.com/ServiceModel/Relay/")]
    class EchoService : IEchoContract
    {
        public string Echo(string text)
        {
            Console.WriteLine("Echoing: {0}", text);
            return text;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {

            ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.AutoDetect;         

            Console.Write("Your Service Namespace: ");
            string serviceNamespace = Console.ReadLine();
            Console.Write("Your SAS key: ");
            string sasKey = Console.ReadLine();

           // Create the credentials object for the endpoint.
            TransportClientEndpointBehavior sasCredential = new TransportClientEndpointBehavior();
            sasCredential.TokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider("RootManageSharedAccessKey", sasKey);

            // Create the service URI based on the service namespace.
            Uri address = ServiceBusEnvironment.CreateServiceUri("sb", serviceNamespace, "EchoService");

            // Create the service host reading the configuration.
            ServiceHost host = new ServiceHost(typeof(EchoService), address);

            // Create the ServiceRegistrySettings behavior for the endpoint.
            IEndpointBehavior serviceRegistrySettings = new ServiceRegistrySettings(DiscoveryType.Public);

            // Add the Relay credentials to all endpoints specified in configuration.
            foreach (ServiceEndpoint endpoint in host.Description.Endpoints)
            {
                endpoint.Behaviors.Add(serviceRegistrySettings);
                endpoint.Behaviors.Add(sasCredential);
            }

            // Open the service.
            host.Open();

            Console.WriteLine("Service address: " + address);
            Console.WriteLine("Press [Enter] to exit");
            Console.ReadLine();

            // Close the service.
            host.Close();
        }
    }
}

Erstellen eines WCF-Clients für den Dienstvertrag

Die nächste Aufgabe besteht darin, eine Clientanwendung zu erstellen und den Dienstvertrag zu definieren, den Sie später implementieren. Diese Schritte ähneln den Schritten, die zum Erstellen eines Diensts verwendet werden: Definieren eines Vertrags, Bearbeiten einer App.config-Datei, Verwenden von Anmeldeinformationen zum Herstellen einer Verbindung mit dem Relaydienst usw. Der für diese Aufgaben verwendete Code wird im Beispiel nach dem Verfahren bereitgestellt.

  1. Erstellen Sie in der aktuellen Visual Studio-Projektmappe für den Client ein neues Projekt:

    1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf die aktuelle Projektmappe (nicht auf das Projekt), und wählen Sie Hinzufügen>Neues Projekt aus.
    2. Wählen Sie unter Neues Projekt erstellen die Option Konsolen-App (.NET Framework) für C# und dann Weiter aus.
    3. Geben Sie dem Projekt den Namen EchoClient, und wählen Sie Erstellen aus.
  2. Doppelklicken Sie im Projektmappen-Explorer im Projekt EchoClient auf die Datei Program.cs, um die Datei im Editor zu öffnen (sofern sie nicht bereits geöffnet ist).

  3. Ändern Sie den Namespacenamen vom Standardnamen EchoClient in Microsoft.ServiceBus.Samples.

  4. Installieren Sie das NuGet-Paket für Service Bus:

    1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf EchoClient, und wählen Sie anschließend NuGet-Pakete verwalten aus.

    2. Wählen Sie Durchsuchen aus, suchen Sie nach WindowsAzure.ServiceBus, und wählen Sie diese Option aus. Wählen Sie Installieren aus, und akzeptieren Sie die Nutzungsbedingungen.

      Installieren des Service Bus-Pakets

  5. Fügen Sie der Datei Program.cs eine using-Anweisung für den Namespace System.ServiceModel hinzu.

    using System.ServiceModel;
    
  6. Fügen Sie dem Namespace die Dienstvertragsdefinition hinzu, wie im folgenden Beispiel gezeigt. Diese Definition ist mit der im Projekt Service verwendeten Definition identisch. Fügen Sie diesen Code am Anfang des Namespace Microsoft.ServiceBus.Samples hinzu.

    [ServiceContract(Name = "IEchoContract", Namespace = "https://samples.microsoft.com/ServiceModel/Relay/")]
    public interface IEchoContract
    {
        [OperationContract]
        string Echo(string text);
    }
    
    public interface IEchoChannel : IEchoContract, IClientChannel { }
    
  7. Wählen Sie STRG+UMSCHALT+B aus, um den Client zu erstellen.

Beispiel für das Projekt „EchoClient“

Mit dem folgenden Code wird der aktuelle Status der Datei Program.cs im Projekt EchoClient angezeigt.

using System;
using Microsoft.ServiceBus;
using System.ServiceModel;

namespace Microsoft.ServiceBus.Samples
{

    [ServiceContract(Name = "IEchoContract", Namespace = "https://samples.microsoft.com/ServiceModel/Relay/")]
    public interface IEchoContract
    {
        [OperationContract]
        string Echo(string text);
    }

    public interface IEchoChannel : IEchoContract, IClientChannel { }


    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}

Konfigurieren des WCF-Clients

In diesem Schritt erstellen Sie eine App.config-Datei für eine Clientbasisanwendung, die auf den zuvor in diesem Tutorial erstellten Dienst zugreift. Diese App.config-Datei definiert den Vertrag, die Bindung und den Namen des Endpunkts. Der für diese Aufgaben verwendete Code wird im Beispiel nach dem Verfahren bereitgestellt.

  1. Doppelklicken Sie im Projektmappen-Explorer im Projekt EchoClient auf App.config, um die Datei im Visual Studio-Editor zu öffnen.

  2. Ersetzen Sie im <appSettings>-Element die Platzhalter durch den Namen Ihres Dienstnamespace und den SAS-Schlüssel, den Sie in einem vorherigen Schritt kopiert haben.

  3. Fügen Sie im system.serviceModel-Element ein <client>-Element hinzu.

    <?xmlversion="1.0" encoding="utf-8"?>
    <configuration>
      <system.serviceModel>
        <client>
        </client>
      </system.serviceModel>
    </configuration>
    

    Mit diesem Code wird deklariert, dass Sie eine Clientanwendung im WCF-Stil definieren.

  4. Definieren Sie im Element client den Namen, den Vertrag und den Bindungstyp für den Endpunkt.

    <endpoint name="RelayEndpoint"
                    contract="Microsoft.ServiceBus.Samples.IEchoContract"
                    binding="netTcpRelayBinding"/>
    

    Mit diesem Code wird der Name des Endpunkts definiert. Außerdem werden der im Dienst festgelegte Vertrag und die Verwendung von TCP durch die Clientanwendung für die Kommunikation mit Azure Relay definiert. Der Endpunktname wird im nächsten Schritt verwendet, um diese Endpunktkonfiguration mit dem Dienst-URI zu verknüpfen.

  5. Wählen Sie Datei>Alle speichern aus.

Beispiel für die Datei „App.config“

Der folgende Code veranschaulicht die App.config-Datei für den Echo-Client.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <client>
      <endpoint name="RelayEndpoint"
                      contract="Microsoft.ServiceBus.Samples.IEchoContract"
                      binding="netTcpRelayBinding"/>
    </client>
    <extensions>
      <bindingExtensions>
        <add name="netTcpRelayBinding"
                    type="Microsoft.ServiceBus.Configuration.NetTcpRelayBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      </bindingExtensions>
    </extensions>
  </system.serviceModel>
</configuration>

Implementieren des WCF-Clients

In diesem Abschnitt implementieren Sie eine Clientbasisanwendung, die auf den zuvor in diesem Tutorial erstellten Dienst zugreift. Ähnlich wie der Dienst führt der Client viele derselben Vorgänge durch, um auf Azure Relay zuzugreifen:

  • Festlegen des Verbindungsmodus.
  • Erstellen des URIs, der den Hostdienst ermittelt.
  • Definieren der Sicherheitsanmeldeinformationen.
  • Anwenden der Anmeldeinformationen auf die Verbindung.
  • Öffnen der Verbindung.
  • Ausführen der anwendungsspezifischen Aufgaben.
  • Schließen der Verbindung.

Einer der Hauptunterschiede besteht aber darin, dass die Clientanwendung einen Kanal für die Verbindung mit dem Relaydienst verwendet. Der Dienst verwendet einen Aufruf von ServiceHost. Der für diese Aufgaben verwendete Code wird im Beispiel nach dem Verfahren bereitgestellt.

Implementieren einer Clientanwendung

  1. Legen Sie den Verbindungsmodus auf AutoDetect fest. Fügen Sie der Anwendung EchoClient in der Methode Main() den folgenden Code hinzu.

    ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.AutoDetect;
    
  2. Definieren Sie Variablen zum Speichern der Werte für den Dienstnamespace und den SAS-Schlüssel, die aus der Konsole gelesen werden.

    Console.Write("Your Service Namespace: ");
    string serviceNamespace = Console.ReadLine();
    Console.Write("Your SAS Key: ");
    string sasKey = Console.ReadLine();
    
  3. Erstellen Sie den URI, der den Speicherort des Hosts in Ihrem Relayprojekt definiert.

    Uri serviceUri = ServiceBusEnvironment.CreateServiceUri("sb", serviceNamespace, "EchoService");
    
  4. Erstellen Sie das Objekt für die Anmeldeinformationen für Ihren Dienstnamespace-Endpunkt.

    TransportClientEndpointBehavior sasCredential = new TransportClientEndpointBehavior();
    sasCredential.TokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider("RootManageSharedAccessKey", sasKey);
    
  5. Erstellen Sie die Kanalfactory, mit der die in der Datei App.config beschriebene Konfiguration geladen wird.

    ChannelFactory<IEchoChannel> channelFactory = new ChannelFactory<IEchoChannel>("RelayEndpoint", new EndpointAddress(serviceUri));
    

    Bei einer Kanalfactory ist handelt es sich um ein WCF-Objekt, das einen Kanal erstellt, über den der Dienst und die Clientanwendungen kommunizieren.

  6. Wenden Sie die Anmeldeinformationen an.

    channelFactory.Endpoint.Behaviors.Add(sasCredential);
    
  7. Erstellen und öffnen Sie den Kanal zum Dienst.

    IEchoChannel channel = channelFactory.CreateChannel();
    channel.Open();
    
  8. Schreiben Sie die grundlegende Benutzeroberfläche und die Funktionen für das Echo.

    Console.WriteLine("Enter text to echo (or [Enter] to exit):");
    string input = Console.ReadLine();
    while (input != String.Empty)
    {
        try
        {
            Console.WriteLine("Server echoed: {0}", channel.Echo(input));
        }
        catch (Exception e)
        {
            Console.WriteLine("Error: " + e.Message);
        }
        input = Console.ReadLine();
    }
    

    Im Code wird die Instanz des Kanalobjekts als Proxy für den Dienst verwendet.

  9. Schließen Sie den Kanal und die Factory.

    channel.Close();
    channelFactory.Close();
    

Beispielcode für dieses Tutorial

Der fertige Code sollte wie folgt aussehen. Dieser Code veranschaulicht, wie eine Clientanwendung erstellt wird, wie die Dienstvorgänge aufgerufen werden und wie der Client geschlossen wird, nachdem der Vorgangsaufruf abgeschlossen ist.

using System;
using Microsoft.ServiceBus;
using System.ServiceModel;

namespace Microsoft.ServiceBus.Samples
{
    [ServiceContract(Name = "IEchoContract", Namespace = "https://samples.microsoft.com/ServiceModel/Relay/")]
    public interface IEchoContract
    {
        [OperationContract]
        String Echo(string text);
    }

    public interface IEchoChannel : IEchoContract, IClientChannel { }

    class Program
    {
        static void Main(string[] args)
        {
            ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.AutoDetect;


            Console.Write("Your Service Namespace: ");
            string serviceNamespace = Console.ReadLine();
            Console.Write("Your SAS Key: ");
            string sasKey = Console.ReadLine();



            Uri serviceUri = ServiceBusEnvironment.CreateServiceUri("sb", serviceNamespace, "EchoService");

            TransportClientEndpointBehavior sasCredential = new TransportClientEndpointBehavior();
            sasCredential.TokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider("RootManageSharedAccessKey", sasKey);

            ChannelFactory<IEchoChannel> channelFactory = new ChannelFactory<IEchoChannel>("RelayEndpoint", new EndpointAddress(serviceUri));

            channelFactory.Endpoint.Behaviors.Add(sasCredential);

            IEchoChannel channel = channelFactory.CreateChannel();
            channel.Open();

            Console.WriteLine("Enter text to echo (or [Enter] to exit):");
            string input = Console.ReadLine();
            while (input != String.Empty)
            {
                try
                {
                    Console.WriteLine("Server echoed: {0}", channel.Echo(input));
                }
                catch (Exception e)
                {
                    Console.WriteLine("Error: " + e.Message);
                }
                input = Console.ReadLine();
            }

            channel.Close();
            channelFactory.Close();

        }
    }
}

Ausführen der Anwendungen

  1. Wählen Sie STRG+UMSCHALT+B aus, um die Projektmappe zu erstellen. Mit dieser Aktion werden das Client- und das Dienstprojekt erstellt, die Sie in den vorherigen Schritten erstellt haben.

  2. Vergewissern Sie sich vor dem Ausführen der Clientanwendung, dass die Dienstanwendung ausgeführt wird. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf die Projektmappe EchoService, und wählen Sie anschließend Eigenschaften aus.

  3. Wählen Sie unter Eigenschaftenseiten die Option Allgemeine Eigenschaften>Startprojekt und dann Mehrere Startprojekte aus. Vergewissern Sie sich, dass EchoService als erster Eintrag in der Liste angezeigt wird.

  4. Legen Sie das Feld Aktion sowohl für das Projekt EchoService als auch für das Projekt EchoClient auf Starten fest.

    Seiten mit Projekteigenschaften

  5. Wählen Sie Projektabhängigkeiten aus. Wählen Sie unter Projekte die Option EchoClient aus. Stellen Sie sicher, dass unter Abhängig von die Option EchoService ausgewählt ist.

    Projektabhängigkeiten

  6. Wählen Sie OK aus, um Eigenschaftenseiten zu schließen.

  7. Wählen Sie F5 aus, um beide Projekte auszuführen.

  8. Beide Konsolenfenster werden geöffnet, und Sie werden jeweils zur Angabe des Namespacenamens aufgefordert. Der Dienst muss zuerst ausgeführt werden. Geben Sie daher im Konsolenfenster von EchoService den Namespace ein, und wählen Sie anschließend die EINGABETASTE aus.

  9. Als Nächstes werden Sie von der Konsole zum Eingeben Ihres SAS-Schlüssels aufgefordert. Geben Sie den SAS-Schlüssel ein, und wählen Sie die EINGABETASTE aus.

    Im Folgenden wird eine Beispielausgabe des Konsolenfensters gezeigt. Bei den hier aufgeführten Werten handelt es sich nur um Beispiele.

    Your Service Namespace: myNamespace

    Your SAS Key: <SAS key value>

    Die Dienstanwendung gibt die Adresse, an der sie lauscht, wie im folgenden Beispiel gezeigt im Konsolenfenster aus:

    Service address: sb://mynamespace.servicebus.windows.net/EchoService/

    Press [Enter] to exit

  10. Geben Sie im Konsolenfenster EchoClient die gleichen Informationen wie für die Dienstanwendung ein. Geben Sie die gleichen Dienstnamespace- und SAS-Schlüsselwerte für die Clientanwendung ein.

  11. Nachdem Sie diese Werte eingegeben haben, öffnet der Client einen Kanal zum Dienst und fordert Sie auf, Text einzugeben, wie im folgenden Beispiel für die Konsolenausgabe gezeigt.

    Enter text to echo (or [Enter] to exit):

    Geben Sie Text ein, der an die Dienstanwendung gesendet werden soll, und wählen Sie die EINGABETASTE aus. Dieser Text wird über den Echo-Dienstvorgang an den Dienst gesendet und im Dienstkonsolenfenster ähnlich wie in der folgenden Beispielausgabe angezeigt.

    Echoing: My sample text

    Die Clientanwendung empfängt den Rückgabewert des Echo-Vorgangs (den ursprünglichen Text) und gibt diesen in ihrem Konsolenfenster aus. Der folgende Text ist eine Beispielausgabe des Clientkonsolenfensters.

    Server echoed: My sample text

  12. Sie können auf diese Weise weitere Textnachrichten vom Client an den Dienst senden. Wählen Sie nach Abschluss des Vorgangs im Client- bzw. Dienstkonsolenfenster die EINGABETASTE aus, um beide Anwendungen zu beenden.

Nächste Schritte

Fahren Sie mit dem folgenden Tutorial fort: