Esercitazione su REST per l'inoltro WCF di AzureAzure WCF Relay REST tutorial

Questa esercitazione descrive come creare una semplice applicazione host di inoltro di Azure che espone un'interfaccia basata su REST.This tutorial describes how to build a simple Azure Relay host application that exposes a REST-based interface. REST consente ai client Web, ad esempio un Web browser, di accedere all'API del bus di servizio tramite richieste HTTP.REST enables a web client, such as a web browser, to access the Service Bus APIs through HTTP requests.

In questa esercitazione viene usato il modello di programmazione REST di Windows Communication Foundation (WCF) per creare un servizio REST nel servizio di inoltro di Azure.The tutorial uses the Windows Communication Foundation (WCF) REST programming model to construct a REST service on Azure Relay. Per altre informazioni, vedere Modello di programmazione HTTP Web WCF e Progettazione e implementazione di servizi nella documentazione di WCF.For more information, see WCF REST Programming Model and Designing and Implementing Services in the WCF documentation.

Passaggio 1: Creare uno spazio dei nomiStep 1: Create a namespace

Per usare le funzionalità del servizio d'inoltro di Azure, è prima necessario creare uno spazio dei nomi del servizio.To begin using the relay features in Azure, you must first create a service namespace. Uno spazio dei nomi funge da contenitore di ambito in cui indirizzare le risorse di Azure nell'applicazione.A namespace provides a scoping container for addressing Azure resources within your application. Seguire le istruzioni qui per creare uno spazio dei nomi di inoltro.Follow the instructions here to create a Relay namespace.

Passaggio 2: definire un contratto di servizio WCF basato su REST da usare con il servizio di inoltro di AzureStep 2: Define a REST-based WCF service contract to use with Azure Relay

Quando si crea un servizio basato su REST WCF, è necessario definire il contratto.When you create a WCF REST-style service, you must define the contract. Il contratto specifica quali operazioni sono supportate dall'host.The contract specifies what operations the host supports. Un'operazione di servizio può essere considerata come un metodo del servizio Web.A service operation can be thought of as a web service method. I contratti vengono creati definendo un'interfaccia C++, C# o Visual Basic.Contracts are created by defining a C++, C#, or Visual Basic interface. Ogni metodo dell'interfaccia corrisponde a un'operazione di servizio specifico.Each method in the interface corresponds to a specific service operation. L'attributo ServiceContractAttribute deve essere applicato a ogni interfaccia e l'attributo OperationContractAttribute deve essere applicato a ogni operazione.The ServiceContractAttribute attribute must be applied to each interface, and the OperationContractAttribute attribute must be applied to each operation. Se un metodo di un'interfaccia che ha ServiceContractAttribute non ha OperationContractAttribute, non viene esposto.If a method in an interface that has the ServiceContractAttribute does not have the OperationContractAttribute, that method is not exposed. Il codice usato per eseguire queste attività viene illustrato nell'esempio che segue la procedura.The code used for these tasks is shown in the example following the procedure.

La differenza principale tra un contratto di WCF e un contratto di tipo REST è costituita dall'aggiunta di una proprietà all'attributo OperationContractAttribute: WebGetAttribute.The primary difference between a WCF contract and a REST-style contract is the addition of a property to the OperationContractAttribute: WebGetAttribute. Questa proprietà consente di eseguire il mapping di un metodo dell'interfaccia a un metodo su altro lato dell'interfaccia.This property enables you to map a method in your interface to a method on the other side of the interface. Questo esempio usa l'attributo WebGetAttribute per collegare un metodo al metodo HTTP GET.This example uses the WebGetAttribute attribute to link a method to HTTP GET. In questo modo il bus di servizio può recuperare e interpretare in modo accurato i comandi inviati all'interfaccia.This enables Service Bus to accurately retrieve and interpret commands sent to the interface.

Per creare un contratto con un'interfacciaTo create a contract with an interface

  1. Aprire Visual Studio come amministratore: fare clic con il pulsante destro del mouse sul programma nel menu Start e quindi fare clic su Esegui come amministratore.Open Visual Studio as an administrator: right-click the program in the Start menu, and then click Run as administrator.
  2. Creare un nuovo progetto di applicazione console.Create a new console application project. Scegliere il menu File, selezionare Nuovo e quindi Progetto.Click the File menu and select New, then select Project. Nella finestra di dialogo Nuovo progetto fare clic su Visual C#, selezionare il modello Applicazione console e denominarlo ImageListener.In the New Project dialog box, click Visual C#, select the Console Application template, and name it ImageListener. Usare il valore predefinito Percorso.Use the default Location. Fare clic su OK per creare il progetto.Click OK to create the project.
  3. Per un progetto C#, Visual Studio crea un file Program.cs.For a C# project, Visual Studio creates a Program.cs file. Questa classe contiene un metodo Main() vuoto, necessario per una corretta compilazione del progetto di applicazione console.This class contains an empty Main() method, required for a console application project to build correctly.
  4. Aggiungere al progetto i riferimenti al bus di servizio e a System.ServiceModel.dll installando il pacchetto NuGet del bus di servizio.Add references to Service Bus and System.ServiceModel.dll to the project by installing the Service Bus NuGet package. Questo pacchetto aggiunge automaticamente i riferimenti alle librerie del bus di servizio, oltre all'oggetto System.ServiceModel di WCF.This package automatically adds references to the Service Bus libraries, as well as the WCF System.ServiceModel. In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto ImageListener e quindi scegliere Gestisci pacchetti NuGet.In Solution Explorer, right-click the ImageListener project, and then click Manage NuGet Packages. Fare clic sulla scheda Sfoglia e quindi cercare Microsoft Azure Service Bus.Click the Browse tab, then search for Microsoft Azure Service Bus. Fare clic su Installae accettare le condizioni per l'utilizzo.Click Install, and accept the terms of use.
  5. È necessario aggiungere in modo esplicito un riferimento a System.ServiceModel.Web.dll nel progetto:You must explicitly add a reference to System.ServiceModel.Web.dll to the project:

    a.a. In Esplora soluzioni fare clic con il pulsante destro del mouse sulla cartella Riferimenti nella cartella di progetto e quindi fare clic su Aggiungi riferimento.In Solution Explorer, right-click the References folder under the project folder and then click Add Reference.

    b.b. Nella finestra di dialogo Aggiungi riferimento fare clic sulla scheda Framework sul lato sinistro e nella casella Cerca digitare System.ServiceModel.Web.In the Add Reference dialog box, click the Framework tab on the left-hand side and in the Search box, type System.ServiceModel.Web. Selezionare la casella di controllo System.ServiceModel.Web e quindi fare clic su OK.Select the System.ServiceModel.Web check box, then click OK.

  6. Aggiungere le istruzioni using seguenti all'inizio del file Program.cs.Add the following using statements at the top of the Program.cs file.

    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Web;
    using System.IO;
    

    System.ServiceModel è lo spazio dei nomi che consente l'accesso a livello di codice alle funzionalità di base di WCF.System.ServiceModel is the namespace that enables programmatic access to basic features of WCF. Inoltro WCF usa molti oggetti e attributi di WCF per definire i contratti di servizio.WCF Relay uses many of the objects and attributes of WCF to define service contracts. Questo spazio dei nomi viene usato nella maggior parte delle applicazioni di inoltro.You use this namespace in most of your relay applications. Analogamente, System.ServiceModel.Channels consente di definire il canale, ossia l'oggetto usato per comunicare con il servizio di inoltro di Azure e il Web browser client.Similarly, System.ServiceModel.Channels helps define the channel, which is the object through which you communicate with Azure Relay and the client web browser. Infine, System.ServiceModel.Web contiene i tipi che consentono di creare applicazioni basate sul Web.Finally, System.ServiceModel.Web contains the types that enable you to create web-based applications.

  7. Rinominare lo spazio dei nomi ImageListener in Microsoft.ServiceBus.Samples.Rename the ImageListener namespace to Microsoft.ServiceBus.Samples.

    namespace Microsoft.ServiceBus.Samples
    {
        ...
    
  8. Subito dopo la parentesi graffa aperta nella dichiarazione dello spazio dei nomi, definire una nuova interfaccia denominata IImageContract e applicare l'attributo ServiceContractAttribute all'interfaccia con il valore http://samples.microsoft.com/ServiceModel/Relay/.Directly after the opening curly brace of the namespace declaration, define a new interface named IImageContract and apply the ServiceContractAttribute attribute to the interface with a value of http://samples.microsoft.com/ServiceModel/Relay/. Il valore dello spazio dei nomi è diverso dallo spazio dei nomi usato nell'ambito del codice.The namespace value differs from the namespace that you use throughout the scope of your code. Il valore dello spazio dei nomi viene utilizzato come identificatore univoco per questo contratto e deve disporre delle informazioni sulla versione.The namespace value is used as a unique identifier for this contract, and should have version information. Per altre informazioni, vedere Controllo delle versioni del servizio.For more information, see Service Versioning. Specificando lo spazio dei nomi in modo esplicito si impedisce che il valore predefinito dello spazio dei nomi venga aggiunto al nome del contratto.Specifying the namespace explicitly prevents the default namespace value from being added to the contract name.

    [ServiceContract(Name = "ImageContract", Namespace = "http://samples.microsoft.com/ServiceModel/Relay/RESTTutorial1")]
    public interface IImageContract
    {
    }
    
  9. Nell'interfaccia IImageContract dichiarare un metodo per la singola operazione esposta dal contratto IImageContract nell'interfaccia e applicare l'attributo OperationContractAttribute al metodo da esporre come parte del contratto pubblico del bus di servizio.Within the IImageContract interface, declare a method for the single operation the IImageContract contract exposes in the interface and apply the OperationContractAttribute attribute to the method that you want to expose as part of the public Service Bus contract.

    public interface IImageContract
    {
        [OperationContract]
        Stream GetImage();
    }
    
  10. Nell'attributo OperationContract aggiungere il valore WebGet.In the OperationContract attribute, add the WebGet value.

    public interface IImageContract
    {
        [OperationContract, WebGet]
        Stream GetImage();
    }
    

    Ciò consente al servizio di inoltro di instradare le richieste HTTP GET a GetImage e di convertire i valori restituiti di GetImage in una risposta HTTP GETRESPONSE.Doing so enables the relay service to route HTTP GET requests to GetImage, and to translate the return values of GetImage into an HTTP GETRESPONSE reply. Più avanti nell'esercitazione si utilizzerà un Web browser per accedere a questo metodo e per visualizzare l'immagine nel browser.Later in the tutorial, you will use a web browser to access this method, and to display the image in the browser.

  11. Subito dopo la definizione di IImageContract, dichiarare un canale che eredita dalle interfacce IImageContract e IClientChannel.Directly after the IImageContract definition, declare a channel that inherits from both the IImageContract and IClientChannel interfaces.

    public interface IImageChannel : IImageContract, IClientChannel { }
    

    Un canale è l'oggetto WCF tramite il quale il servizio e il client si scambiano le informazioni.A channel is the WCF object through which the service and client pass information to each other. In seguito verrà creato il canale nell'applicazione host.Later, you create the channel in your host application. A questo punto, il servizio di inoltro di Azure usa questo canale per passare le richieste HTTP GET dal browser all'implementazione di GetImage.Azure Relay then uses this channel to pass the HTTP GET requests from the browser to your GetImage implementation. L'inoltro usa il canale anche per richiedere il valore restituito GetImage e convertirlo in una risposta HTTP GETRESPONSE per il browser client.The relay also uses the channel to take the GetImage return value and translate it into an HTTP GETRESPONSE for the client browser.

  12. Dal menu Compila, fare clic su Compila soluzione per verificare la correttezza del lavoro svolto finora.From the Build menu, click Build Solution to confirm the accuracy of your work so far.

EsempioExample

L'esempio di codice seguente illustra un'interfaccia di base che definisce un contratto dell'inoltro WCF.The following code shows a basic interface that defines a WCF Relay contract.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Web;
using System.IO;

namespace Microsoft.ServiceBus.Samples
{

    [ServiceContract(Name = "IImageContract", Namespace = "http://samples.microsoft.com/ServiceModel/Relay/")]
    public interface IImageContract
    {
        [OperationContract, WebGet]
        Stream GetImage();
    }

    public interface IImageChannel : IImageContract, IClientChannel { }

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

Passaggio 3: implementare un contratto di servizio WCF basato su REST per utilizzare il bus di servizioStep 3: Implement a REST-based WCF service contract to use Service Bus

La creazione di un servizio di inoltro WCF basato su REST richiede prima la creazione del contratto, che viene definito usando un'interfaccia.Creating a REST-style WCF Relay service requires that you first create the contract, which is defined by using an interface. Il passaggio successivo consiste nell'implementazione dell'interfaccia.The next step is to implement the interface. Ciò comporta la creazione di una classe denominata ImageService che implementa l’interfaccia IImageContract definita dall'utente.This involves creating a class named ImageService that implements the user-defined IImageContract interface. Dopo aver implementato il contratto, è quindi necessario configurare l'interfaccia utilizzando un file App.config.After you implement the contract, you then configure the interface using an App.config file. Il file di configurazione contiene le informazioni necessarie per l'applicazione, ad esempio il nome del servizio, il nome del contratto e il tipo di protocollo usato per comunicare con il servizio di inoltro.The configuration file contains necessary information for the application, such as the name of the service, the name of the contract, and the type of protocol that is used to communicate with the relay service. Il codice usato per eseguire queste attività viene fornito nell'esempio che segue la procedura.The code used for these tasks is provided in the example following the procedure.

Come per i passaggi precedenti, è impercettibile la differenza tra l'implementazione di un contratto di tipo REST e di un contratto dell'inoltro WCF.As with the previous steps, there is very little difference between implementing a REST-style contract and a WCF Relay contract.

Per implementare un contratto del bus di servizio di tipo RESTTo implement a REST-style Service Bus contract

  1. Creare una nuova classe denominata ImageService direttamente dopo la definizione dell'interfaccia IImageContract.Create a new class named ImageService directly after the definition of the IImageContract interface. La classe ImageService implementa l'interfaccia IImageContract.The ImageService class implements the IImageContract interface.

    class ImageService : IImageContract
    {
    }
    

    Analogamente ad altre implementazioni di interfaccia, è possibile implementare la definizione in un altro file.Similar to other interface implementations, you can implement the definition in a different file. Tuttavia, per questa esercitazione, l'implementazione è presente nello stesso file di definizione dell'interfaccia e del metodo Main().However, for this tutorial, the implementation appears in the same file as the interface definition and Main() method.

  2. Applicare l'attributo ServiceBehaviorAttribute alla classe IImageService per indicare che la classe è un'implementazione di un contratto WCF.Apply the ServiceBehaviorAttribute attribute to the IImageService class to indicate that the class is an implementation of a WCF contract.

    [ServiceBehavior(Name = "ImageService", Namespace = "http://samples.microsoft.com/ServiceModel/Relay/")]
    class ImageService : IImageContract
    {
    }
    

    Come accennato in precedenza, questo spazio dei nomi non è uno spazio dei nomi tradizionale.As mentioned previously, this namespace is not a traditional namespace. Infatti, fa parte dell'architettura WCF che identifica il contratto.Instead, it is part of the WCF architecture that identifies the contract. Per altre informazioni, vedere l'articolo Nomi di contratto dati nella documentazione di WCF.For more information, see the Data Contract Names article in the WCF documentation.

  3. Aggiungere un'immagine con estensione jpg al progetto.Add a .jpg image to your project.

    Si tratta di un'immagine che viene visualizzata nel browser di ricezione dal servizio.This is a picture that the service displays in the receiving browser. Fare clic con il pulsante destro del mouse sul progetto e quindi scegliere Aggiungi.Right-click your project, then click Add. Fare clic su Elemento esistente.Then click Existing Item. Usare la finestra di dialogo Aggiungi elemento esistente per trovare un'immagine con estensione jpg appropriata e quindi fare clic su Aggiungi.Use the Add Existing Item dialog box to browse to an appropriate .jpg, and then click Add.

    Quando si aggiunge il file, assicurarsi che Tutti i file sia selezionato nell'elenco a discesa accanto al campo Nome file:.When adding the file, make sure that All Files is selected in the drop-down list next to the File name: field. Nella parte restante di questa esercitazione si presuppone che il nome dell'immagine sia "image.jpg".The rest of this tutorial assumes that the name of the image is "image.jpg". Se si dispone di un file diverso, è necessario rinominare l'immagine o modificare il codice per compensare.If you have a different file, you must rename the image, or change your code to compensate.

  4. Per assicurarsi che il servizio in esecuzione riesca a trovare il file di immagine, in Esplora soluzioni fare clic con il pulsante destro del mouse sul file di immagine e scegliere Proprietà.To make sure that the running service can find the image file, in Solution Explorer right-click the image file, then click Properties. Nel riquadro Proprietà impostare il valore di Copia in directory di output su Copia se più recente.In the Properties pane, set Copy to Output Directory to Copy if newer.
  5. Aggiungere al progetto un riferimento all'assembly System.Drawing.dll e anche le istruzioni using associate riportate qui sotto.Add a reference to the System.Drawing.dll assembly to the project, and also add the following associated using statements.

    using System.Drawing;
    using System.Drawing.Imaging;
    using Microsoft.ServiceBus;
    using Microsoft.ServiceBus.Web;
    
  6. Nella classe ImageService aggiungere il costruttore seguente che consente di caricare la bitmap e prepararla per l'invio al browser client.In the ImageService class, add the following constructor that loads the bitmap and prepares to send it to the client browser.

    class ImageService : IImageContract
    {
        const string imageFileName = "image.jpg";
    
        Image bitmap;
    
        public ImageService()
        {
            this.bitmap = Image.FromFile(imageFileName);
        }
    }
    
  7. Direttamente dopo il codice precedente, aggiungere il metodo GetImage seguente nella classe ImageService per restituire un messaggio HTTP che contiene l'immagine.Directly after the previous code, add the following GetImage method in the ImageService class to return an HTTP message that contains the image.

    public Stream GetImage()
    {
        MemoryStream stream = new MemoryStream();
        this.bitmap.Save(stream, ImageFormat.Jpeg);
    
        stream.Position = 0;
        WebOperationContext.Current.OutgoingResponse.ContentType = "image/jpeg";
    
        return stream;
    }
    

    Questa implementazione usa MemoryStream per recuperare l'immagine e prepararla per la trasmissione in streaming al browser.This implementation uses MemoryStream to retrieve the image and prepare it for streaming to the browser. Avvia la posizione del flusso da zero, dichiara il contenuto di flusso come jpeg e trasmette le informazioni.It starts the stream position at zero, declares the stream content as a jpeg, and streams the information.

  8. Dal menu Compila scegliere Compila soluzione.From the Build menu, click Build Solution.

Per definire la configurazione per l'esecuzione del servizio Web sul bus di servizioTo define the configuration for running the web service on Service Bus

  1. In Esplora soluzioni fare doppio clic sul file App.config per aprirlo nell'editor di Visual Studio.In Solution Explorer, double-click App.config to open it in the Visual Studio editor.

    Il file App.config include il nome del servizio, l'endpoint (ovvero il percorso esposto dal servizio di inoltro di Azure per le comunicazioni tra client e host) e il binding (ossia il tipo di protocollo usato per la comunicazione).The App.config file includes the service name, endpoint (that is, the location Azure Relay exposes for clients and hosts to communicate with each other), and binding (the type of protocol that is used to communicate). La differenza principale è che l'endpoint di servizio configurato fa riferimento a un'associazione WebHttpRelayBinding.The main difference here is that the configured service endpoint refers to a WebHttpRelayBinding binding.

  2. L'elemento XML <system.serviceModel> è un elemento WCF che definisce uno o più servizi.The <system.serviceModel> XML element is a WCF element that defines one or more services. In questo caso, viene utilizzato per definire il nome del servizio e l'endpoint.Here, it is used to define the service name and endpoint. Nella parte inferiore dell'elemento <system.serviceModel>, ma sempre in <system.serviceModel>, aggiungere un elemento <bindings> che include il contenuto seguente.At the bottom of the <system.serviceModel> element (but still within <system.serviceModel>), add a <bindings> element that has the following content. In tal modo, vengono definite le associazioni utilizzate nell'applicazione.This defines the bindings used in the application. È possibile definire più associazioni, ma per questa esercitazione se ne definisce una sola.You can define multiple bindings, but for this tutorial you are defining only one.

    <bindings>
        <!-- Application Binding -->
        <webHttpRelayBinding>
            <binding name="default">
                <security relayClientAuthenticationType="None" />
            </binding>
        </webHttpRelayBinding>
    </bindings>
    

    Il codice precedente definisce un'associazione WebHttpRelayBinding dell'inoltro WCF con relayClientAuthenticationType impostato su None.The previous code defines a WCF Relay WebHttpRelayBinding binding with relayClientAuthenticationType set to None. Questa impostazione indica che un endpoint che utilizza questa associazione non richiede le credenziali client.This setting indicates that an endpoint using this binding does not require a client credential.

  3. Dopo l'elemento <bindings> aggiungere un elemento <services>.After the <bindings> element, add a <services> element. Come per le associazioni, è possibile definire più servizi in un solo file di configurazione.Similar to the bindings, you can define multiple services in a single configuration file. Tuttavia, per questa esercitazione, se ne definisce solo uno.However, for this tutorial, you define only one.

    <services>
        <!-- Application Service -->
        <service name="Microsoft.ServiceBus.Samples.ImageService"
             behaviorConfiguration="default">
            <endpoint name="RelayEndpoint"
                    contract="Microsoft.ServiceBus.Samples.IImageContract"
                    binding="webHttpRelayBinding"
                    bindingConfiguration="default"
                    behaviorConfiguration="sbTokenProvider"
                    address="" />
        </service>
    </services>
    

    Questo passaggio consente di configurare un servizio che usa il valore predefinito webHttpRelayBinding definito in precedenza.This step configures a service that uses the previously defined default webHttpRelayBinding. Usa anche il valore predefinito sbTokenProvider, definito nel passaggio successivo.It also uses the default sbTokenProvider, which is defined in the next step.

  4. Dopo l'elemento <services> creare un elemento <behaviors> con il contenuto seguente, sostituendo "SAS_KEY" con la chiave di firma di accesso condiviso ottenuta in precedenza dal portale di Azure.After the <services> element, create a <behaviors> element with the following content, replacing "SAS_KEY" with the Shared Access Signature (SAS) key you previously obtained from the Azure portal.

    <behaviors>
        <endpointBehaviors>
            <behavior name="sbTokenProvider">
                <transportClientEndpointBehavior>
                    <tokenProvider>
                        <sharedAccessSignature keyName="RootManageSharedAccessKey" key="YOUR_SAS_KEY" />
                    </tokenProvider>
                </transportClientEndpointBehavior>
            </behavior>
            </endpointBehaviors>
            <serviceBehaviors>
                <behavior name="default">
                    <serviceDebug httpHelpPageEnabled="false" httpsHelpPageEnabled="false" />
                </behavior>
            </serviceBehaviors>
    </behaviors>
    
  5. Nell'elemento <appSettings>, sempre nel file App.config, sostituire il valore dell'intera stringa di connessione con la stringa di connessione ottenuta prima dal portale.Still in App.config, in the <appSettings> element, replace the entire connection string value with the connection string you previously obtained from the portal.

    <appSettings>
       <!-- Service Bus specific app settings for messaging connections -->
       <add key="Microsoft.ServiceBus.ConnectionString"
           value="Endpoint=sb://yourNamespace.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=YOUR_SAS_KEY"/>
    </appSettings>
    
  6. Scegliere Compila soluzione dal menu Compila per compilare l'intera soluzione.From the Build menu, click Build Solution to build the entire solution.

EsempioExample

Il codice seguente illustra l'implementazione del contratto e del servizio per un servizio basato su REST eseguito nel bus di servizio usando l'associazione WebHttpRelayBinding.The following code shows the contract and service implementation for a REST-based service that is running on Service Bus using the WebHttpRelayBinding binding.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Web;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using Microsoft.ServiceBus;
using Microsoft.ServiceBus.Web;

namespace Microsoft.ServiceBus.Samples
{


    [ServiceContract(Name = "ImageContract", Namespace = "http://samples.microsoft.com/ServiceModel/Relay/")]
    public interface IImageContract
    {
        [OperationContract, WebGet]
        Stream GetImage();
    }

    public interface IImageChannel : IImageContract, IClientChannel { }

    [ServiceBehavior(Name = "ImageService", Namespace = "http://samples.microsoft.com/ServiceModel/Relay/")]
    class ImageService : IImageContract
    {
        const string imageFileName = "image.jpg";

        Image bitmap;

        public ImageService()
        {
            this.bitmap = Image.FromFile(imageFileName);
        }

        public Stream GetImage()
        {
            MemoryStream stream = new MemoryStream();
            this.bitmap.Save(stream, ImageFormat.Jpeg);

            stream.Position = 0;
            WebOperationContext.Current.OutgoingResponse.ContentType = "image/jpeg";

            return stream;
        }
    }

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

Nell'esempio seguente viene illustrato il file App.config associato al servizio.The following example shows the App.config file associated with the service.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/>
    </startup>
    <system.serviceModel>
        <extensions>
            <!-- In this extension section we are introducing all known service bus extensions. User can remove the ones they don't need. -->
            <behaviorExtensions>
                <add name="connectionStatusBehavior"
                    type="Microsoft.ServiceBus.Configuration.ConnectionStatusElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
                <add name="transportClientEndpointBehavior"
                    type="Microsoft.ServiceBus.Configuration.TransportClientEndpointBehaviorElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
                <add name="serviceRegistrySettings"
                    type="Microsoft.ServiceBus.Configuration.ServiceRegistrySettingsElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
            </behaviorExtensions>
            <bindingElementExtensions>
                <add name="netMessagingTransport"
                    type="Microsoft.ServiceBus.Messaging.Configuration.NetMessagingTransportExtensionElement, Microsoft.ServiceBus,  Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
                <add name="tcpRelayTransport"
                    type="Microsoft.ServiceBus.Configuration.TcpRelayTransportElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
                <add name="httpRelayTransport"
                    type="Microsoft.ServiceBus.Configuration.HttpRelayTransportElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
                <add name="httpsRelayTransport"
                    type="Microsoft.ServiceBus.Configuration.HttpsRelayTransportElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
                <add name="onewayRelayTransport"
                    type="Microsoft.ServiceBus.Configuration.RelayedOnewayTransportElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
            </bindingElementExtensions>
            <bindingExtensions>
                <add name="basicHttpRelayBinding"
                    type="Microsoft.ServiceBus.Configuration.BasicHttpRelayBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
                <add name="webHttpRelayBinding"
                    type="Microsoft.ServiceBus.Configuration.WebHttpRelayBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
                <add name="ws2007HttpRelayBinding"
                    type="Microsoft.ServiceBus.Configuration.WS2007HttpRelayBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
                <add name="netTcpRelayBinding"
                    type="Microsoft.ServiceBus.Configuration.NetTcpRelayBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
                <add name="netOnewayRelayBinding"
                    type="Microsoft.ServiceBus.Configuration.NetOnewayRelayBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
                <add name="netEventRelayBinding"
                    type="Microsoft.ServiceBus.Configuration.NetEventRelayBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
                <add name="netMessagingBinding"
                    type="Microsoft.ServiceBus.Messaging.Configuration.NetMessagingBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
            </bindingExtensions>
        </extensions>
      <bindings>
        <!-- Application Binding -->
        <webHttpRelayBinding>
          <binding name="default">
            <security relayClientAuthenticationType="None" />
          </binding>
        </webHttpRelayBinding>
      </bindings>
      <services>
        <!-- Application Service -->
        <service name="Microsoft.ServiceBus.Samples.ImageService"
             behaviorConfiguration="default">
          <endpoint name="RelayEndpoint"
                  contract="Microsoft.ServiceBus.Samples.IImageContract"
                  binding="webHttpRelayBinding"
                  bindingConfiguration="default"
                  behaviorConfiguration="sbTokenProvider"
                  address="" />
        </service>
      </services>
      <behaviors>
        <endpointBehaviors>
          <behavior name="sbTokenProvider">
            <transportClientEndpointBehavior>
              <tokenProvider>
                <sharedAccessSignature keyName="RootManageSharedAccessKey" key="YOUR_SAS_KEY" />
              </tokenProvider>
            </transportClientEndpointBehavior>
          </behavior>
        </endpointBehaviors>
        <serviceBehaviors>
          <behavior name="default">
            <serviceDebug httpHelpPageEnabled="false" httpsHelpPageEnabled="false" />
          </behavior>
        </serviceBehaviors>
      </behaviors>
    </system.serviceModel>
    <appSettings>
        <!-- Service Bus specific app setings for messaging connections -->
        <add key="Microsoft.ServiceBus.ConnectionString"
            value="Endpoint=sb://yourNamespace.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey="YOUR_SAS_KEY"/>
    </appSettings>
</configuration>

Passaggio 4: eseguire l'hosting del servizio WCF basato su REST per usare il servizio di inoltro di AzureStep 4: Host the REST-based WCF service to use Azure Relay

Questo passaggio descrive come eseguire un servizio Web usando un'applicazione console con l'inoltro WCF.This step describes how to run a web service using a console application with WCF Relay. Un elenco completo del codice scritto in questo passaggio viene fornito nell’esempio che segue la procedura.A complete listing of the code written in this step is provided in the example following the procedure.

Per creare un indirizzo di base per il servizioTo create a base address for the service

  1. Nella dichiarazione della funzione Main() creare una variabile per archiviare lo spazio dei nomi del progetto.In the Main() function declaration, create a variable to store the namespace of your project. Assicurarsi di sostituire yourNamespace con il nome dello spazio dei nomi di inoltro creato prima.Make sure to replace yourNamespace with the name of the Relay namespace you created previously.

    string serviceNamespace = "yourNamespace";
    

    Il bus di servizio utilizza il nome dello spazio dei nomi per creare un URI univoco.Service Bus uses the name of your namespace to create a unique URI.

  2. Creare un'istanza di Uri per l'indirizzo di base del servizio basato sullo spazio dei nomi.Create a Uri instance for the base address of the service that is based on the namespace.

    Uri address = ServiceBusEnvironment.CreateServiceUri("https", serviceNamespace, "Image");
    

Per creare e configurare l'host del servizio WebTo create and configure the web service host

  • Creare l'host del servizio Web utilizzando l'indirizzo URI creato precedentemente in questa sezione.Create the web service host, using the URI address created earlier in this section.

    WebServiceHost host = new WebServiceHost(typeof(ImageService), address);
    

    L'host del servizio è l'oggetto WCF che crea un'istanza dell'applicazione host.The service host is the WCF object that instantiates the host application. In questo esempio viene passato il tipo di host da creare, ovvero ImageService, nonché l'indirizzo al quale si vuole esporre l'applicazione host.This example passes it the type of host you want to create (an ImageService), and also the address at which you want to expose the host application.

Per eseguire l'host del servizio WebTo run the web service host

  1. Aprire il servizio.Open the service.

    host.Open();
    

    Il servizio è in esecuzione.The service is now running.

  2. Visualizzare un messaggio che indica che il servizio è in esecuzione e come arrestare il servizio.Display a message indicating that the service is running, and how to stop the service.

    Console.WriteLine("Copy the following address into a browser to see the image: ");
    Console.WriteLine(address + "GetImage");
    Console.WriteLine();
    Console.WriteLine("Press [Enter] to exit");
    Console.ReadLine();
    
  3. Al termine, chiudere l'host del servizio.When finished, close the service host.

    host.Close();
    

EsempioExample

Nell'esempio seguente vengono inclusi il contratto di servizio e l'implementazione dei passaggi precedenti dell'esercitazione e viene ospitato il servizio in un'applicazione console.The following example includes the service contract and implementation from previous steps in the tutorial and hosts the service in a console application. Compilare il codice seguente in un eseguibile denominato ImageListener.exe.Compile the following code into an executable named ImageListener.exe.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Web;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using Microsoft.ServiceBus;
using Microsoft.ServiceBus.Web;

namespace Microsoft.ServiceBus.Samples
{

    [ServiceContract(Name = "ImageContract", Namespace = "http://samples.microsoft.com/ServiceModel/Relay/")]
    public interface IImageContract
    {
        [OperationContract, WebGet]
        Stream GetImage();
    }

    public interface IImageChannel : IImageContract, IClientChannel { }

    [ServiceBehavior(Name = "ImageService", Namespace = "http://samples.microsoft.com/ServiceModel/Relay/")]
    class ImageService : IImageContract
    {
        const string imageFileName = "image.jpg";

        Image bitmap;

        public ImageService()
        {
            this.bitmap = Image.FromFile(imageFileName);
        }

        public Stream GetImage()
        {
            MemoryStream stream = new MemoryStream();
            this.bitmap.Save(stream, ImageFormat.Jpeg);

            stream.Position = 0;
            WebOperationContext.Current.OutgoingResponse.ContentType = "image/jpeg";

            return stream;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            string serviceNamespace = "InsertServiceNamespaceHere";
            Uri address = ServiceBusEnvironment.CreateServiceUri("https", serviceNamespace, "Image");

            WebServiceHost host = new WebServiceHost(typeof(ImageService), address);
            host.Open();

            Console.WriteLine("Copy the following address into a browser to see the image: ");
            Console.WriteLine(address + "GetImage");
            Console.WriteLine();
            Console.WriteLine("Press [Enter] to exit");
            Console.ReadLine();

            host.Close();
        }
    }
}

Compilazione del codiceCompiling the code

Dopo aver compilato la soluzione, effettuare le operazioni seguenti per eseguire l'applicazione:After building the solution, do the following to run the application:

  1. Premere F5 o passare al percorso del file eseguibile ImageListener\bin\Debug\ImageListener.exe per eseguire il servizio.Press F5, or browse to the executable file location (ImageListener\bin\Debug\ImageListener.exe), to run the service. Mantenere l'app in esecuzione perché verrà usata per eseguire il passaggio successivo.Keep the app running, as it's required to perform the next step.
  2. Copiare e incollare l'indirizzo dal prompt dei comandi in un browser per visualizzare l'immagine.Copy and paste the address from the command prompt into a browser to see the image.
  3. Al termine, premere INVIO nella finestra del prompt dei comandi per chiudere l'app.When you are finished, press Enter in the command prompt window to close the app.

Passaggi successiviNext steps

A questo punto, dopo avere creato un'applicazione che usa il servizio di inoltro di Azure, vedere gli articoli seguenti per altre informazioni:Now that you've built an application that uses the Azure Relay service, see the following articles to learn more: