Host ASP.NET-Web-API 2 in einer Azure-Workerrolle

von Mike Wasson

In diesem Tutorial erfahren Sie, wie Sie ASP.NET-Web-API in einer Azure-Workerrolle hosten, indem Sie OWIN verwenden, um das Web-API-Framework selbst zu hosten.

Open Web Interface for .NET (OWIN) definiert eine Abstraktion zwischen .NET-Webservern und Webanwendungen. OWIN entkoppelt die Webanwendung vom Server. Dadurch eignet sich OWIN ideal für das Selbsthosting einer Webanwendung in Ihrem eigenen Prozess, außerhalb von IIS, z. B. innerhalb einer Azure-Workerrolle.

In diesem Tutorial verwenden Sie das Paket Microsoft.Owin.Host.HttpListener, das einen HTTP-Server bereitstellt, der zum Selbsthosten von OWIN-Anwendungen verwendet wird.

Im Tutorial verwendete Softwareversionen

Erstellen eines Microsoft Azure-Projekts

Starten Sie Visual Studio mit Administratorrechten. Administratorrechte sind erforderlich, um die Anwendung mithilfe des Azure-Computeemulators lokal zu debuggen.

Klicken Sie im Menü Datei auf Neu und dann auf Projekt. Klicken Sie unter Installierte Vorlagen unter Visual C# auf Cloud und dann auf Windows Azure Cloud Service. Nennen Sie das Projekt "AzureApp", und klicken Sie auf OK.

Screenshot des Dialogfelds

Doppelklicken Sie im Dialogfeld Neuer Windows Azure-Clouddienst auf Workerrolle. Behalten Sie den Standardnamen ("WorkerRole1") bei. In diesem Schritt wird der Lösung eine Workerrolle hinzugefügt. Klicken Sie auf OK.

Screenshot des Dialogfelds

Die erstellte Visual Studio-Projektmappe enthält zwei Projekte:

  • "AzureApp" definiert die Rollen und die Konfiguration für die Azure-Anwendung.
  • "WorkerRole1" enthält den Code für die Workerrolle.

Im Allgemeinen kann eine Azure-Anwendung mehrere Rollen enthalten, obwohl in diesem Tutorial eine einzelne Rolle verwendet wird.

Screenshot des Projektmappen-Explorer-Fensters, in dem das neue Azure-App-Projekt hervorgehoben ist und darunter die Option App-Name und Workerrolle angezeigt wird.

Hinzufügen der Web-API und der OWIN-Pakete

Klicken Sie im Menü Extras auf NuGet-Paket-Manager und dann auf Paket-Manager-Konsole.

Geben Sie im Fenster Paket-Manager-Konsole den folgenden Befehl ein:

Install-Package Microsoft.AspNet.WebApi.OwinSelfHost

Hinzufügen eines HTTP-Endpunkts

Erweitern Sie in Projektmappen-Explorer das Projekt AzureApp. Erweitern Sie den Knoten Rollen, klicken Sie mit der rechten Maustaste auf WorkerRole1, und wählen Sie Eigenschaften aus.

Screenshot des Fenstermenüs des Projektmappen-Explorers, in dem die Schritte zum Auswählen der Eigenschafteneinstellungen der Workerrolle hervorgehoben sind.

Klicken Sie auf Endpunkte und dann auf Endpunkt hinzufügen.

Wählen Sie in der Dropdownliste Protokoll die Option "http" aus. Geben Sie unter Öffentlicher Port und privater Port den Wert 80 ein. Diese Portnummern dürfen sich unterscheiden. Der öffentliche Port wird von Clients verwendet, wenn sie eine Anforderung an die Rolle senden.

Screenshot der Dropdownmenüoptionen für das Protokoll, in dem die verschiedenen Dienstkonfigurationen und Endpunktoptionen angezeigt werden.

Konfigurieren der Web-API für Self-Host

Klicken Sie in Projektmappen-Explorer mit der rechten Maustaste auf das Projekt WorkerRole1, und wählen SieKlassehinzufügen / aus, um eine neue Klasse hinzuzufügen. Geben Sie der Klassen den Namen Startup.

Screenshot des Projektmappen-Explorer-Fensters mit den Menüoptionen und hervorgehobenem Pfad zum Hinzufügen einer Klasse.

Ersetzen Sie den gesamten Code der Bausteine in dieser Datei durch Folgendes:

using Owin;
using System.Web.Http;

namespace WorkerRole1
{
    class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            HttpConfiguration config = new HttpConfiguration();
            config.Routes.MapHttpRoute(
                "Default",
                "{controller}/{id}",
                new { id = RouteParameter.Optional });

            app.UseWebApi(config);
        }
    }
}

Hinzufügen eines Web-API-Controllers

Fügen Sie als Nächstes eine Web-API-Controllerklasse hinzu. Klicken Sie mit der rechten Maustaste auf das Projekt WorkerRole1, und wählen SieKlassehinzufügen / aus. Nennen Sie die Klasse TestController. Ersetzen Sie den gesamten Code der Bausteine in dieser Datei durch Folgendes:

using System;
using System.Net.Http;
using System.Web.Http;

namespace WorkerRole1
{
    public class TestController : ApiController
    {
        public HttpResponseMessage Get()
        {
            return new HttpResponseMessage()
            {
                Content = new StringContent("Hello from OWIN!")
            };
        }

        public HttpResponseMessage Get(int id)
        {
            string msg = String.Format("Hello from OWIN (id = {0})", id);
            return new HttpResponseMessage()
            {
                Content = new StringContent(msg)
            };
        }
    }
}

Der Einfachheit halber definiert dieser Controller nur zwei GET-Methoden, die Nur-Text zurückgeben.

Starten des OWIN-Hosts

Öffnen Sie die Datei WorkerRole.cs. Diese Klasse definiert den Code, der ausgeführt wird, wenn die Workerrolle gestartet und beendet wird.

Fügen Sie die folgende using-Anweisung hinzu:

using Microsoft.Owin.Hosting;

Fügen Sie der WorkerRole -Klasse ein IDisposable-Element hinzu:

public class WorkerRole : RoleEntryPoint
{
    private IDisposable _app = null;

    // ....
}

Fügen Sie in der OnStart -Methode den folgenden Code hinzu, um den Host zu starten:

public override bool OnStart()
{
    ServicePointManager.DefaultConnectionLimit = 12;

    // New code:
    var endpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["Endpoint1"];
    string baseUri = String.Format("{0}://{1}", 
        endpoint.Protocol, endpoint.IPEndpoint);

    Trace.TraceInformation(String.Format("Starting OWIN at {0}", baseUri), 
        "Information");

    _app = WebApp.Start<Startup>(new StartOptions(url: baseUri));
    return base.OnStart();
}

Die WebApp.Start-Methode startet den OWIN-Host. Der Name der Startup -Klasse ist ein Typparameter für die -Methode. Gemäß Konvention ruft der Host die Configure -Methode dieser Klasse auf.

Überschreiben Sie, um die OnStop_app instance zu verwerfen:

public override void OnStop()
{
    if (_app != null)
    {
        _app.Dispose();
    }
    base.OnStop();
}

Hier sehen Sie den vollständigen Code für WorkerRole.cs:

using Microsoft.Owin.Hosting;
using Microsoft.WindowsAzure.ServiceRuntime;
using System;
using System.Diagnostics;
using System.Net;
using System.Threading;

namespace WorkerRole1
{
    public class WorkerRole : RoleEntryPoint
    {
        private IDisposable _app = null;

        public override void Run()
        {
            Trace.TraceInformation("WebApiRole entry point called", "Information");

            while (true)
            {
                Thread.Sleep(10000);
                Trace.TraceInformation("Working", "Information");
            }
        }

        public override bool OnStart()
        {
            ServicePointManager.DefaultConnectionLimit = 12;

            var endpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["Endpoint1"];
            string baseUri = String.Format("{0}://{1}", 
                endpoint.Protocol, endpoint.IPEndpoint);

            Trace.TraceInformation(String.Format("Starting OWIN at {0}", baseUri), 
                "Information");

            _app = WebApp.Start<Startup>(new StartOptions(url: baseUri));
           return base.OnStart();
        }

        public override void OnStop()
        {
            if (_app != null)
            {
                _app.Dispose();
            }
            base.OnStop();
        }
    }
}

Erstellen Sie die Lösung, und drücken Sie F5, um die Anwendung lokal im Azure-Computeemulator auszuführen. Abhängig von Ihren Firewalleinstellungen müssen Sie möglicherweise den Emulator über Ihre Firewall zulassen.

Hinweis

Wenn Sie eine Ausnahme wie die folgende erhalten, finden Sie in diesem Blogbeitrag eine Problemumgehung. "Datei oder Assembly 'Microsoft.Owin, Version=2.0.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' oder eine ihrer Abhängigkeiten konnte nicht geladen werden. Die Manifestdefinition der befindeten Assembly stimmt nicht mit dem Assemblyverweis überein. (Ausnahme von HRESULT: 0x80131040)"

Der Computeemulator weist dem Endpunkt eine lokale IP-Adresse zu. Sie können die IP-Adresse finden, indem Sie die Benutzeroberfläche des Computeemulators anzeigen. Klicken Sie im Infobereich der Taskleiste mit der rechten Maustaste auf das Emulatorsymbol, und wählen Sie Computeemulator-Benutzeroberfläche anzeigen aus.

Screenshot der Azure Compute Emulator-U I mit dem Menü und den Ip-Endpunktadresseninformationen, wenn Sie die Option

Suchen Sie die IP-Adresse unter Dienstbereitstellungen, Bereitstellung [ID], Dienstdetails. Öffnen Sie einen Webbrowser, und navigieren Sie zu http:// adresse/test/1, wobei adresse die vom Computeemulator zugewiesene IP-Adresse ist. beispiel: http://127.0.0.1:80/test/1. Die Antwort des Web-API-Controllers sollte angezeigt werden:

Screenshot des Browserfensters mit der Antwort des Web-AP-Controllers nach Eingabe der vom Computeemulator zugewiesenen IP-Adresse.

In Azure bereitstellen

Für diesen Schritt benötigen Sie ein Azure-Konto. Wenn Sie noch nicht über ein Konto verfügen, können Sie in wenigen Minuten ein kostenloses Testkonto erstellen. Weitere Informationen finden Sie unter Kostenlose Microsoft Azure-Testversion.

Klicken Sie in Projektmappen-Explorer mit der rechten Maustaste auf das Projekt AzureApp. Wählen Sie Veröffentlichen aus.

Screenshot der Menüoptionen des Projektmappen-Explorer-Fensters, in dem die Schritte zum Bereitstellen oder Veröffentlichen des Projekts hervorgehoben sind.

Wenn Sie nicht bei Ihrem Azure-Konto angemeldet sind, klicken Sie auf Anmelden.

Screenshot des Dialogfelds

Nachdem Sie angemeldet sind, wählen Sie ein Abonnement aus, und klicken Sie auf Weiter.

Screenshot:

Geben Sie einen Namen für den Clouddienst ein, und wählen Sie eine Region aus. Klicken Sie auf Erstellen.

Screenshot des Dialogfelds

Klicken Sie auf Veröffentlichen.

Screenshot des Fensters

Konfigurieren eines benutzerdefinierten Domänennamens für einen Azure-Clouddienst (klassisch)

Zusätzliche Ressourcen