Esporre un servizio WCF locale a un'applicazione Web nel cloud usando Inoltro di Azure

Questo articolo illustra come compilare un'applicazione cloud ibrida con Microsoft Azure e Visual Studio. Si crea un'applicazione che usa più risorse di Azure nel cloud. Questa esercitazione illustra come:

  • Creare o adattare un servizio Web esistente utilizzabile in una soluzione Web.
  • Come usare il servizio di inoltro di Windows Communication Foundation (WCF) di Azure per condividere i dati tra un'applicazione di Azure e un servizio Web ospitato altrove.

In questa esercitazione si eseguiranno le attività seguenti:

  • Installare i prerequisiti per questa esercitazione.
  • Esaminare lo scenario
  • Creare uno spazio dei nomi.
  • Creare un server locale.
  • Creare un'applicazione ASP .NET.
  • Eseguire l'app in locale.
  • Distribuire l'app Web in Azure.
  • Eseguire l'app in Azure.

Prerequisiti

Per completare questa esercitazione è necessario soddisfare i prerequisiti seguenti:

Vantaggi del servizio d'inoltro di Azure con soluzioni ibride

Le soluzioni aziendali sono in genere costituite da una combinazione di codice personalizzato e funzionalità esistenti. Il codice personalizzato affronta i requisiti aziendali nuovi e univoci. Le soluzioni e i sistemi già presenti forniscono funzionalità esistenti.

Da qualche tempo gli architetti di soluzioni hanno iniziato a usare il cloud per semplificare la gestione dei requisiti di scalabilità e ridurre i costi operativi. In questo modo, trovano che gli asset di servizio esistenti che vorrebbero usare come blocchi predefiniti per le proprie soluzioni si trovano all'interno del firewall aziendale e sono facilmente raggiungibili dalla soluzione cloud. Molti servizi interni non sono compilati o ospitati in modo che possano essere facilmente esposti nella rete perimetrale aziendale.

Inoltro di Azure accetta servizi Web WCF esistenti e rende questi servizi accessibili in modo sicuro alle soluzioni esterne al perimetro aziendale senza richiedere modifiche intrusive all'infrastruttura di rete aziendale. Tali servizi d'inoltro sono comunque ospitati all'interno dell'ambiente esistente, ma delegano l'ascolto delle sessioni e delle richieste in ingresso al servizio d'inoltro ospitato nel cloud. Il servizio d'inoltro di Azure protegge anche quei servizi dall'accesso non autorizzato tramite l'autenticazione con firma di accesso condiviso.

Esaminare lo scenario

In questa esercitazione viene creato un sito Web ASP.NET che consente di visualizzare un elenco di prodotti nella pagina relativa all'inventario dei prodotti.

Scenario

In questa esercitazione si presuppone che le informazioni sui prodotti siano già disponibili in un sistema locale esistente e che per accedere a tale sistema venga usato il servizio d'inoltro di Azure. Un servizio Web eseguito in una semplice applicazione console simula questa situazione. Contiene un set di prodotti in memoria. È possibile eseguire questa applicazione console nel proprio computer e distribuire il ruolo Web in Azure. In questo modo, si vedrà come il ruolo Web in esecuzione nel data center di Azure chiama nel computer. Questa chiamata avviene anche se il computer sarà quasi certamente dietro almeno un firewall e un livello NAT (Network Address Translation).

Impostazione dell'ambiente di sviluppo

Prima di iniziare a sviluppare applicazioni Azure, è necessario scaricare gli strumenti e configurare l'ambiente di sviluppo:

  1. Installare Azure SDK per .NET dalla pagina di download di SDK.
  2. Nella colonna .NET scegliere la versione di Visual Studio in uso. Questa esercitazione usa Visual Studio 2019.
  3. Quando viene richiesto di eseguire o salvare il programma di installazione, selezionare Esegui.
  4. Nella finestra di dialogo Programma di installazione piattaforma Web selezionare Installa e continuare con l'installazione.

Al termine dell'installazione, hai tutto il necessario per iniziare a sviluppare l'app. Nell'SDK sono disponibili gli strumenti che consentono di sviluppare con facilità applicazioni per Azure in Visual Studio.

Creare uno spazio dei nomi

Il primo passaggio consiste nel creare uno spazio dei nomi e nell'ottenere una chiave di firma di accesso condiviso. Uno spazio dei nomi fornisce un limite per ogni applicazione esposta tramite il servizio di inoltro. Una chiave di firma di accesso condiviso viene automaticamente generata dal sistema quando viene creato uno spazio dei nomi del servizio. La combinazione di spazio dei nomi servizio e chiave di firma di accesso condiviso fornisce le credenziali che consentono ad Azure di autenticare l'accesso a un'applicazione.

  1. Accedi al portale di Azure.

  2. Scegliere Tutti i servizi dal menu a sinistra. Selezionare Integrazione, cercare Inoltro, spostare il mouse su Inoltro e quindi selezionare Crea.

    Screenshot showing the selection of Relays -> Create button.

  3. Nella pagina Crea spazio dei nomi seguire questa procedura:

    1. Scegliere una sottoscrizione di Azure in cui creare lo spazio dei nomi.

    2. Per Gruppo di risorse scegliere un gruppo di risorse esistente in cui inserire lo spazio dei nomi oppure crearne uno nuovo.

    3. Immettere un nome per lo spazio dei nomi Relay.

    4. Selezionare l'area in cui deve essere ospitato lo spazio dei nomi.

    5. Selezionare Rivedi e crea nella parte inferiore della pagina.

      Screenshot showing the Create namespace page.

    6. Nella pagina Rivedi e crea selezionare Crea.

    7. Dopo alcuni minuti viene visualizzata la pagina Inoltro per lo spazio dei nomi .

      Screenshot showing the home page for Relay namespace.

Ottenere le credenziali di gestione

  1. Nella pagina Inoltro selezionare Criteri di accesso condiviso nel menu a sinistra. `

  2. Nella pagina Criteri di accesso condiviso selezionare RootManageSharedAccessKey.

  3. In Criteri di firma di accesso condiviso: RootManageSharedAccessKey selezionare il pulsante Copia accanto a Stringa di Connessione primaria. La stringa di connessione viene copiata negli Appunti per un uso successivo. Incollare questo valore nel Blocco note o in un'altra posizione temporanea.

  4. Ripetere il passaggio precedente per copiare e incollare il valore di Chiave primaria in un percorso temporaneo per usarlo in seguito.

    Screenshot showing the connection info for Relay namespace.

Creare un server locale

In primo luogo, viene creato un sistema di catalogo prodotti locale fittizio. Il progetto è un'applicazione console di Visual Studio e usa il pacchetto NuGet del bus di servizio di Azure per includere le librerie e le impostazioni di configurazione del bus di servizio.

  1. Avviare Microsoft Visual Studio come amministratore. A tale scopo, fare clic con il tasto destro del mouse sull'icona del programma Visual Studio e selezionare Esegui come amministratore.

  2. In Visual Studio selezionare Crea un nuovo progetto.

  3. In Crea un nuovo progetto selezionare App console (.NET Framework) per C# e selezionare Avanti.

  4. Assegnare al progetto il nome ProductsServer e selezionare Crea.

    Configure your new project

  5. In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto ProductsServer, quindi scegliere Gestisci pacchetti NuGet.

  6. Selezionare Sfoglia, quindi cercare e scegliere WindowsAzure.ServiceBus. Selezionare Installa e accettare le condizioni per l'utilizzo.

    Select NuGet package

    I riferimenti agli assembly client necessari sono ora disponibili.

  7. Aggiungere una nuova classe per il contratto dei prodotti. In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto ProductsServer e scegliere Aggiungi>classe.

  8. In Nome immettere il nome ProductsContract.cs e selezionare Aggiungi.

Apportare le modifiche di codice seguenti alla soluzione:

  1. In ProductsContract.cs sostituire la definizione dello spazio dei nomi con il codice seguente, che consente di definire il contratto per il servizio.

    namespace ProductsServer
    {
        using System.Collections.Generic;
        using System.Runtime.Serialization;
        using System.ServiceModel;
    
        // Define the data contract for the service
        [DataContract]
        // Declare the serializable properties.
        public class ProductData
        {
            [DataMember]
            public string Id { get; set; }
            [DataMember]
            public string Name { get; set; }
            [DataMember]
            public string Quantity { get; set; }
        }
    
        // Define the service contract.
        [ServiceContract]
        interface IProducts
        {
            [OperationContract]
            IList<ProductData> GetProducts();
    
        }
    
        interface IProductsChannel : IProducts, IClientChannel
        {
        }
    }
    
  2. In Program.cs sostituire la definizione dello spazio dei nomi con il codice seguente, che aggiunge il servizio profilo e l'host per esso.

    namespace ProductsServer
    {
        using System;
        using System.Linq;
        using System.Collections.Generic;
        using System.ServiceModel;
    
        // Implement the IProducts interface.
        class ProductsService : IProducts
        {
    
            // Populate array of products for display on website
            ProductData[] products =
                new []
                    {
                        new ProductData{ Id = "1", Name = "Rock",
                                         Quantity = "1"},
                        new ProductData{ Id = "2", Name = "Paper",
                                         Quantity = "3"},
                        new ProductData{ Id = "3", Name = "Scissors",
                                         Quantity = "5"},
                        new ProductData{ Id = "4", Name = "Well",
                                         Quantity = "2500"},
                    };
    
            // Display a message in the service console application
            // when the list of products is retrieved.
            public IList<ProductData> GetProducts()
            {
                Console.WriteLine("GetProducts called.");
                return products;
            }
    
        }
    
        class Program
        {
            // Define the Main() function in the service application.
            static void Main(string[] args)
            {
                var sh = new ServiceHost(typeof(ProductsService));
                sh.Open();
    
                Console.WriteLine("Press ENTER to close");
                Console.ReadLine();
    
                sh.Close();
            }
        }
    }
    
  3. In Esplora soluzioni fare doppio clic su App.config per aprire il file nell'editor di Visual Studio. Nella parte inferiore dell'elemento, ma ancora all'interno <system.ServiceModel><system.ServiceModel>di , aggiungere il codice XML seguente.

    Importante

    Sostituire yourServiceNamespace con il nome dello spazio dei nomi e yourKey con la chiave di firma di accesso condiviso recuperata in precedenza dal portale:

      <services>
         <service name="ProductsServer.ProductsService">
           <endpoint address="sb://yourServiceNamespace.servicebus.windows.net/products" binding="netTcpRelayBinding" contract="ProductsServer.IProducts" behaviorConfiguration="products"/>
         </service>
      </services>
      <behaviors>
         <endpointBehaviors>
           <behavior name="products">
             <transportClientEndpointBehavior>
                <tokenProvider>
                   <sharedAccessSignature keyName="RootManageSharedAccessKey" key="yourKey" />
                </tokenProvider>
             </transportClientEndpointBehavior>
           </behavior>
         </endpointBehaviors>
      </behaviors>
    

    Nota

    L'errore causato da transportClientEndpointBehavior è solo un avviso e non è un problema di blocco per questo esempio.

  4. Sempre in App.config, nell'elemento <appSettings> sostituire il valore stringa di connessione con il stringa di connessione ottenuto in precedenza dal portale.

    <appSettings>
       <!-- Service Bus specific app settings for messaging connections -->
       <add key="Microsoft.ServiceBus.ConnectionString"
           value="Endpoint=sb://yourNamespace.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=yourKey"/>
    </appSettings>
    
  5. Selezionare CTRL+MAIUSC+B oppure compila >soluzione per compilare l'applicazione e verificare l'accuratezza del lavoro fino a questo momento.

Creare un'applicazione ASP.NET

In questa sezione viene creata una semplice applicazione ASP.NET per visualizzare i dati recuperati dal servizio dei prodotti.

Creare il progetto

  1. Assicurarsi che Visual Studio sia in esecuzione come amministratore.

  2. In Visual Studio selezionare Crea un nuovo progetto.

  3. In Crea un nuovo progetto selezionare ASP.NET'applicazione Web (.NET Framework) per C# e selezionare Avanti.

  4. Assegnare al progetto il nome ProductsPortal e selezionare Crea.

  5. In Crea una nuova applicazione Web ASP.NET scegliere MVC e selezionare Cambia in Autenticazione.

    Select ASP .NET Web Application

  6. In Modifica autenticazione scegliere Nessuna autenticazione e quindi selezionare OK. Per questa esercitazione si sta distribuendo un'app che non richiede l'accesso di un utente.

    Specify authentication

  7. Tornare in Crea una nuova applicazione Web ASP.NET selezionare Crea per creare l'app MVC.

  8. Configurare le risorse di Azure per una nuova app Web. Seguire la procedura descritta in Pubblicare l'app Web. Tornare quindi a questa esercitazione e continuare con il passaggio successivo.

  9. In Esplora soluzioni fare clic con il pulsante destro del mouse su Modelli e quindi scegliere Aggiungi>classe.

  10. Assegnare alla classe il nome Product.cs e quindi selezionare Aggiungi.

    Create Product model

Modificare l'applicazione web

  1. Nel file Product.cs in Visual Studio sostituire la definizione dello spazio dei nomi esistente con il codice seguente:

     // Declare properties for the products inventory.
     namespace ProductsWeb.Models
     {
        public class Product
        {
            public string Id { get; set; }
            public string Name { get; set; }
            public string Quantity { get; set; }
        }
     }
    
  2. In Esplora soluzioni espandere Controller, quindi fare doppio clic su HomeController.cs per aprire il file in Visual Studio.

  3. In HomeController.cs sostituire la definizione dello spazio dei nomi esistente con il codice seguente:

    namespace ProductsWeb.Controllers
    {
        using System.Collections.Generic;
        using System.Web.Mvc;
        using Models;
    
        public class HomeController : Controller
        {
            // Return a view of the products inventory.
            public ActionResult Index(string Identifier, string ProductName)
            {
                var products = new List<Product>
                    {new Product {Id = Identifier, Name = ProductName}};
                return View(products);
            }
         }
    }
    
  4. In Esplora soluzioni espandere Visualizzazioni>condivise, quindi fare doppio clic su _Layout.cshtml per aprire il file nell'editor di Visual Studio.

  5. Modificare tutte le occorrenze di My ASP.NET Application in Northwind Traders Products.

  6. Rimuovere i Homecollegamenti , Aboute Contact . Nell'esempio seguente, eliminare il codice evidenziato.

    Delete the generated list items

  7. In Esplora soluzioni espandere Visualizzazioni>home, quindi fare doppio clic su Index.cshtml per aprire il file nell'editor di Visual Studio. Sostituire l'intero contenuto del file con il codice seguente:

    @model IEnumerable<ProductsWeb.Models.Product>
    
    @{
             ViewBag.Title = "Index";
    }
    
    <h2>Prod Inventory</h2>
    
    <table>
              <tr>
                  <th>
                      @Html.DisplayNameFor(model => model.Name)
                  </th>
                  <th></th>
                  <th>
                      @Html.DisplayNameFor(model => model.Quantity)
                  </th>
              </tr>
    
    @foreach (var item in Model) {
              <tr>
                  <td>
                      @Html.DisplayFor(modelItem => item.Name)
                  </td>
                  <td>
                      @Html.DisplayFor(modelItem => item.Quantity)
                  </td>
              </tr>
    }
    
    </table>
    
  8. Per verificare l'accuratezza del lavoro finora, è possibile selezionare CTRL+MAIUSC+B per compilare il progetto.

Eseguire l'app in locale

Eseguire l'applicazione per verificarne il funzionamento.

  1. Assicurarsi che il progetto attivo sia ProductsPortal. Fare clic con il pulsante destro del mouse sul nome del progetto in Esplora soluzioni e scegliere Imposta come progetto di avvio.
  2. In Visual Studio selezionare F5.

L'applicazione dovrebbe risultare in esecuzione in un browser.

Screenshot shows an example of the application running in a browser with the URL highlighted.

Combinare i diversi componenti

Nel passaggio successivo si collegherà il server dei prodotti locale all'applicazione ASP.NET.

  1. Se non è già aperto, in Visual Studio aprire il progetto ProductsPortal creato nella sezione Creare un'applicazione ASP.NET.

  2. Analogamente al passaggio nella sezione Creare un server locale, aggiungere il pacchetto NuGet ai riferimenti al progetto. In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto ProductsPortal e quindi scegliere Gestisci pacchetti NuGet.

  3. Cercare WindowsAzure.ServiceBus e selezionare l'elemento WindowsAzure.ServiceBus. Completare quindi l'installazione e chiudere questa finestra di dialogo.

  4. In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto ProductsPortal e quindi scegliere Aggiungi>elemento esistente.

  5. Individuare il file ProductsContract.cs nel progetto console ProductsServer. Evidenziare ProductsContract.cs. Selezionare la freccia giù accanto a Aggiungi, quindi scegliere Aggiungi come collegamento.

    Add as a link

  6. Aprire il file HomeController.cs nell'editor di Visual Studio e sostituire la definizione dello spazio dei nomi con il codice seguente. Assicurarsi di sostituire yourServiceNamespace con il nome dello spazio dei nomi di Inoltro e yourKey con la chiave di firma di accesso condiviso. Questo codice consente al client di chiamare il servizio locale, restituendo il risultato della chiamata.

    namespace ProductsWeb.Controllers
    {
        using System.Linq;
        using System.ServiceModel;
        using System.Web.Mvc;
        using Microsoft.ServiceBus;
        using Models;
        using ProductsServer;
    
        public class HomeController : Controller
        {
            // Declare the channel factory.
            static ChannelFactory<IProductsChannel> channelFactory;
    
            static HomeController()
            {
                // Create shared access signature token credentials for authentication.
                channelFactory = new ChannelFactory<IProductsChannel>(new NetTcpRelayBinding(),
                    "sb://yourServiceNamespace.servicebus.windows.net/products");
                channelFactory.Endpoint.Behaviors.Add(new TransportClientEndpointBehavior {
                    TokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider(
                        "RootManageSharedAccessKey", "yourKey") });
            }
    
            public ActionResult Index()
            {
                using (IProductsChannel channel = channelFactory.CreateChannel())
                {
                    // Return a view of the products inventory.
                    return this.View(from prod in channel.GetProducts()
                                     select
                                         new Product { Id = prod.Id, Name = prod.Name,
                                             Quantity = prod.Quantity });
                }
            }
        }
    }
    
  7. In Esplora soluzioni fare clic con il pulsante destro del mouse sulla soluzione ProductsPortal. Assicurarsi di fare clic con il pulsante destro del mouse sulla soluzione, non sul progetto. Selezionare Aggiungi>progetto esistente.

  8. Individuare il progetto ProductsServer, quindi fare doppio clic sulla soluzione ProductsServer.csproj per aggiungerla.

  9. ProductsServer deve essere in esecuzione per visualizzare i dati in ProductsPortal. In Esplora soluzioni fare clic con il pulsante destro del mouse sulla soluzione ProductsPortal e scegliere Proprietà per visualizzare le pagine delle proprietà.

  10. Selezionare Common Properties>Startup Project (Progetto di avvio comune) e scegliere Multiple startup projects (Progetti di avvio multipli). Assicurarsi che ProductsServer e ProductsPortal siano visualizzati, in tale ordine, e che l'azione per entrambi sia Start.

    Multiple startup projects

  11. Selezionare Proprietà>comuni Dipendenze progetto sul lato sinistro.

  12. Per Progetti scegliere ProdottiPortale. Assicurarsi che ProductsServer sia selezionato.

    Project dependencies

  13. Per Progetti scegliere ProductsServer. Assicurarsi che ProductsPortal non sia selezionato e quindi selezionare OK per salvare le modifiche.

Eseguire il progetto in locale

Per testare l'applicazione in locale, in Visual Studio selezionare F5. Il server locale, ProductsServer, deve iniziare per primo, quindi l'applicazione ProductsPortal deve essere avviata in una finestra del browser. Questa volta è possibile notare che nell'inventario dei prodotti sono elencati i dati recuperati dal sistema locale del servizio dei prodotti.

Web application

Selezionare Aggiorna nella pagina ProductsPortal . Ogni volta che si aggiorna la pagina, nell'app server viene visualizzato un messaggio quando si chiama GetProducts() da ProductsServer.

Chiudere entrambe le applicazioni prima di passare alla sezione successiva.

Distribuire il progetto ProductsPortal in un'app Web di Azure

Il passaggio successivo consiste nel ripubblicare il front-end dell'app Web di Azure ProductsPortal :

  1. In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto ProductsPortal e scegliere Pubblica. Nella pagina Pubblica selezionare Pubblica.

    Nota

    È possibile che nella finestra del browser venga visualizzato un messaggio di errore quando il progetto Web ProductsPortal viene avviato automaticamente dopo la distribuzione. Si tratta di un comportamento previsto che si verifica perché l'applicazione ProductsServer non è ancora in esecuzione.

  2. Copiare l'URL dell'app Web distribuita. L'URL sarà necessario in un secondo momento. È anche possibile ottenere questo URL dalla finestra attività del servizio app Azure in Visual Studio:

    URL of the deployed app

  3. Chiudere la finestra del browser per arrestare l'applicazione in esecuzione.

Prima di eseguire l'applicazione nel cloud, è necessario assicurarsi che ProductsPortal venga avviato da Visual Studio come app Web.

  1. In Visual Studio fare clic con il pulsante destro del mouse sul progetto ProductsPortal e scegliere Proprietà.

  2. Seleziona Web. In Avvia azione scegliere URL di avvio. Immettere l'URL per l'app Web distribuita in precedenza, in questo esempio . https://productsportal20190906122808.azurewebsites.net/

    Start URL

  3. Selezionare File>Salva tutto.

  4. Selezionare Compilacompila>soluzione.

Eseguire l'applicazione

Selezionare F5 per compilare ed eseguire l'applicazione. Il server locale, ovvero l'applicazione console ProductsServer , deve essere avviato per primo, quindi l'applicazione ProductsPortal deve essere avviata in una finestra del browser, come illustrato di seguito:

Run the web app on Azure

L'inventario dei prodotti elenca i dati recuperati dal sistema locale del servizio prodotto e visualizza tali dati nell'app Web. Verificare l'URL per assicurarsi che ProductsPortal sia in esecuzione nel cloud come app Web di Azure.

Importante

L'applicazione console ProductsServer deve essere in esecuzione e in grado di passare dati all'applicazione ProductsPortal. Se nel browser viene visualizzato un errore, attendere alcuni secondi prima che ProductsServer venga caricato e visualizzato il messaggio seguente, quindi aggiornare il browser.

Nel browser aggiornare la pagina ProductsPortal . Ogni volta che si aggiorna la pagina, nell'app server viene visualizzato un messaggio quando si chiama GetProducts() da ProductsServer.

Updated output

Passaggi successivi

Passare all'esercitazione seguente: