Partilhar via


Tutorial: Criar um aplicativo .NET Service Fabric

Este tutorial é a primeira parte de uma série. Neste tutorial, saiba como criar um aplicativo do Azure Service Fabric que tenha um front-end da API Web Core do ASP.NET e um serviço back-end com monitoração de estado para armazenar seus dados. Quando terminar, você terá um aplicativo de votação com um front-end da Web ASP.NET Core que salva os resultados da votação em um serviço back-end com monitoração de estado no cluster.

Esta série de tutoriais requer um computador desenvolvedor Windows. Se não quiser criar manualmente a aplicação de voto, pode transferir o código de origem da aplicação concluída e avançar diretamente para o Guia do exemplo de aplicação de voto. Você também pode ver um vídeo passo a passo deste tutorial.

Diagrama que mostra um front-end da API AngularJS+ASP.NET conectando-se a um serviço back-end com monitoração de estado no Service Fabric.

Neste tutorial, irá aprender a:

  • Criar um serviço de API Web do ASP.NET Core como um Reliable Service com monitorização de estado
  • Criar um serviço de Aplicação Web do ASP.NET Core como um serviço Web sem monitorização de estado
  • Usar proxy reverso para se comunicar com o serviço stateful

A série de tutoriais mostra como:

Pré-requisitos

Antes de começar este tutorial:

Criar um serviço de API Web do ASP.NET como um Reliable Service

Primeiro, crie o front-end da Web do aplicativo de votação usando o ASP.NET Core. O ASP.NET Core é uma arquitetura de desenvolvimento Web simples para várias plataformas que pode utilizar para criar uma IU Web e APIs Web modernas.

Para obter uma compreensão completa de como o ASP.NET Core se integra ao Service Fabric, recomendamos que você analise ASP.NET Core nos Serviços Confiáveis do Service Fabric. Por agora, pode seguir este tutorial para começar a trabalhar rapidamente. Para saber mais sobre o ASP.NET Core, consulte a documentação do ASP.NET Core.

Para criar o serviço:

  1. Abra o Visual Studio usando a opção Executar como administrador .

  2. Selecione Arquivo>Novo>Projeto para criar um novo projeto.

  3. Em Criar um novo projeto, selecione Aplicativo> do Cloud Service Fabric. Selecione Seguinte.

    Captura de tela que mostra a caixa de diálogo Criar um novo projeto no Visual Studio.

  4. Selecione Stateless ASP.NET Core para o novo tipo de projeto, nomeie seu serviço VotingWeb e selecione Criar.

    Captura de tela que mostra a escolha de um serviço Web ASP.NET no novo painel de serviço.

  5. O próximo painel mostra um conjunto de modelos de projeto ASP.NET Core. Para este tutorial, selecione Aplicativo Web (Model-View-Controller) e, em seguida, selecione OK.

    Captura de tela que mostra a seleção do tipo de projeto ASP.NET.

    O Visual Studio cria um aplicativo e um projeto de serviço e os exibe no Gerenciador de Soluções do Visual Studio:

    Captura de tela que mostra o Gerenciador de Soluções depois que o aplicativo é criado usando o ASP.NET serviço de API Web principal.

Atualizar o ficheiro site.js

Vá para wwwroot/js/site.js e abra o arquivo. Substitua o conteúdo do ficheiro pelo seguinte JavaScript utilizado pelas vistas Início e, em seguida, guarde as alterações.

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;
            })
    };
}]);

Atualizar o ficheiro Index.cshtml

Vá para Views/Home/Index.cshtml e abra o arquivo. Este ficheiro tem a vista específica para o controlador Home. Substitua seu conteúdo pelo código a seguir e salve as alterações.

@{
    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>

Atualizar o ficheiro _Layout.cshtml

Vá para Views/Shared/_Layout.cshtml e abra o arquivo. Esse arquivo tem o layout padrão para o aplicativo ASP.NET. Substitua seu conteúdo pelo código a seguir e salve as alterações.

<!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>

Atualizar o ficheiro VotingWeb.cs

Abra o arquivo VotingWeb.cs . Esse arquivo cria o ASP.NET Core WebHost dentro do serviço sem estado usando o servidor Web WebListener.

No início do arquivo, adicione a using System.Net.Http; diretiva.

Substitua a CreateServiceInstanceListeners() função pelo código a seguir e salve as alterações.

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();
                    }))
    };
}

Em seguida, adicione o seguinte GetVotingDataServiceName método após CreateServiceInstanceListeners()e, em seguida, salve as alterações. GetVotingDataServiceName devolve o nome do serviço quando consultado.

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

Adicionar o ficheiro VotesController.cs

Adicione um controlador para definir ações de votação. Clique com o botão direito do mouse na pasta Controllers e selecione Add>New item>Visual C#>ASP.NET Core>Class. Nomeie o arquivo VotesController.cs e selecione Adicionar.

Substitua o conteúdo do arquivo VotesController.cs pelo código a seguir e salve as alterações. Mais adiante, em Atualizar o ficheiro VotesController.cs, este ficheiro é modificado para ler e escrever dados de voto do serviço de back-end. Por agora, o controlador devolve dados de cadeia estática à vista.

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);
        }
     }
}

Configurar a porta de escuta

Quando o serviço de front-end VotingWeb é criado, o Visual Studio seleciona aleatoriamente uma porta na qual o serviço escuta. O serviço VotingWeb atua como o front-end para este aplicativo e aceita tráfego externo. Nesta seção, você vincula esse serviço a uma porta fixa e conhecida. O manifesto do serviço declara os pontos finais de serviço.

No Explorador de Soluções, abra VotingWeb/PackageRoot/ServiceManifest.xml. Resources Na seção , localize o Endpoint elemento e, em seguida, altere o Port valor para 8080.

Para implementar e executar a aplicação localmente, a porta de escuta da aplicação tem de estar aberta e disponível no seu computador.

<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>

Em seguida, atualize o valor da Application URL propriedade no projeto Voting para que um navegador da Web seja aberto para a porta correta quando você depurar seu aplicativo. No Gerenciador de Soluções, selecione o projeto de votação e atualize a Application URL propriedade para 8080.

Implementar e executar a aplicação de Voto localmente

Agora você pode executar o aplicativo de votação para depurá-lo. No Visual Studio, selecione F5 para implantar o aplicativo em seu cluster local do Service Fabric no modo de depuração. O aplicativo falhará se você não tiver aberto anteriormente o Visual Studio usando a opção Executar como administrador .

Nota

Na primeira vez que você executa e implanta o aplicativo localmente, o Visual Studio cria um cluster local do Service Fabric para usar na depuração. O processo para criar um cluster pode levar algum tempo. O status de criação do cluster é exibido na janela Saída do Visual Studio.

Depois que o aplicativo de votação é implantado em seu cluster local do Service Fabric, seu aplicativo Web é aberto automaticamente em uma guia do navegador. É semelhante a este exemplo:

Captura de tela que mostra o front-end do aplicativo em um navegador.

Para parar de depurar o aplicativo, volte para o Visual Studio e selecione Shift+F5.

Adicionar um serviço de back-end com monitorização de estado à sua aplicação

Agora que um serviço de API Web ASP.NET está em execução no aplicativo, adicione um serviço confiável com monitoração de estado para armazenar alguns dados no aplicativo.

Você pode usar o Service Fabric para armazenar seus dados de forma consistente e confiável diretamente dentro do seu serviço usando coleções confiáveis. Coleções confiáveis são um conjunto de classes de coleção altamente disponíveis e confiáveis que são familiares para qualquer pessoa que tenha experiência no uso de coleções C#.

Para criar um serviço que armazena um valor de contador em uma coleção confiável:

  1. No Gerenciador de Soluções, clique com o botão direito do mouse em Serviços no projeto de aplicativo de votação e selecione Adicionar>Novo Serviço do Service Fabric.

  2. Na caixa de diálogo Novo Serviço do Service Fabric, selecione Stateful ASP.NET Core, nomeie o serviço VotingData e selecione OK.

    Depois que seu projeto de serviço é criado, você tem dois serviços em seu aplicativo. À medida que você continua a criar seu aplicativo, você pode adicionar mais serviços da mesma maneira. Cada serviço pode ser versionado e atualizado de forma independente.

  3. O próximo painel mostra um conjunto de modelos de projeto ASP.NET Core. Para este tutorial, selecione API.

    O Visual Studio cria o projeto de serviço VotingData e o exibe no Gerenciador de Soluções:

    Captura de tela que mostra o projeto de serviço VotingData no Gerenciador de Soluções.

Adicionar o ficheiro VoteDataController.cs

No projeto VotingData, clique com o botão direito do mouse na pasta Controllers e selecione Add>New item>Class. Nomeie o arquivo VoteDataController.cs e selecione Adicionar. Substitua o conteúdo do arquivo pelo código a seguir e salve as alterações.

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();
                }
            }
        }
    }
}

Ligar os serviços

Nesta seção, você conecta dois serviços. Você faz com que o aplicativo Web front-end obtenha informações de votação do serviço back-end e, em seguida, defina as informações no aplicativo.

O Service Fabric oferece total flexibilidade na maneira como você se comunica com serviços confiáveis. Dentro de um único aplicativo, você pode ter serviços que são acessíveis via TCP/IP, por meio de uma API REST HTTP ou via protocolo WebSocket. Para obter informações básicas sobre as opções disponíveis e suas compensações, consulte Comunicação com serviços.

Este tutorial usa ASP.NET API Web Core e o proxy reverso do Service Fabric para que o serviço Web front-end VotingWeb possa se comunicar com o serviço VotingData back-end. Um proxy reverso é configurado por padrão para usar a porta 19081. A porta de proxy reverso é definida no modelo do Azure Resource Manager que configura o cluster. Para localizar qual porta é usada, procure no modelo de cluster no Microsoft.ServiceFabric/clusters recurso:

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

Para localizar a porta de proxy reverso usada no cluster de desenvolvimento local, exiba o HttpApplicationGatewayEndpoint elemento no manifesto do cluster local do Service Fabric:

  1. Para abrir a ferramenta Service Fabric Explorer, abra um navegador e vá para http://localhost:19080.
  2. Selecione Manifesto do cluster>.
  3. Anote a porta do elemento HttpApplicationGatewayEndpoint . Por padrão, a porta é 19081. Se não for 19081, altere a GetProxyAddress porta no método do código VotesController.cs, conforme descrito na próxima seção.

Atualizar o ficheiro VotesController.cs

No projeto VotingWeb, abra o arquivo Controllers/VotesController.cs . Substitua o conteúdo da definição de VotesController classe pelo código a seguir e salve as alterações. Se a porta de proxy reverso descoberta na etapa anterior não for 19081, altere a GetProxyAddress porta no método de 19081 para a porta descoberta.

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';
    }
}

Percorrer a aplicação de votação de exemplo

A aplicação de votação é composta por dois serviços:

  • Um serviço front-end da Web (VotingWeb): um serviço front-end da Web ASP.NET Core que serve a página da Web e expõe APIs da Web para se comunicar com o serviço back-end.
  • Um serviço back-end (VotingData): um serviço Web ASP.NET Core que expõe uma API para armazenar os resultados da votação em um dicionário confiável que persiste no disco.

Diagrama que representa os serviços de aplicativo.

Quando você vota no aplicativo, ocorrem os seguintes eventos:

  1. Um arquivo JavaScript envia a solicitação de voto para a API da Web no serviço front-end da Web como uma solicitação HTTP PUT.

  2. O serviço de front-end da Web utiliza um proxy para localizar e reencaminhar um pedido HTTP PUT para o serviço de back-end.

  3. O serviço de back-end recebe a solicitação de entrada e armazena o resultado atualizado em um dicionário confiável. O dicionário é replicado para vários nós no cluster e persiste no disco. Todos os dados da aplicação são armazenados no cluster, pelo que não é necessária uma base de dados.

Depurar no Visual Studio

Ao depurar um aplicativo no Visual Studio, você usa um cluster de desenvolvimento local do Service Fabric. Você pode ajustar sua experiência de depuração ao seu cenário.

Neste aplicativo, armazene dados no serviço back-end usando um dicionário confiável. Visual Studio remove o aplicativo por padrão quando você parar o depurador. Remover a aplicação faz com que os dados no serviço de back-end sejam também removidos. Para persistir os dados entre as sessões de depuração, pode alterar o Modo de Depuração da Aplicação como propriedade no projeto Voting no Visual Studio.

Para ver o que acontece no código, conclua as seguintes etapas:

  1. Abra o arquivo VotingWeb\VotesController.cs e defina um ponto de Put interrupção no método da API da Web (linha 72).

  2. Abra o arquivo VotingData\VoteDataController.cs e defina um ponto de Put interrupção no método desta API da Web (linha 54).

  3. Selecione F5 para iniciar o aplicativo no modo de depuração.

  4. Volte ao navegador e selecione uma opção de voto ou adicione uma nova opção de voto. Você atinge o primeiro ponto de interrupção no controlador de API do front-end da Web.

    O JavaScript no navegador envia uma solicitação para o controlador de API da Web no serviço front-end:

    Captura de tela que mostra a adição de um serviço front-end de votação.

    1. Primeiro, construa a URL para o proxy reverso para o serviço back-end. (1)
    2. Em seguida, envie a solicitação HTTP PUT para o proxy reverso. (2)
    3. Finalmente, retorne a resposta do serviço de back-end para o cliente. (3)
  5. Selecione F5 para continuar.

    Agora você está no ponto de interrupção no serviço de back-end:

    Captura de tela que mostra a adição de um voto ao serviço de back-end.

    1. Na primeira linha do método, use stateManager para obter ou adicionar um dicionário confiável chamado counts. (1)
    2. Todas as interações que têm valores em um dicionário confiável exigem uma transação. Esta using instrução cria essa transação. (2)
    3. Na transação, atualize o valor da chave relevante para a opção de voto e confirme a operação. Quando o commit método retorna, os dados são atualizados no dicionário. Em seguida, ele se replica para outros nós no cluster. Os dados agora são armazenados com segurança no cluster e o serviço back-end pode fazer failover para outros nós e ainda ter os dados disponíveis. (3)
  6. Selecione F5 para continuar.

Para interromper a sessão de depuração, selecione Shift+F5.

Próximo passo

Avance para o tutorial seguinte: