Condividi tramite


Esercitazione: Creare un'applicazione di Service Fabric .NET

Questa esercitazione fa parte di una serie. Questa esercitazione illustra come creare un'applicazione di Azure Service Fabric con un front-end api Web di ASP.NET Core e un servizio back-end con stato per archiviare i dati. Al termine, si dispone di un'applicazione di voto con un front-end Web ASP.NET Core che salva i risultati di voto in un servizio back-end con stato nel cluster.

Questa serie di esercitazioni richiede un computer per sviluppatori Windows. Se non si vuole creare manualmente l'applicazione di voto, è possibile scaricare il codice sorgente per l'applicazione completata e passare direttamente alla Descrizione dettagliata dell'applicazione di voto di esempio. È anche possibile visualizzare una procedura dettagliata video di questa esercitazione.

Diagramma che mostra un front-end dell'API AngularJS+ASP.NET che si connette a un servizio back-end con stato in Service Fabric.

In questa esercitazione apprenderai a:

  • Creare un servizio API Web ASP.NET Core come servizio Reliable con stato
  • Creare un servizio applicazione Web ASP.NET Core come servizio Web senza stato
  • Usare il proxy inverso per comunicare con il servizio con stato

La serie di esercitazioni illustra come:

Prerequisiti

Prima di iniziare questa esercitazione:

Creare un servizio API Web ASP.NET come servizio Reliable

Creare prima di tutto il front-end Web dell'applicazione di voto usando ASP.NET Core. ASP.NET Core è un framework di sviluppo Web multipiattaforma leggero, che consente di creare un'interfaccia utente Web e API Web moderne.

Per comprendere in modo completo come ASP.NET Core si integra con Service Fabric, è consigliabile esaminare ASP.NET Core in Service Fabric Reliable Services. Per il momento, è possibile seguire questa esercitazione per essere subito operativi. Per altre informazioni su ASP.NET Core, vedere la documentazione di ASP.NET Core.

Per creare il servizio:

  1. Aprire Visual Studio usando l'opzione Esegui come amministratore .

  2. Selezionare File>Nuovo>progetto per creare un nuovo progetto.

  3. In Crea un nuovo progetto selezionare Applicazione Cloud>Service Fabric. Selezionare Avanti.

    Screenshot che mostra la finestra di dialogo Crea un nuovo progetto in Visual Studio.

  4. Selezionare Stateless ASP.NET Core per il nuovo tipo di progetto, assegnare al servizio il nome VotingWeb e quindi selezionare Crea.

    Screenshot che mostra la scelta di un servizio Web ASP.NET nel nuovo riquadro del servizio.

  5. Il riquadro successivo mostra un set di modelli di progetto ASP.NET Core. Per questa esercitazione selezionare Applicazione Web (Model-View-Controller) e quindi selezionare OK.

    Screenshot che mostra la selezione del tipo di progetto ASP.NET.

    Visual Studio crea un'applicazione e un progetto di servizio e li visualizza in Visual Studio Esplora soluzioni:

    Screenshot che mostra Esplora soluzioni dopo la creazione dell'applicazione usando il servizio API Web principale ASP.NET.

Aggiornare il file site.js

Passare a wwwroot/js/site.js e aprire il file. Sostituire il contenuto del file con il codice JavaScript seguente usato dalle visualizzazioni Home e quindi salvare le modifiche.

var app = angular.module('VotingApp', ['ui.bootstrap']);
app.run(function () { });

app.controller('VotingAppController', ['$rootScope', '$scope', '$http', '$timeout', function ($rootScope, $scope, $http, $timeout) {

    $scope.refresh = function () {
        $http.get('api/Votes?c=' + new Date().getTime())
            .then(function (data, status) {
                $scope.votes = data;
            }, function (data, status) {
                $scope.votes = undefined;
            });
    };

    $scope.remove = function (item) {
        $http.delete('api/Votes/' + item)
            .then(function (data, status) {
                $scope.refresh();
            })
    };

    $scope.add = function (item) {
        var fd = new FormData();
        fd.append('item', item);
        $http.put('api/Votes/' + item, fd, {
            transformRequest: angular.identity,
            headers: { 'Content-Type': undefined }
        })
            .then(function (data, status) {
                $scope.refresh();
                $scope.item = undefined;
            })
    };
}]);

Aggiornare il file Index.cshtml

Passare a Views/Home/Index.cshtml e aprire il file. Questo file ha la visualizzazione specifica del controller Home. Sostituire il contenuto con il codice seguente e quindi salvare le modifiche.

@{
    ViewData["Title"] = "Service Fabric Voting Sample";
}

<div ng-controller="VotingAppController" ng-init="refresh()">
    <div class="container-fluid">
        <div class="row">
            <div class="col-xs-8 col-xs-offset-2 text-center">
                <h2>Service Fabric Voting Sample</h2>
            </div>
        </div>

        <div class="row">
            <div class="col-xs-8 col-xs-offset-2">
                <form class="col-xs-12 center-block">
                    <div class="col-xs-6 form-group">
                        <input id="txtAdd" type="text" class="form-control" placeholder="Add voting option" ng-model="item"/>
                    </div>
                    <button id="btnAdd" class="btn btn-default" ng-click="add(item)">
                        <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
                        Add
                    </button>
                </form>
            </div>
        </div>

        <hr/>

        <div class="row">
            <div class="col-xs-8 col-xs-offset-2">
                <div class="row">
                    <div class="col-xs-4">
                        Click to vote
                    </div>
                </div>
                <div class="row top-buffer" ng-repeat="vote in votes.data">
                    <div class="col-xs-8">
                        <button class="btn btn-success text-left btn-block" ng-click="add(vote.Key)">
                            <span class="pull-left">
                                {{vote.key}}
                            </span>
                            <span class="badge pull-right">
                                {{vote.value}} Votes
                            </span>
                        </button>
                    </div>
                    <div class="col-xs-4">
                        <button class="btn btn-danger pull-right btn-block" ng-click="remove(vote.Key)">
                            <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
                            Remove
                        </button>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

Aggiornare il file _Layout.cshtml

Passare a Views/Shared/_Layout.cshtml e aprire il file. Questo file ha il layout predefinito per l'app ASP.NET. Sostituire il contenuto con il codice seguente e quindi salvare le modifiche.

<!DOCTYPE html>
<html ng-app="VotingApp" xmlns:ng="https://angularjs.org">
<head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>@ViewData["Title"]</title>

    <link href="~/lib/bootstrap/dist/css/bootstrap.css" rel="stylesheet"/>
    <link href="~/css/site.css" rel="stylesheet"/>

</head>
<body>
<div class="container body-content">
    @RenderBody()
</div>

<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.2/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.5.0/ui-bootstrap-tpls.js"></script>
<script src="~/js/site.js"></script>

@RenderSection("Scripts", required: false)
</body>
</html>

Aggiornare il file VotingWeb.cs

Aprire il file VotingWeb.cs . Questo file crea il ASP.NET Core WebHost all'interno del servizio senza stato usando il server WebListener.

All'inizio del file aggiungere la using System.Net.Http; direttiva .

Sostituire la CreateServiceInstanceListeners() funzione con il codice seguente e quindi salvare le modifiche.

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
    return new ServiceInstanceListener[]
    {
        new ServiceInstanceListener(
            serviceContext =>
                new KestrelCommunicationListener(
                    serviceContext,
                    "ServiceEndpoint",
                    (url, listener) =>
                    {
                        ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");

                        return new WebHostBuilder()
                            .UseKestrel()
                            .ConfigureServices(
                                services => services
                                    .AddSingleton<HttpClient>(new HttpClient())
                                    .AddSingleton<FabricClient>(new FabricClient())
                                    .AddSingleton<StatelessServiceContext>(serviceContext))
                            .UseContentRoot(Directory.GetCurrentDirectory())
                            .UseStartup<Startup>()
                            .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                            .UseUrls(url)
                            .Build();
                    }))
    };
}

Aggiungere quindi il metodo seguente GetVotingDataServiceName dopo CreateServiceInstanceListeners()e quindi salvare le modifiche. GetVotingDataServiceName restituisce il nome del servizio quando viene eseguito il polling.

internal static Uri GetVotingDataServiceName(ServiceContext context)
{
    return new Uri($"{context.CodePackageActivationContext.ApplicationName}/VotingData");
}

Aggiungere il file VotesController.cs

Aggiungere un controller per definire le azioni di voto. Fare clic con il pulsante destro del mouse sulla cartella Controllers e quindi scegliere Aggiungi>nuovo elemento>Visual C#>ASP.NET Classe core.> Assegnare al file il nome VotesController.cs e quindi selezionare Aggiungi.

Sostituire il contenuto del file VotesController.cs con il codice seguente e quindi salvare le modifiche. Nella sezione Aggiornare il file VotesController.cs disponibile più avanti, questo file viene modificato per leggere e scrivere i dati di voto dal servizio back-end. Per il momento, il controller restituisce nella visualizzazione i dati di una stringa statica.

namespace VotingWeb.Controllers
{
    using System;
    using System.Collections.Generic;
    using System.Fabric;
    using System.Fabric.Query;
    using System.Linq;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using System.Text;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Mvc;
    using Newtonsoft.Json;

    [Produces("application/json")]
    [Route("api/Votes")]
    public class VotesController : Controller
    {
        private readonly HttpClient httpClient;

        public VotesController(HttpClient httpClient)
        {
            this.httpClient = httpClient;
        }

        // GET: api/Votes
        [HttpGet]
        public async Task<IActionResult> Get()
        {
            List<KeyValuePair<string, int>> votes= new List<KeyValuePair<string, int>>();
            votes.Add(new KeyValuePair<string, int>("Pizza", 3));
            votes.Add(new KeyValuePair<string, int>("Ice cream", 4));

            return Json(votes);
        }
     }
}

Configurare la porta di ascolto

Quando viene creato il servizio front-end VotingWeb, Visual Studio seleziona casualmente una porta su cui il servizio resterà in ascolto. Il servizio VotingWeb funge da front-end per questa applicazione e accetta il traffico esterno. In questa sezione il servizio viene associato a una porta fissa e nota. Il manifesto del servizio dichiara gli endpoint di servizio.

In Esplora soluzioni aprire VotingWeb/PackageRoot/ServiceManifest.xml. Resources Nella sezione trovare l'elemento Endpoint e quindi modificare il Port valore in 8080.

Per distribuire ed eseguire l'applicazione in locale, la porta dell'applicazione in ascolto deve essere aperta e disponibile nel computer.

<Resources>
    <Endpoints>
      <!-- This endpoint is used by the communication listener to obtain the port on which to 
           listen. Please note that if your service is partitioned, this port is shared with 
           replicas of different partitions that are placed in your code. -->
      <Endpoint Protocol="http" Name="ServiceEndpoint" Type="Input" Port="8080" />
    </Endpoints>
  </Resources>

Aggiornare quindi il valore della Application URL proprietà nel progetto Voting in modo che un Web browser si apra alla porta corretta quando si esegue il debug dell'applicazione. In Esplora soluzioni selezionare il progetto Voting e quindi aggiornare la Application URL proprietà a 8080.

Distribuire ed eseguire l'applicazione Voting in locale

È ora possibile eseguire l'applicazione Voting per eseguirne il debug. In Visual Studio selezionare F5 per distribuire l'applicazione nel cluster locale di Service Fabric in modalità di debug. L'applicazione ha esito negativo se visual Studio non è stato aperto in precedenza usando l'opzione Esegui come amministratore .

Nota

La prima volta che si esegue e si distribuisce l'applicazione in locale, Visual Studio crea un cluster di Service Fabric locale da usare per il debug. Il processo di creazione di un cluster potrebbe richiedere del tempo. Lo stato di creazione del cluster viene visualizzato nella finestra Output di Visual Studio.

Dopo aver distribuito l'applicazione Voting nel cluster di Service Fabric locale, l'app Web viene aperta automaticamente in una scheda del browser. L'esempio è simile al seguente:

Screenshot che mostra il front-end dell'applicazione in un browser.

Per arrestare il debug dell'applicazione, tornare a Visual Studio e selezionare MAIUSC+F5.

Aggiungere un servizio back-end con stato a un'applicazione

Ora che un servizio API Web ASP.NET è in esecuzione nell'applicazione, aggiungere un servizio Reliable Service con stato per archiviare alcuni dati nell'applicazione.

È possibile usare Service Fabric per archiviare in modo coerente e affidabile i dati direttamente all'interno del servizio usando raccolte affidabili. Le raccolte Reliable Sono un set di classi di raccolta affidabili e a disponibilità elevata che hanno familiarità con chiunque abbia esperienza nell'uso delle raccolte C#.

Per creare un servizio che archivia un valore del contatore in una raccolta Reliable Collection:

  1. In Esplora soluzioni fare clic con il pulsante destro del mouse su Servizi nel progetto di applicazione Voting e selezionare Aggiungi>nuovo servizio Service Fabric.

  2. Nella finestra di dialogo Nuovo servizio di Service Fabric selezionare Con stato ASP.NET Core, assegnare al servizio il nome VotingData e quindi selezionare OK.

    Dopo aver creato il progetto di servizio, nell'applicazione sono presenti due servizi. Man mano che si continua a compilare l'applicazione, è possibile aggiungere altri servizi allo stesso modo. Ogni servizio può essere sottoposto a controllo delle versioni e aggiornato in modo indipendente.

  3. Il riquadro successivo mostra un set di modelli di progetto ASP.NET Core. Per questa esercitazione selezionare API.

    Visual Studio crea il progetto di servizio VotingData e lo visualizza in Esplora soluzioni:

    Screenshot che mostra il progetto di servizio VotingData in Esplora soluzioni.

Aggiungere il file VoteDataController.cs

Nel progetto VotingData fare clic con il pulsante destro del mouse sulla cartella Controllers e quindi scegliere Aggiungi>nuova classe elemento.> Assegnare al file il nome VoteDataController.cs e selezionare Aggiungi. Sostituire il contenuto del file con il codice seguente e quindi salvare le modifiche.

namespace VotingData.Controllers
{
    using System.Collections.Generic;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.ServiceFabric.Data;
    using Microsoft.ServiceFabric.Data.Collections;

    [Route("api/[controller]")]
    public class VoteDataController : Controller
    {
        private readonly IReliableStateManager stateManager;

        public VoteDataController(IReliableStateManager stateManager)
        {
            this.stateManager = stateManager;
        }

        // GET api/VoteData
        [HttpGet]
        public async Task<IActionResult> Get()
        {
            CancellationToken ct = new CancellationToken();

            IReliableDictionary<string, int> votesDictionary = await this.stateManager.GetOrAddAsync<IReliableDictionary<string, int>>("counts");

            using (ITransaction tx = this.stateManager.CreateTransaction())
            {
                Microsoft.ServiceFabric.Data.IAsyncEnumerable<KeyValuePair<string, int>> list = await votesDictionary.CreateEnumerableAsync(tx);

                Microsoft.ServiceFabric.Data.IAsyncEnumerator<KeyValuePair<string, int>> enumerator = list.GetAsyncEnumerator();

                List<KeyValuePair<string, int>> result = new List<KeyValuePair<string, int>>();

                while (await enumerator.MoveNextAsync(ct))
                {
                    result.Add(enumerator.Current);
                }

                return this.Json(result);
            }
        }

        // PUT api/VoteData/name
        [HttpPut("{name}")]
        public async Task<IActionResult> Put(string name)
        {
            IReliableDictionary<string, int> votesDictionary = await this.stateManager.GetOrAddAsync<IReliableDictionary<string, int>>("counts");

            using (ITransaction tx = this.stateManager.CreateTransaction())
            {
                await votesDictionary.AddOrUpdateAsync(tx, name, 1, (key, oldvalue) => oldvalue + 1);
                await tx.CommitAsync();
            }

            return new OkResult();
        }

        // DELETE api/VoteData/name
        [HttpDelete("{name}")]
        public async Task<IActionResult> Delete(string name)
        {
            IReliableDictionary<string, int> votesDictionary = await this.stateManager.GetOrAddAsync<IReliableDictionary<string, int>>("counts");

            using (ITransaction tx = this.stateManager.CreateTransaction())
            {
                if (await votesDictionary.ContainsKeyAsync(tx, name))
                {
                    await votesDictionary.TryRemoveAsync(tx, name);
                    await tx.CommitAsync();
                    return new OkResult();
                }
                else
                {
                    return new NotFoundResult();
                }
            }
        }
    }
}

Connettere i servizi

In questa sezione si connettono due servizi. L'applicazione Web front-end ottiene informazioni di voto dal servizio back-end e quindi imposta le informazioni nell'app.

Service Fabric offre flessibilità completa nel modo in cui si comunica con Reliable Services. All'interno di una singola applicazione potrebbero essere presenti servizi accessibili tramite TCP/IP, tramite un'API REST HTTP o tramite il protocollo WebSocket. Per informazioni generali sulle opzioni disponibili e sui relativi compromessi, vedere Comunicazione con i servizi.

Questa esercitazione usa ASP.NET'API Web core e il proxy inverso di Service Fabric in modo che il servizio Web front-end VotingWeb possa comunicare con il servizio VotingData back-end. Un proxy inverso è configurato per impostazione predefinita per usare la porta 19081. La porta del proxy inverso è impostata nel modello di Azure Resource Manager che configura il cluster. Per trovare la porta usata, esaminare il modello di cluster nella Microsoft.ServiceFabric/clusters risorsa:

"nodeTypes": [
          {
            ...
            "httpGatewayEndpointPort": "[variables('nt0fabricHttpGatewayPort')]",
            "isPrimary": true,
            "vmInstanceCount": "[parameters('nt0InstanceCount')]",
            "reverseProxyEndpointPort": "[parameters('SFReverseProxyPort')]"
          }
        ],

Per trovare la porta del proxy inverso usata nel cluster di sviluppo locale, visualizzare l'elemento HttpApplicationGatewayEndpoint nel manifesto del cluster di Service Fabric locale:

  1. Per aprire lo strumento Service Fabric Explorer, aprire un browser e passare a http://localhost:19080.
  2. Selezionare Manifesto cluster>.
  3. Prendere nota della porta dell'elemento HttpApplicationGatewayEndpoint . Per impostazione predefinita, la porta è 19081. Se non è 19081, modificare la porta nel GetProxyAddress metodo del codice VotesController.cs come descritto nella sezione successiva.

Aggiornare il file VotesController.cs

Nel progetto VotingWeb aprire il file Controllers/VotesController.cs . Sostituire il contenuto della definizione della VotesController classe con il codice seguente e quindi salvare le modifiche. Se la porta del proxy inverso individuata nel passaggio pervioso non è 19081, modificare la porta nel GetProxyAddress metodo da 19081 alla porta individuata.

public class VotesController : Controller
{
    private readonly HttpClient httpClient;
    private readonly FabricClient fabricClient;
    private readonly StatelessServiceContext serviceContext;

    public VotesController(HttpClient httpClient, StatelessServiceContext context, FabricClient fabricClient)
    {
        this.fabricClient = fabricClient;
        this.httpClient = httpClient;
        this.serviceContext = context;
    }

    // GET: api/Votes
    [HttpGet("")]
    public async Task<IActionResult> Get()
    {
        Uri serviceName = VotingWeb.GetVotingDataServiceName(this.serviceContext);
        Uri proxyAddress = this.GetProxyAddress(serviceName);

        ServicePartitionList partitions = await this.fabricClient.QueryManager.GetPartitionListAsync(serviceName);

        List<KeyValuePair<string, int>> result = new List<KeyValuePair<string, int>>();

        foreach (Partition partition in partitions)
        {
            string proxyUrl =
                $"{proxyAddress}/api/VoteData?PartitionKey={((Int64RangePartitionInformation) partition.PartitionInformation).LowKey}&PartitionKind=Int64Range";

            using (HttpResponseMessage response = await this.httpClient.GetAsync(proxyUrl))
            {
                if (response.StatusCode != System.Net.HttpStatusCode.OK)
                {
                    continue;
                }

                result.AddRange(JsonConvert.DeserializeObject<List<KeyValuePair<string, int>>>(await response.Content.ReadAsStringAsync()));
            }
        }

        return this.Json(result);
    }

    // PUT: api/Votes/name
    [HttpPut("{name}")]
    public async Task<IActionResult> Put(string name)
    {
        Uri serviceName = VotingWeb.GetVotingDataServiceName(this.serviceContext);
        Uri proxyAddress = this.GetProxyAddress(serviceName);
        long partitionKey = this.GetPartitionKey(name);
        string proxyUrl = $"{proxyAddress}/api/VoteData/{name}?PartitionKey={partitionKey}&PartitionKind=Int64Range";

        StringContent putContent = new StringContent($"{{ 'name' : '{name}' }}", Encoding.UTF8, "application/json");
        putContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");

        using (HttpResponseMessage response = await this.httpClient.PutAsync(proxyUrl, putContent))
        {
            return new ContentResult()
            {
                StatusCode = (int) response.StatusCode,
                Content = await response.Content.ReadAsStringAsync()
            };
        }
    }

    // DELETE: api/Votes/name
    [HttpDelete("{name}")]
    public async Task<IActionResult> Delete(string name)
    {
        Uri serviceName = VotingWeb.GetVotingDataServiceName(this.serviceContext);
        Uri proxyAddress = this.GetProxyAddress(serviceName);
        long partitionKey = this.GetPartitionKey(name);
        string proxyUrl = $"{proxyAddress}/api/VoteData/{name}?PartitionKey={partitionKey}&PartitionKind=Int64Range";

        using (HttpResponseMessage response = await this.httpClient.DeleteAsync(proxyUrl))
        {
            if (response.StatusCode != System.Net.HttpStatusCode.OK)
            {
                return this.StatusCode((int) response.StatusCode);
            }
        }

        return new OkResult();
    }


    /// <summary>
    /// Constructs a reverse proxy URL for a given service.
    /// Example: http://localhost:19081/VotingApplication/VotingData/
    /// </summary>
    /// <param name="serviceName"></param>
    /// <returns></returns>
    private Uri GetProxyAddress(Uri serviceName)
    {
        return new Uri($"http://localhost:19081{serviceName.AbsolutePath}");
    }

    /// <summary>
    /// Creates a partition key from the given name.
    /// Uses the zero-based numeric position in the alphabet of the first letter of the name (0-25).
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    private long GetPartitionKey(string name)
    {
        return Char.ToUpper(name.First()) - 'A';
    }
}

Descrizione dettagliata dell'applicazione di voto di esempio

L'applicazione di voto è costituita da due servizi:

  • Un servizio front-end Web (VotingWeb): un servizio front-end Web di ASP.NET Core che serve la pagina Web ed espone le API Web per comunicare con il servizio back-end.
  • Un servizio back-end (VotingData): un servizio Web ASP.NET Core che espone un'API per archiviare i risultati del voto in un dizionario affidabile persistente su disco.

Diagramma che illustra i servizi dell'applicazione.

Quando si vota nell'applicazione, si verificano gli eventi seguenti:

  1. Un file JavaScript invia la richiesta di voto all'API Web nel servizio front-end Web come richiesta HTTP PUT.

  2. Il servizio front-end Web usa un proxy per individuare e inoltrare una richiesta PUT HTTP al servizio back-end.

  3. Il servizio back-end accetta la richiesta in ingresso e archivia il risultato aggiornato in un dizionario affidabile. Il dizionario viene replicato in più nodi nel cluster e salvato in modo permanente su disco. Tutti i dati dell'applicazione sono archiviati nel cluster, quindi non è necessario alcun database.

Eseguire il debug in Visual Studio

Quando si esegue il debug di un'applicazione in Visual Studio, si usa un cluster di sviluppo di Service Fabric locale. È possibile modificare l'esperienza di debug in base allo specifico scenario.

In questa applicazione archiviare i dati nel servizio back-end usando un dizionario affidabile. Visual Studio rimuove l'applicazione per impostazione predefinita quando si arresta il debugger. La rimozione dell'applicazione determina la rimozione anche dei dati nel servizio back-end. Per rendere persistenti i dati tra le sessioni di debug, è possibile modificare la proprietà Modalità di debug applicazione del progetto Voting in Visual Studio.

Per vedere cosa accade nel codice, completare la procedura seguente:

  1. Aprire il file VotingWeb\VotesController.cs e impostare un punto di interruzione nel metodo dell'API Put Web (riga 72).

  2. Aprire il file VotingData\VoteDataController.cs e impostare un punto di interruzione nel metodo dell'API Put Web (riga 54).

  3. Selezionare F5 per avviare l'applicazione in modalità di debug.

  4. Tornare al browser e selezionare un'opzione di voto o aggiungere una nuova opzione di voto. Si raggiunge il primo punto di interruzione nel controller API del front-end Web.

    JavaScript nel browser invia una richiesta al controller API Web nel servizio front-end:

    Screenshot che mostra l'aggiunta di un servizio front-end di voto.

    1. Creare prima di tutto l'URL del proxy inverso per il servizio back-end. (1)
    2. Inviare quindi la richiesta HTTP PUT al proxy inverso. (2)
    3. Infine, restituire la risposta dal servizio back-end al client. (3)
  5. Selezionare F5 per continuare.

    Si è ora nel punto di interruzione nel servizio back-end:

    Screenshot che mostra l'aggiunta di un voto al servizio back-end.

    1. Nella prima riga del metodo usare stateManager per ottenere o aggiungere un dizionario affidabile denominato counts. (1)
    2. Tutte le interazioni con valori in un dizionario affidabile richiedono una transazione. Questa using istruzione crea la transazione. (2)
    3. Nella transazione aggiornare il valore della chiave pertinente per l'opzione di voto ed eseguire il commit dell'operazione. Quando il commit metodo termina, i dati vengono aggiornati nel dizionario. Viene quindi replicato in altri nodi del cluster. I dati sono ora archiviati in modo sicuro nel cluster e il servizio back-end può eseguire il failover in altri nodi e avere ancora i dati disponibili. (3)
  6. Selezionare F5 per continuare.

Per arrestare la sessione di debug, selezionare MAIUSC+F5.

Passaggio successivo

Passare all'esercitazione successiva: