Tutorial: Erstellen und Bereitstellen einer Anwendung mit einem ASP.NET Core-Web-API-Front-End-Dienst und einem zustandsbehafteten Back-End-DienstTutorial: Create and deploy an application with an ASP.NET Core Web API front-end service and a stateful back-end service

Dieses Tutorial ist der erste Teil einer Serie.This tutorial is part one of a series. Hier erfahren Sie, wie Sie eine Azure Service Fabric-Anwendung mit einem ASP.NET Core-Web-API-Front-End und einem zustandsbehafteten Back-End-Dienst zum Speichern Ihrer Daten erstellen.You will learn how to create an Azure Service Fabric application with an ASP.NET Core Web API front end and a stateful back-end service to store your data. Am Ende verfügen Sie über eine Abstimmungsanwendung mit einem ASP.NET Core-Web-Front-End, mit der Abstimmungsergebnisse im Cluster in einem zustandsbehafteten Back-End-Dienst gespeichert werden.When you're finished, you have a voting application with an ASP.NET Core web front-end that saves voting results in a stateful back-end service in the cluster. Wenn Sie die Abstimmungsanwendung nicht manuell erstellen möchten, können Sie den Quellcode für die fertige Anwendung herunterladen und mit Durchlaufen der Beispielanwendung für die Abstimmung fortfahren.If you don't want to manually create the voting application, you can download the source code for the completed application and skip ahead to Walk through the voting sample application. Wenn Sie möchten, können Sie sich auch eine schrittweise Videoanleitung zu diesem Tutorial ansehen.If you prefer, you can also watch a video walk-through of this tutorial.

AngularJS- + ASP.NET-API-Front-End, Herstellen einer Verbindung mit einem zustandsbehafteten Dienst in Service Fabric

Im ersten Teil der Serie lernen Sie Folgendes:In part one of the series, you learn how to:

  • Erstellen eines ASP.NET Core-Web-API-Diensts als zustandsbehafteter zuverlässiger DienstCreate an ASP.NET Core Web API service as a stateful reliable service
  • Erstellen eines ASP.NET Core-Webanwendungsdiensts als zustandsloser WebdienstCreate an ASP.NET Core Web Application service as a stateless web service
  • Kommunizieren mit dem zustandsbehafteten Dienst unter Verwendung des ReverseproxysUse the reverse proxy to communicate with the stateful service

In dieser Tutorialserie lernen Sie Folgendes:In this tutorial series you learn how to:

VoraussetzungenPrerequisites

Bevor Sie mit diesem Tutorial beginnen können, müssen Sie Folgendes tun:Before you begin this tutorial:

Erstellen eines ASP.NET-Web-API-Diensts als zuverlässigen DienstCreate an ASP.NET Web API service as a reliable service

Erstellen Sie mithilfe von ASP.NET Core zunächst das Web-Front-End der Abstimmungsanwendung.First, create the web front-end of the voting application using ASP.NET Core. ASP.NET Core ist ein einfaches, plattformübergreifendes Webentwicklungsframework, das Sie zur Erstellung von modernen Benutzeroberflächen und Web-APIs verwenden können.ASP.NET Core is a lightweight, cross-platform web development framework that you can use to create modern web UI and web APIs. Damit Sie die Integration von ASP.NET Core mit Service Fabric vollständig verstehen, wird dringend empfohlen, den Artikel ASP.NET Core in Service Fabric-Reliable Services zu lesen.To get a complete understanding of how ASP.NET Core integrates with Service Fabric, we strongly recommend reading through the ASP.NET Core in Service Fabric Reliable Services article. Für einen schnellen Einstieg reicht es jedoch, wenn Sie vorerst nur diesem Tutorial folgen.For now, you can follow this tutorial to get started quickly. Weitere Informationen zu ASP.NET Core finden Sie in der ASP.NET Core-Dokumentation.To learn more about ASP.NET Core, see the ASP.NET Core Documentation.

  1. Starten Sie Visual Studio als Administrator.Launch Visual Studio as an administrator.

  2. Erstellen Sie mit Datei->Neu->Projekt ein Projekt.Create a project with File->New->Project.

  3. Wählen Sie im Dialogfeld Neues Projekt die Option Cloud > Service Fabric-Anwendung aus.In the New Project dialog, choose Cloud > Service Fabric Application.

  4. Geben Sie der Anwendung den Namen Voting, und klicken Sie auf OK.Name the application Voting and click OK.

    Dialogfeld „Neues Projekt“ in Visual Studio

  5. Wählen Sie auf der Seite Neuer Service Fabric-Dienst die Option Zustandsloses ASP.NET Core aus, und nennen Sie den Dienst VotingWeb, und klicken Sie dann auf OK.On the New Service Fabric Service page, choose Stateless ASP.NET Core, name your service VotingWeb, then click OK.

    Auswählen eines neuen ASP.NET-Webdienstes im Dialogfeld „Neuer Dienst“

  6. Die nächste Seite umfasst eine Reihe von ASP.NET Core-Projektvorlagen.The next page provides a set of ASP.NET Core project templates. Wählen Sie für dieses Tutorial die Option Webanwendung (Model-View-Controller) , und klicken Sie dann auf OK.For this tutorial, choose Web Application (Model-View-Controller), then click OK.

    Auswählen des ASP.NET-Projekttyps

    Visual Studio erstellt ein Anwendungs- und ein Dienstprojekt und zeigt sie im Projektmappen-Explorer an.Visual Studio creates an application and a service project and displays them in Solution Explorer.

    Projektmappen-Explorer nach der Erstellung der Anwendung mit einem ASP.NET Core-Web-API-Dienst

Aktualisieren der Datei „site.js“Update the site.js file

Öffnen Sie die Datei wwwroot/js/site.js.Open wwwroot/js/site.js. Ersetzen Sie den Inhalt der Datei durch den folgenden JavaScript-Code, der von den Home-Ansichten verwendet wird, und speichern Sie anschließend Ihre Änderungen:Replace its contents with the following JavaScript used by the Home views, then save your changes.

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

Aktualisieren der Datei „Index.cshtml“Update the Index.cshtml file

Öffnen Sie die Datei Views/Home/Index.cshtml (die spezifische Ansicht für den Home-Controller).Open Views/Home/Index.cshtml, the view specific to the Home controller. Ersetzen Sie den Inhalt durch Folgendes, und speichern Sie anschließend Ihre Änderungen:Replace its contents with the following, then save your changes.

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

Aktualisieren der Datei „_Layout.cshtml“Update the _Layout.cshtml file

Öffnen Sie die Datei Views/Shared/_Layout.cshtml (das Standardlayout für die ASP.NET-App).Open Views/Shared/_Layout.cshtml, the default layout for the ASP.NET app. Ersetzen Sie den Inhalt durch Folgendes, und speichern Sie anschließend Ihre Änderungen:Replace its contents with the following, then save your changes.

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

Aktualisieren der Datei „VotingWeb.cs“Update the VotingWeb.cs file

Öffnen Sie die Datei VotingWeb.cs (erstellt den ASP.NET Core-Webhost innerhalb des zustandslosen Diensts unter Verwendung des WebListener-Webservers).Open the VotingWeb.cs file, which creates the ASP.NET Core WebHost inside the stateless service using the WebListener web server.

Fügen Sie am Anfang der Datei die Direktive using System.Net.Http; hinzu.Add the using System.Net.Http; directive to the top of the file.

Ersetzen Sie die Funktion CreateServiceInstanceListeners() durch den folgenden Code, und speichern Sie anschließend Ihre Änderungen.Replace the CreateServiceInstanceListeners() function with the following code, then save your changes.

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

Fügen Sie außerdem die folgende GetVotingDataServiceName-Methode unter CreateServiceInstanceListeners() hinzu, und speichern Sie anschließend Ihre Änderungen.Also add the following GetVotingDataServiceName method below CreateServiceInstanceListeners(), then save your changes. Wenn GetVotingDataServiceName abgerufen wird, wird der Name des Diensts zurückgegeben.GetVotingDataServiceName returns the service name when polled.

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

Hinzufügen der Datei „VotesController.cs“Add the VotesController.cs file

Fügen Sie einen Controller zum Definieren von Abstimmungsaktionen hinzu.Add a controller, which defines voting actions. Klicken Sie mit der rechten Maustaste auf den Ordner Controllers, und wählen Sie Hinzufügen > Neues Element > Visual C# > ASP.NET Core > Klasse aus.Right-click on the Controllers folder, then select Add->New item->Visual C#->ASP.NET Core->Class. Nennen Sie die Datei VotesController.cs, und klicken Sie auf Hinzufügen.Name the file VotesController.cs, then click Add.

Ersetzen Sie den Inhalt der Datei VotesController.cs durch Folgendes, und speichern Sie anschließend Ihre Änderungen.Replace the VotesController.cs file contents with the following, then save your changes. Unter Aktualisieren der Datei „VotesController.cs“ wird diese Datei dann für das Lesen und Schreiben von Abstimmungsdaten aus dem Back-End-Dienst angepasst.Later, in Update the VotesController.cs file, this file is modified to read and write voting data from the back-end service. Vorläufig gibt der Controller statische Zeichenfolgendaten an die Ansicht zurück.For now, the controller returns static string data to the view.

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

Konfigurieren des LauschportsConfigure the listening port

Beim Erstellen des VotingWeb Front-End-Diensts wählt Visual Studio nach dem Zufallsprinzip einen Port aus, an dem der Dienst lauscht.When the VotingWeb front-end service is created, Visual Studio randomly selects a port for the service to listen on. Der VotingWeb-Dienst fungiert als Front-End für diese Anwendung und akzeptiert externen Datenverkehr. Daher binden wir diesen Dienst an einen festen und bekannten Port.The VotingWeb service acts as the front-end for this application and accepts external traffic, so let's bind that service to a fixed and well-know port. Mit dem Dienstmanifest werden die Dienstendpunkte deklariert.The service manifest declares the service endpoints.

Öffnen Sie VotingWeb/PackageRoot/ServiceManifest.xml im Projektmappen-Explorer.In Solution Explorer, open VotingWeb/PackageRoot/ServiceManifest.xml. Navigieren Sie im Abschnitt Ressourcen zum Element Endpunkt, und legen Sie den Wert für Port auf 8080 fest.Find the Endpoint element in the Resources section and change the Port value to 8080. Wenn Sie die Anwendung lokal bereitstellen und ausführen möchten, muss der Anwendungslauschport auf dem Computer geöffnet und verfügbar sein.To deploy and run the application locally, the application listening port must be open and available on your 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>

Aktualisieren Sie außerdem den Wert der Eigenschaft „Anwendungs-URL“ im Projekt „Voting“, damit ein Webbrowser beim Debuggen der Anwendung mit dem korrekten Port geöffnet wird.Also update the Application URL property value in the Voting project so a web browser opens to the correct port when you debug your application. Wählen Sie im Projektmappen-Explorer das Projekt Voting aus, und ändern Sie die Eigenschaft Anwendungs-URL in 8080.In Solution Explorer, select the Voting project and update the Application URL property to 8080.

Lokales Bereitstellen und Ausführen der Anwendung „Voting“Deploy and run the Voting application locally

Sie können die Anwendung „Voting“ jetzt zum Debuggen ausführen.You can now go ahead and run the Voting application for debugging. Drücken Sie in Visual Studio F5, um die Anwendung für Ihren lokalen Service Fabric-Cluster im Debugmodus bereitzustellen.In Visual Studio, press F5 to deploy the application to your local Service Fabric cluster in debug mode. Die Anwendung schlägt fehl, wenn Sie Visual Studio zuvor nicht als Administrator geöffnet haben.The application will fail if you didn't previously open Visual Studio as administrator.

Hinweis

Wenn Sie die Anwendung zum ersten Mal lokal ausführen und bereitstellen, erstellt Visual Studio einen lokalen Service Fabric-Cluster für das Debuggen.The first time you run and deploy the application locally, Visual Studio creates a local Service Fabric cluster for debugging. Die Clustererstellung kann etwas dauern.Cluster creation may take some time. Der Status der Clustererstellung wird im Ausgabefenster von Visual Studio angezeigt.The cluster creation status is displayed in the Visual Studio output window.

Nachdem die Voting-Anwendung für Ihren lokalen Service Fabric-Cluster bereitgestellt wurde, wird Ihre Web-App automatisch in einer Browserregisterkarte geöffnet, und sollte wie folgt aussehen:After the Voting application has been deployed to your local Service Fabric cluster, your web app will open in a browser tab automatically and should look like this:

ASP.NET Core-Front-End

Zum Beenden des Debuggens der Anwendung wechseln Sie zurück zu Visual Studio, und drücken Sie UMSCHALT+F5.To stop debugging the application, go back to Visual Studio and press Shift+F5.

Hinzufügen eines zustandsbehafteten Back-End-Diensts zur AnwendungAdd a stateful back-end service to your application

Nachdem in der Anwendung nun ein ASP.NET-Web-API-Dienst ausgeführt wird, können Sie einen zustandsbehafteten zuverlässigen Dienst hinzufügen, um einige Daten in der Anwendung zu speichern.Now that an ASP.NET Web API service is running in the application, go ahead and add a stateful reliable service to store some data in the application.

Service Fabric ermöglicht eine konsistente und zuverlässige Speicherung von Daten direkt innerhalb des Diensts anhand von Reliable Collections.Service Fabric allows you to consistently and reliably store your data right inside your service by using reliable collections. Bei Reliable Collections handelt es sich um eine Gruppe hochverfügbarer und zuverlässiger Sammlungsklassen, die jedem vertraut sind, der bereits mit C#-Auflistungen gearbeitet hat.Reliable collections are a set of highly available and reliable collection classes that are familiar to anyone who has used C# collections.

In diesem Tutorial erstellen Sie einen Dienst, der einen Zählerwert in einer Reliable Collection speichert.In this tutorial, you create a service which stores a counter value in a reliable collection.

  1. Klicken Sie im Projektmappen-Explorer im Anwendungsprojekt „Voting“ mit der rechten Maustaste auf Dienste, und wählen Sie Hinzufügen > Neuer Service Fabric-Dienst aus.In Solution Explorer, right-click Services within the Voting application project and choose Add -> New Service Fabric Service....

  2. Wählen Sie im Dialogfeld Neuer Service Fabric-Dienst die Option Zustandsbehaftetes ASP.NET Core aus, nennen Sie den Dienst VotingData, und klicken Sie dann auf OK.In the New Service Fabric Service dialog, choose Stateful ASP.NET Core, name the service VotingData, then press OK.

    Nach Erstellung Ihres Dienstprojekts stehen Ihnen zwei Dienste in Ihrer Anwendung zur Verfügung.Once your service project is created, you have two services in your application. Bei der weiteren Erstellung Ihrer Anwendung können Sie weitere Dienste auf die gleiche Weise hinzufügen.As you continue to build your application, you can add more services in the same way. Diese können unabhängig versioniert und aktualisiert werden.Each can be independently versioned and upgraded.

  3. Die nächste Seite umfasst eine Reihe von ASP.NET Core-Projektvorlagen.The next page provides a set of ASP.NET Core project templates. Wählen Sie für dieses Tutorial API aus.For this tutorial, choose API.

    Visual Studio erstellt ein VotingData-Dienstprojekt und zeigt es im Projektmappen-Explorer an.Visual Studio creates the VotingData service project and displays it in Solution Explorer.

    Projektmappen-Explorer

Hinzufügen der Datei „VoteDataController.cs“Add the VoteDataController.cs file

Klicken Sie im Projekt VotingData mit der rechten Maustaste auf den Ordner Controllers, und wählen Sie Hinzufügen > Neues Element > Klasse aus.In the VotingData project, right-click on the Controllers folder, then select Add->New item->Class. Nennen Sie die Datei VoteDataController.cs, und klicken Sie auf Hinzufügen.Name the file VoteDataController.cs and click Add. Ersetzen Sie den Inhalt der Datei durch Folgendes, und speichern Sie anschließend Ihre Änderungen:Replace the file contents with the following, then save your changes.

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

Verbinden der DiensteConnect the services

Im nächsten Schritt verbinden Sie die beiden Dienste miteinander und sorgen dafür, dass die Front-End-Webanwendung Abstimmungsinformationen aus dem Back-End-Dienst abruft und festlegt.In this next step, connect the two services and make the front-end Web application get and set voting information from the back-end service.

Service Fabric bietet absolute Flexibilität bei der Kommunikation mit Reliable Services.Service Fabric provides complete flexibility in how you communicate with reliable services. Sie können in einer Anwendung über Dienste verfügen, auf die über TCP zugegriffen werden kann.Within a single application, you might have services that are accessible via TCP. Auf andere Dienste wird möglicherweise über eine HTTP-REST-API zugegriffen, und bei wieder anderen Diensten erfolgt der Zugriff über Websockets.Other services that might be accessible via an HTTP REST API and still other services could be accessible via web sockets. Ausführliche Informationen zu den verfügbaren Optionen und deren Vor- und Nachteilen finden Sie unter Kommunizieren mit Diensten.For background on the options available and the tradeoffs involved, see Communicating with services.

In diesem Tutorial verwenden Sie die ASP.NET Core-Web-API und den Service Fabric-Reverseproxy, damit der Front-End-Webdienst „VotingWeb“ mit dem Back-End-Datendienst „VotingData“ kommunizieren kann.This tutorial uses ASP.NET Core Web API and the Service Fabric reverse proxy so the VotingWeb front-end web service can communicate with the back-end VotingData service. Der Reverseproxy ist standardmäßig zur Verwendung des Ports 19081 konfiguriert und sollte für dieses Tutorial funktionieren.The reverse proxy is configured by default to use port 19081 and should work for this tutorial. Der Port des Reverseproxys ist in der Azure Resource Manager-Vorlage zum Einrichten des Clusters festgelegt.The reverse proxy port is set in the Azure Resource Manager template used to set up the cluster. Welcher Port verwendet wird, geht aus der Cluster-Vorlage in der Ressource Microsoft.ServiceFabric/clusters hervor:To find which port is used, look in the cluster template in the Microsoft.ServiceFabric/clusters resource:

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

Um den in Ihrem lokalen Entwicklungscluster verwendeten Port des Reverseproxys zu ermitteln, sehen Sie sich das HttpApplicationGatewayEndpoint-Element im lokalen Service Fabric-Clustermanifest an:To find the reverse proxy port used in your local development cluster, view the HttpApplicationGatewayEndpoint element in the local Service Fabric cluster manifest:

  1. Öffnen Sie ein Browserfenster, und navigieren Sie zu http://localhost:19080, um das Tool Service Fabric Explorer zu öffnen.Open a browser window and navigate to http://localhost:19080 to open the Service Fabric Explorer tool.
  2. Wählen Sie Cluster > Manifest aus.Select Cluster -> Manifest.
  3. Notieren Sie sich den Port des Elements „HttpApplicationGatewayEndpoint“.Make a note of the HttpApplicationGatewayEndpoint element port. Dieser sollte standardmäßig 19081 sein.By default this should be 19081. Wenn es nicht 19081 ist, müssen Sie den Port in der Methode „GetProxyAddress“ im folgenden Code in der Datei „VotesController.cs“ ändern.If it is not 19081, you will need to change the port in the GetProxyAddress method of the following VotesController.cs code.

Aktualisieren der Datei „VotesController.cs“Update the VotesController.cs file

Öffnen Sie im Projekt VotingWeb die Datei Controllers/VotesController.cs.In the VotingWeb project, open the Controllers/VotesController.cs file. Ersetzen Sie den Inhalt der Definition der Klasse VotesController durch Folgendes, und speichern Sie anschließend Ihre Änderungen:Replace the VotesController class definition contents with the following, then save your changes. Wenn der Reverseproxyport, den Sie im vorherigen Schritt ermittelt haben, nicht 19081 ist, ändern Sie den Port in der Methode „GetProxyAddress“ verwendeten Port von 19081 in den ermittelten Port.If the reverse proxy port you discovered in the pervious step is not 19081, change the port used in the GetProxyAddress method from 19081 to the port that you discovered.

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

Durchlaufen der Beispielanwendung für die AbstimmungWalk through the voting sample application

Die Abstimmungsanwendung besteht aus zwei Diensten:The voting application consists of two services:

  • Web-Front-End-Dienst (VotingWeb): Ein ASP.NET Core-Web-Front-End-Dienst, der die Webseite bereitstellt und Web-APIs für die Kommunikation mit dem Back-End-Dienst verfügbar macht.Web front-end service (VotingWeb)- An ASP.NET Core web front-end service, which serves the web page and exposes web APIs to communicate with the backend service.
  • Back-End-Dienst (VotingData): Ein ASP.NET Core-Web-Dienst, der eine API verfügbar macht, um die Abstimmungsergebnisse in einem zuverlässigen Wörterbuch zu speichern, das dauerhaft auf dem Datenträger vorhanden ist.Back-end service (VotingData)- An ASP.NET Core web service, which exposes an API to store the vote results in a reliable dictionary persisted on disk.

Anwendungsdiagramm

Beim Abstimmen in der Anwendung treten die folgenden Ereignisse ein:When you vote in the application the following events occur:

  1. Ein JavaScript sendet die Abstimmungsanforderung als HTTP PUT-Anforderung an die Web-API im Web-Front-End-Dienst.A JavaScript sends the vote request to the web API in the web front-end service as an HTTP PUT request.

  2. Der Web-Front-End-Dienst nutzt einen Proxy, um eine HTTP PUT-Anforderung zu lokalisieren und an den Back-End-Dienst weiterzuleiten.The web front-end service uses a proxy to locate and forward an HTTP PUT request to the back-end service.

  3. Der Back-End-Dienst erhält die eingehende Anforderung und speichert das aktualisierte Ergebnis in einem zuverlässigen Wörterbuch, das auf mehreren Knoten im Cluster repliziert und dauerhaft auf dem Datenträger gespeichert wird.The back-end service takes the incoming request, and stores the updated result in a reliable dictionary, which gets replicated to multiple nodes within the cluster and persisted on disk. Alle Daten der Anwendung werden im Cluster gespeichert, sodass keine Datenbank erforderlich ist.All the application's data is stored in the cluster, so no database is needed.

Debuggen in Visual StudioDebug in Visual Studio

Beim Debuggen der Anwendung in Visual Studio verwenden Sie einen lokalen Service Fabric-Entwicklungscluster.When debugging application in Visual Studio, you are using a local Service Fabric development cluster. Sie haben die Möglichkeit, Ihre Oberfläche für das Debuggen an Ihr Szenario anzupassen.You have the option to adjust your debugging experience to your scenario. In dieser Anwendung speichern Sie Daten im Back-End-Dienst, indem Sie ein zuverlässiges Wörterbuch verwenden.In this application, store data in the back-end service using a reliable dictionary. Standardmäßig wird die Anwendung von Visual Studio entfernt, wenn Sie den Debugger beenden.Visual Studio removes the application per default when you stop the debugger. Die Entfernung der Anwendung führt dazu, dass auch die Daten im Back-End-Dienst entfernt werden.Removing the application causes the data in the back-end service to also be removed. Um die Daten zwischen den Debugsitzungen beizubehalten, können Sie den Debugmodus für die Anwendung als Eigenschaft im Projekt Voting in Visual Studio ändern.To persist the data between debugging sessions, you can change the Application Debug Mode as a property on the Voting project in Visual Studio.

Führen Sie die folgenden Schritte aus, um zu ermitteln, was im Code passiert:To look at what happens in the code, complete the following steps:

  1. Öffnen Sie die Datei VotingWeb\VotesController.cs, und legen Sie in der Put-Methode der Web-API (Zeile 72) einen Haltepunkt fest.Open the VotingWeb\VotesController.cs file and set a breakpoint in the web API's Put method (line 72).

  2. Öffnen Sie die Datei VotingData\VoteDataController.cs, und legen Sie in der Put-Methode der Web-API (Zeile 54) einen Haltepunkt fest.Open the VotingData\VoteDataController.cs file and set a breakpoint in this web API's Put method (line 54).

  3. Drücken Sie F5, um die Anwendung im Debugmodus auszuführen.Press F5 to start the application in debug mode.

  4. Wechseln Sie zurück in den Browser, und klicken Sie auf eine Abstimmungsoption, oder fügen Sie eine neue Abstimmungsoption hinzu.Go back to the browser and click a voting option or add a new voting option. Sie stoßen im API-Controller des Web-Front-Ends auf den ersten Breakpoint.You hit the first breakpoint in the web front-end's api controller.

    1. An diesem Punkt sendet das JavaScript im Browser eine Anforderung an den Web-API-Controller im Front-End-Dienst.This is where the JavaScript in the browser sends a request to the web API controller in the front-end service.

      Front-End-Dienst „Stimme hinzufügen“

    2. Erstellen Sie zunächst die URL zum Reverseproxy für den Back-End-Dienst (1) .First construct the URL to the ReverseProxy for the back-end service (1).

    3. Senden Sie anschließend die HTTP PUT-Anforderung an den Reverseproxy (2) .Then send the HTTP PUT Request to the ReverseProxy (2).

    4. Zum Schluss wird die Antwort vom Back-End-Dienst an den Client (3) zurückgegeben.Finally the return the response from the back-end service to the client (3).

  5. Drücken Sie F5, um fortzufahren.Press F5 to continue.

    1. Sie befinden sich jetzt am Breakpoint im Back-End-Dienst.You are now at the break point in the back-end service.

      Back-End-Dienst „Stimme hinzufügen“

    2. Verwenden Sie in der ersten Zeile der Methode (1) das StateManager-Element, um ein zuverlässiges Wörterbuch mit dem Namen counts abzurufen bzw. hinzuzufügen.In the first line in the method (1) use the StateManager to get or add a reliable dictionary called counts.

    3. Für alle Interaktionen mit Werten in einem zuverlässigen Wörterbuch ist eine Transaktion erforderlich. Diese Transaktion wird mithilfe der Anweisung (2) erstellt.All interactions with values in a reliable dictionary require a transaction, this using statement (2) creates that transaction.

    4. Aktualisieren Sie in der Transaktion den Wert des relevanten Schlüssels für die Abstimmungsoption, und committen Sie den Vorgang (3) .In the transaction, update the value of the relevant key for the voting option and commits the operation (3). Nachdem die Rückgabe für die Commit-Methode durchgeführt wurde, werden die Daten im Wörterbuch aktualisiert und auf anderen Knoten im Cluster repliziert.Once the commit method returns, the data is updated in the dictionary and replicated to other nodes in the cluster. Die Daten sind jetzt sicher im Cluster gespeichert, und der Back-End-Dienst kann das Failover auf andere Knoten durchführen, während die Daten weiterhin verfügbar sind.The data is now safely stored in the cluster, and the back-end service can fail over to other nodes, still having the data available.

  6. Drücken Sie F5, um fortzufahren.Press F5 to continue.

Drücken Sie UMSCHALT+F5, um die Debugsitzung zu beenden.To stop the debugging session, press Shift+F5.

Nächste SchritteNext steps

In diesem Teil des Tutorials haben Sie Folgendes gelernt:In this part of the tutorial, you learned how to:

  • Erstellen eines ASP.NET Core-Web-API-Diensts als zustandsbehafteter zuverlässiger DienstCreate an ASP.NET Core Web API service as a stateful reliable service
  • Erstellen eines ASP.NET Core-Webanwendungsdiensts als zustandsloser WebdienstCreate an ASP.NET Core Web Application service as a stateless web service
  • Kommunizieren mit dem zustandsbehafteten Dienst unter Verwendung des ReverseproxysUse the reverse proxy to communicate with the stateful service

Fahren Sie mit dem nächsten Tutorial fort:Advance to the next tutorial: