Übersicht über das Katana-Projekt

von Howard Dierking

Das ASP.NET Framework gibt es seit über zehn Jahren, und die Plattform hat die Entwicklung unzähliger Websites und Dienste ermöglicht. Mit der Entwicklung von Webanwendungen konnte sich das Framework in Schritt mit Technologien wie ASP.NET MVC und ASP.NET-Web-API weiterentwickeln. Da die Entwicklung von Webanwendungen den nächsten evolutionären Schritt in die Welt des Cloud Computings macht, stellt Projekt Katana den zugrunde liegenden Satz von Komponenten für ASP.NET Anwendungen bereit, sodass sie flexibel, portabel, leicht und eine bessere Leistung bieten können – anders ausgedrückt: Project Katana Cloud optimiert Ihre ASP.NET Anwendungen.

Warum Katana – Warum jetzt?

Unabhängig davon, ob es sich um ein Entwicklerframework oder ein Endbenutzerprodukt handelt, ist es wichtig, die zugrunde liegenden Beweggründe für die Erstellung des Produkts zu verstehen – und dazu gehört auch, zu wissen, für wen das Produkt erstellt wurde. ASP.NET wurde ursprünglich für zwei Kunden entwickelt.

Die erste Kundengruppe waren klassische ASP-Entwickler. Zu dieser Zeit war ASP eine der wichtigsten Technologien zum Erstellen dynamischer, datengesteuerter Websites und Anwendungen durch die Verzahnung von Markup und serverseitigem Skript. Die ASP-Runtime lieferte ein serverseitiges Skript mit einer Reihe von Objekten, die Kernaspekte des zugrunde liegenden HTTP-Protokolls und webservers abstrahierten und Zugriff auf zusätzliche Dienste wie Sitzungs- und Anwendungsstatusverwaltung, Cache usw. gewährten. Obwohl leistungsstarke, klassische ASP-Anwendungen wurden zu einer Herausforderung bei der Verwaltung, da sie an Größe und Komplexität wuchsen. Dies war vor allem auf die fehlende Struktur in Skriptumgebungen in Verbindung mit der Duplizierung von Code zurückzuführen, die sich aus der Verschachtelung von Code und Markup ergibt. Um die Stärken des klassischen ASP zu nutzen und gleichzeitig einige seiner Herausforderungen zu bewältigen, nutzten ASP.NET den Code organization, die von den objektorientierten Sprachen des .NET Framework bereitgestellt wurden, während gleichzeitig das serverseitige Programmiermodell beibehalten wurde, an das sich klassische ASP-Entwickler gewöhnt hatten.

Die zweite Gruppe von Zielkunden für ASP.NET waren Windows-Geschäftsanwendungsentwickler. Im Gegensatz zu klassischen ASP-Entwicklern, die es gewohnt waren, HTML-Markup und den Code zu schreiben, um mehr HTML-Markup zu generieren, waren WinForms-Entwickler (wie die VB6-Entwickler vor ihnen) an eine Entwurfszeiterfahrung gewöhnt, die einen Canvas und einen umfangreichen Satz von Steuerelementen für die Benutzeroberfläche enthielt. Die erste Version von ASP.NET – auch als "Web Forms" bezeichnet – bot eine ähnliche Entwurfszeit sowie ein serverseitiges Ereignismodell für Benutzeroberflächenkomponenten und eine Reihe von Infrastrukturfeatures (z. B. ViewState), um eine nahtlose Entwicklerumgebung zwischen client- und serverseitiger Programmierung zu schaffen. Web Forms die zustandslose Natur des Webs effektiv unter einem zustandsbehafteten Ereignismodell versteckt, das WinForms-Entwicklern vertraut war.

Herausforderungen des historischen Modells

Das Nettoergebnis war ein ausgereiftes, funktionsreiches Runtime- und Entwicklerprogrammiermodell. Mit diesem Featurereichtum kamen jedoch einige bemerkenswerte Herausforderungen. Erstens war das Framework monolithisch, wobei logisch ungleiche Funktioneneinheiten eng in derselben System.Web.dll Assembly gekoppelt waren (z. B. die zentralen HTTP-Objekte mit dem Web Forms-Framework). Zweitens wurde ASP.NET als Teil der größeren .NET Framework einbezogen, was bedeutet, dass die Zeit zwischen den Releases in der Größenordnung von Jahren lag. Dies machte es für ASP.NET schwierig, mit all den Veränderungen in der sich schnell entwickelnden Webentwicklung Schritt zu halten. Schließlich wurde System.Web.dll selbst auf verschiedene Weise mit einer bestimmten Webhostingoption gekoppelt: Internetinformationsdienste (IIS).

Evolutionsschritte: ASP.NET MVC und ASP.NET-Web-API

Und in der Webentwicklung hat sich viel verändert! Webanwendungen wurden zunehmend als eine Reihe von kleinen, fokussierten Komponenten statt als große Frameworks entwickelt. Die Anzahl der Komponenten sowie die Häufigkeit, mit der sie freigegeben wurden, nahm immer schneller zu. Es war klar, dass Frameworks, um mit dem Web Schritt zu halten, kleiner, entkoppelt und fokussierter werden müssen, anstatt größer und funktionsreicher zu sein. Daher hat das ASP.NET-Team mehrere evolutionäre Schritte unternommen, um ASP.NET als eine Familie von pluggablen Webkomponenten anstelle eines einzelnen Frameworks zu ermöglichen.

Eine der frühen Änderungen war die zunehmende Popularität des bekannten Modell-Sicht-Controller-Entwurfsmusters (MVC) dank Webentwicklungsframeworks wie Ruby on Rails. Diese Art der Erstellung von Webanwendungen gab dem Entwickler eine bessere Kontrolle über das Markup seiner Anwendung, während die Trennung von Markup und Geschäftslogik beibehalten wurde, was eines der ersten Verkaufsargumente für ASP.NET war. Um die Nachfrage nach dieser Art der Webanwendungsentwicklung zu erfüllen, nutzte Microsoft die Gelegenheit, sich besser für die Zukunft zu positionieren, indem ASP.NET MVC out of band entwickelt (und nicht in die .NET Framework aufgenommen wurde). ASP.NET MVC wurde als unabhängiger Download veröffentlicht. Dies gab dem Entwicklungsteam die Flexibilität, Updates viel häufiger als bisher zu liefern.

Ein weiterer wichtiger Wandel in der Webanwendungsentwicklung war die Umstellung von dynamischen, vom Server generierten Webseiten zum statischen anfänglichen Markup mit dynamischen Abschnitten der Seite, die aus clientseitigen Skripts generiert wurden, die über AJAX-Anforderungen mit Back-End-Web-APIs kommunizieren. Dieser Architekturwandel trug dazu bei, den Aufstieg von Web-APIs und die Entwicklung des ASP.NET-Web-API Frameworks zu fördern. Wie bei ASP.NET MVC bot die Veröffentlichung von ASP.NET-Web-API eine weitere Möglichkeit, sich ASP.NET als modulareres Framework weiterzuentwickeln. Das Entwicklungsteam nutzte die Gelegenheit und baute ASP.NET-Web-API so auf, dass es keine Abhängigkeiten von den Kernframeworktypen in System.Web.dllhatte. Dies ermöglichte zwei Dinge: Erstens bedeutete dies, dass sich ASP.NET-Web-API vollständig eigenständig weiterentwickeln konnte (und schnell weiter iterieren konnte, da es über NuGet bereitgestellt wird). Zweitens, da es keine externen Abhängigkeiten für System.Web.dll und daher keine Abhängigkeiten von IIS gab, ASP.NET-Web-API die Funktion zum Ausführen in einem benutzerdefinierten Host (z. B. einer Konsolenanwendung, einem Windows-Dienst usw.) enthalten.

Die Zukunft: Ein agiles Framework

Durch das Entkoppeln von Frameworkkomponenten und deren Freigabe auf NuGet könnten Frameworks jetzt unabhängiger und schneller iterieren. Darüber hinaus erwies sich die Leistungsfähigkeit und Flexibilität der Selbsthostingfunktion der Web-API als sehr attraktiv für Entwickler, die einen kleinen, einfachen Host für ihre Dienste wollten. Es erwies sich als so attraktiv, dass andere Frameworks diese Funktion auch wollten, und dies stellte eine neue Herausforderung dar, da jedes Framework in seinem eigenen Hostprozess an seiner eigenen Basisadresse lief und unabhängig (gestartet, beendet usw.) verwaltet werden musste. Eine moderne Webanwendung unterstützt in der Regel statische Dateibereitstellung, dynamische Seitengenerierung, Web-API und neuerdings Echtzeit-/Pushbenachrichtigungen. Die Erwartung, dass jeder dieser Dienste unabhängig ausgeführt und verwaltet werden sollte, war einfach nicht realistisch.

Was erforderlich war, war eine einzelne Hosting-Abstraktion, die es einem Entwickler ermöglichte, eine Anwendung aus einer Vielzahl verschiedener Komponenten und Frameworks zu erstellen und diese Anwendung dann auf einem unterstützenden Host auszuführen.

Open Web Interface for .NET (OWIN)

Inspiriert von den Vorteilen , die Rack in der Ruby-Community erzielt hat, haben sich mehrere Mitglieder der .NET-Community zum Ziel gesetzt, eine Abstraktion zwischen Webservern und Frameworkkomponenten zu erstellen. Zwei Entwurfsziele für die OWIN-Abstraktion bestand darin, dass sie einfach war und dass nur wenige mögliche Abhängigkeiten von anderen Frameworktypen benötigt wurden. Diese beiden Ziele tragen dazu bei, Folgendes sicherzustellen:

  • Neue Komponenten könnten leichter entwickelt und genutzt werden.
  • Anwendungen können einfacher zwischen Hosts und möglicherweise ganzen Plattformen/Betriebssystemen portiert werden.

Die resultierende Abstraktion besteht aus zwei Kernelementen. Die erste ist das Umgebungswörterbuch. Diese Datenstruktur ist für das Speichern des gesamten Zustands verantwortlich, der für die Verarbeitung einer HTTP-Anforderung und -Antwort erforderlich ist, sowie für alle relevanten Serverzustände. Das Umgebungswörterbuch ist wie folgt definiert:

IDictionary<string, object>

Ein OWIN-kompatibler Webserver ist für das Auffüllen des Umgebungswörterbuchs mit Daten wie den Textdatenströmen und Headersammlungen für eine HTTP-Anforderung und -Antwort verantwortlich. Es liegt dann in der Verantwortung der Anwendungs- oder Frameworkkomponenten, das Wörterbuch mit zusätzlichen Werten aufzufüllen oder zu aktualisieren und in den Antworttextdatenstrom zu schreiben.

Zusätzlich zum Angeben des Typs für das Umgebungswörterbuch definiert die OWIN-Spezifikation eine Liste der Wichtigsten Wörterbuchschlüsselwertpaare. Die folgende Tabelle zeigt beispielsweise die erforderlichen Wörterbuchschlüssel für eine HTTP-Anforderung:

Schlüsselname Wertbeschreibung
"owin.RequestBody" Ein Stream mit dem Anforderungstext, falls vorhanden. Stream.Null KANN als Platzhalter verwendet werden, wenn kein Anforderungstext vorhanden ist. Siehe Anforderungstext.
"owin.RequestHeaders" Ein IDictionary<string, string[]> von Anforderungsheadern. Siehe Header.
"owin.RequestMethod" Eine string , die die HTTP-Anforderungsmethode der Anforderung enthält (z. B. "GET", "POST").
"owin.RequestPath" Ein string , der den Anforderungspfad enthält. Der Pfad MUSS relativ zum "Stamm" des Anwendungsdelegats sein. siehe Pfade.
"owin.RequestPathBase" Eine string , die den Teil des Anforderungspfads enthält, der dem "Stamm" des Anwendungsdelegats entspricht; siehe Pfade.
"owin.RequestProtocol" Einestring, die den Protokollnamen und die Version (z. B. oder "HTTP/1.1") enthält. "HTTP/1.0"
"owin.RequestQueryString" Eine string , die die Abfragezeichenfolgenkomponente des HTTP-Anforderungs-URI ohne das führende "?" enthält. (z. B. "foo=bar&baz=quux"). Der Wert kann eine leere Zeichenfolge sein.
"owin.RequestScheme" Ein string , der das für die Anforderung verwendete URI-Schema enthält (z. B. "http", "https"); siehe URI-Schema.

Das zweite Schlüsselelement von OWIN ist der Anwendungsdelegat. Dies ist eine Funktionssignatur, die als primäre Schnittstelle zwischen allen Komponenten in einer OWIN-Anwendung dient. Die Definition für den Anwendungsdelegat lautet wie folgt:

Func<IDictionary<string, object>, Task>;

Der Anwendungsdelegat ist dann einfach eine Implementierung des Func-Delegattyps, bei dem die Funktion das Umgebungswörterbuch als Eingabe akzeptiert und einen Task zurückgibt. Dieser Entwurf hat mehrere Auswirkungen auf Entwickler:

  • Es sind sehr wenige Typabhängigkeiten erforderlich, um OWIN-Komponenten zu schreiben. Dies erhöht die Zugänglichkeit von OWIN für Entwickler erheblich.
  • Der asynchrone Entwurf ermöglicht es, die Abstraktion mit ihrem Umgang mit Computingressourcen effizient zu gestalten, insbesondere bei E/A-intensiven Vorgängen.
  • Da der Anwendungsdelegat eine atomare Ausführungseinheit ist und das Umgebungswörterbuch als Parameter auf dem Delegaten übertragen wird, können OWIN-Komponenten problemlos miteinander verkettet werden, um komplexe HTTP-Verarbeitungspipelines zu erstellen.

Aus Sicht der Implementierung ist OWIN eine Spezifikation (http://owin.org/html/owin.html). Das Ziel besteht nicht darin, das nächste Webframework zu sein, sondern eine Spezifikation für die Interaktion von Webframeworks und Webservern.

Wenn Sie OWIN oder Katana untersucht haben, haben Sie möglicherweise auch das Owin NuGet-Paket bemerkt und Owin.dll. Diese Bibliothek enthält eine einzelne Schnittstelle, [IAppBuilder]/dotnet/api/microsoft.aspnetcore.builder.iapplicationbuilder), die die in Abschnitt 4 der OWIN-Spezifikation beschriebene Startsequenz formalisiert und codifiziert. Die Schnittstelle [IAppBuilder]/dotnet/api/microsoft.aspnetcore.builder.iapplicationbuilder) ist zwar nicht erforderlich, um OWIN-Server zu erstellen, bietet jedoch einen konkreten Bezugspunkt und wird von den Katana-Projektkomponenten verwendet.

Projekt Katana

Während sowohl die OWIN-Spezifikation als auch dieOwin.dll im Besitz der Community und der Community Open Source Bemühungen sind, stellt das Katana-Projekt die Reihe von OWIN-Komponenten dar, die zwar noch Open Source, aber von Microsoft erstellt und veröffentlicht werden. Diese Komponenten umfassen sowohl Infrastrukturkomponenten wie Hosts und Server als auch funktionale Komponenten, z. B. Authentifizierungskomponenten und Bindungen an Frameworks wie SignalR und ASP.NET-Web-API. Das Projekt hat die folgenden drei übergeordneten Ziele:

  • Portabel : Komponenten sollten leicht durch neue Komponenten ersetzt werden können, sobald sie verfügbar werden. Dies umfasst alle Arten von Komponenten, vom Framework über den Server bis hin zum Host. Die Folge dieses Ziels ist, dass Frameworks von Drittanbietern nahtlos auf Microsoft-Servern ausgeführt werden können, während Microsoft-Frameworks möglicherweise auf Servern und Hosts von Drittanbietern ausgeführt werden können.
  • Modular/flexibel: Im Gegensatz zu vielen Frameworks, die eine Vielzahl von Standardmäßig aktivierten Features enthalten, sollten Katana-Projektkomponenten klein und fokussiert sein und dem Anwendungsentwickler die Kontrolle darüber geben, welche Komponenten in ihrer Anwendung verwendet werden sollen.
  • Lightweight/Performant/Scalable : Durch das Aufteilen des herkömmlichen Konzepts eines Frameworks in eine Reihe kleiner, fokussierter Komponenten, die explizit vom Anwendungsentwickler hinzugefügt werden, kann eine resultierende Katana-Anwendung weniger Rechenressourcen verbrauchen und somit mehr Last bewältigen als mit anderen Arten von Servern und Frameworks. Da die Anforderungen der Anwendung mehr Features aus der zugrunde liegenden Infrastruktur erfordern, können diese der OWIN-Pipeline hinzugefügt werden. Dies sollte jedoch eine explizite Entscheidung des Anwendungsentwicklers sein. Darüber hinaus bedeutet die Ersetzbarkeit von Komponenten auf niedrigerer Ebene, dass neue Hochleistungsserver nahtlos eingeführt werden können, um die Leistung von OWIN-Anwendungen zu verbessern, ohne diese Anwendungen zu unterbrechen.

Erste Schritte mit Katana-Komponenten

Bei seiner ersten Einführung war ein Aspekt des Node.js Frameworks, der die Aufmerksamkeit der Menschen sofort auf sich zog, die Einfachheit, mit der man einen Webserver erstellen und ausführen konnte. Wenn Katana-Ziele anhand von Node.jsumrahmt würden, könnte man sie zusammenfassen, indem man sagen würde, dass Katana viele der Vorteile von Node.js (und Frameworks wie es) bringt, ohne den Entwickler zu zwingen, alles, was sie über die Entwicklung ASP.NET Webanwendungen weiß, auszuwerfen. Damit diese Aussage wahr ist, sollten die ersten Schritte mit dem Katana-Projekt ebenso einfach sein, um Node.js.

Erstellen von "Hallo Welt!"

Ein wichtiger Unterschied zwischen JavaScript und .NET-Entwicklung ist das Vorhandensein (oder Fehlen) eines Compilers. Daher ist der Ausgangspunkt für einen einfachen Katana-Server ein Visual Studio-Projekt. Wir können jedoch mit den minimalsten Projekttypen beginnen: die leere ASP.NET Webanwendung.

Screenshot des Menüs

Als Nächstes installieren wir das NuGet-Paket Microsoft.Owin.Host.SystemWeb im Projekt. Dieses Paket stellt einen OWIN-Server bereit, der in der ASP.NET-Anforderungspipeline ausgeführt wird. Es befindet sich im NuGet-Katalog und kann entweder über das Visual Studio-Paket-Manager-Dialogfeld oder die Paket-Manager-Konsole mit dem folgenden Befehl installiert werden:

install-package Microsoft.Owin.Host.SystemWeb

Bei der Installation des Microsoft.Owin.Host.SystemWeb Pakets werden einige zusätzliche Pakete als Abhängigkeiten installiert. Eine dieser Abhängigkeiten ist Microsoft.Owin, eine Bibliothek, die mehrere Hilfstypen und Methoden für die Entwicklung von OWIN-Anwendungen bereitstellt. Wir können diese Typen verwenden, um schnell den folgenden "hello world"-Server zu schreiben.

public class Startup
{
   public void Configuration(IAppBuilder app)
   {
      app.Run(context =>
      {
         context.Response.ContentType = "text/plain";
         return context.Response.WriteAsync("Hello World!");
      });
   }
}

Dieser sehr einfache Webserver kann jetzt mit dem F5-Befehl von Visual Studio ausgeführt werden und bietet vollständige Unterstützung für das Debuggen.

Wechseln von Hosts

Standardmäßig wird das vorherige Beispiel "hello world" in der ASP.NET-Anforderungspipeline ausgeführt, die System.Web im Kontext von IIS verwendet. Dies kann allein schon einen enormen Mehrwert bieten, da es uns ermöglicht, von der Flexibilität und Zusammensetzbarkeit einer OWIN-Pipeline mit den Verwaltungsfunktionen und der allgemeinen Reife von IIS zu profitieren. Es kann jedoch Vorkommen geben, in denen die von IIS bereitgestellten Vorteile nicht erforderlich sind und der Wunsch nach einem kleineren, schlankeren Host besteht. Was ist also erforderlich, um unseren einfachen Webserver außerhalb von IIS und System.Web auszuführen?

Um das Portabilitätsziel zu veranschaulichen, müssen Sie für den Wechsel von einem Webserverhost zu einem Befehlszeilenhost einfach die neuen Server- und Hostabhängigkeiten zum Ausgabeordner des Projekts hinzufügen und dann den Host starten. In diesem Beispiel hosten wir unseren Webserver in einem Katana-Host namens OwinHost.exe und verwenden den HttpListener-basierten Katana-Server. Ähnlich wie bei den anderen Katana-Komponenten werden diese mithilfe des folgenden Befehls von NuGet abgerufen:

install-package OwinHost

Über die Befehlszeile können wir dann zum Projektstammordner navigieren und einfach den OwinHost.exe ausführen (der im Ordner tools des jeweiligen NuGet-Pakets installiert wurde). Standardmäßig OwinHost.exe ist für die Suche nach dem HttpListener-basierten Server konfiguriert, sodass keine zusätzliche Konfiguration erforderlich ist. Wenn Sie in einem Webbrowser navigieren, um die Anwendung anzuzeigen http://localhost:5000/ , die jetzt über die Konsole ausgeführt wird.

Screenshot des Promt-Befehls für Entwickler und des Browserfensters mit einem Vergleich der befehle, die in der Befehlszeile eingegeben wurden, und wie das Projekt

Katana-Architektur

Die Katana-Komponentenarchitektur unterteilt eine Anwendung in vier logische Ebenen, wie unten dargestellt: Host, Server, Middleware und Anwendung. Die Komponentenarchitektur ist so umgestaltet, dass Implementierungen dieser Ebenen in vielen Fällen problemlos ersetzt werden können, ohne dass eine erneute Kompilierung der Anwendung erforderlich ist.

Diagramm der Architekturebenen mit vier Balken, die die logischen Ebenen darstellen, in die die Architektur der Anwendung unterteilt ist.

Host

Der Host ist für Folgendes verantwortlich:

  • Verwalten des zugrunde liegenden Prozesses.

  • Orchestrieren des Workflows, der zur Auswahl eines Servers und zum Erstellen einer OWIN-Pipeline führt, über die Anforderungen verarbeitet werden.

    Derzeit gibt es drei primäre Hostingoptionen für Katana-basierte Anwendungen:

IIS/ASP.NET: Mit den Standardtypen HttpModule und HttpHandler können OWIN-Pipelines in IIS als Teil eines ASP.NET-Anforderungsflows ausgeführt werden. ASP.NET Hostingunterstützung wird durch Installieren des NuGet-Pakets Microsoft.AspNet.Host.SystemWeb in einem Webanwendungsprojekt aktiviert. Da IIS außerdem sowohl als Host als auch als Server fungiert, wird die OWIN-Server-/Host-Unterscheidung in diesem NuGet-Paket zusammengeflechtet, was bedeutet, dass ein Entwickler bei Verwendung des SystemWeb-Hosts keine alternative Serverimplementierung ersetzen kann.

Benutzerdefinierter Host: Die Katana-Komponentensammlung bietet Entwicklern die Möglichkeit, Anwendungen in ihrem eigenen benutzerdefinierten Prozess zu hosten, unabhängig davon, ob es sich um eine Konsolenanwendung, einen Windows-Dienst usw. handelt. Diese Funktion ähnelt der Selbsthostfunktion, die von der Web-API bereitgestellt wird. Das folgende Beispiel zeigt einen benutzerdefinierten Host von Web-API-Code:

static void Main()
{
    var baseAddress = new Uri("http://localhost:5000");

    var config = new HttpSelfHostConfiguration(baseAddress);
    config.Routes.MapHttpRoute("default", "{controller}");
       
    using (var svr = new HttpSelfHostServer(config))
    {
        svr.OpenAsync().Wait();
        Console.WriteLine("Press Enter to quit.");
        Console.ReadLine();
    }
}

Die Selbsthosteinrichtung für eine Katana-Anwendung ist ähnlich:

static void Main(string[] args)
{
    const string baseUrl = "http://localhost:5000/";

    using (WebApplication.Start<Startup>(new StartOptions { Url = baseUrl })) 
    {
        Console.WriteLine("Press Enter to quit.");
        Console.ReadKey();
    }
}

Ein wichtiger Unterschied zwischen den Web-API- und Katana-Selbsthostbeispielen besteht darin, dass der Web-API-Konfigurationscode im Katana-Selbsthostbeispiel fehlt. Um sowohl Portabilität als auch Zusammensetzbarkeit zu ermöglichen, trennt Katana den Code, der den Server startet, von dem Code, der die Anforderungsverarbeitungspipeline konfiguriert. Der Code, der die Web-API konfiguriert, ist dann in der Klasse Startup enthalten, die zusätzlich als Typparameter in WebApplication.Start angegeben wird.

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var config = new HttpConfiguration();
        config.Routes.MapHttpRoute("default", "{controller}");
        app.UseWebApi(config);
    }
}

Die Startklasse wird später im Artikel ausführlicher erläutert. Der Code, der zum Starten eines Katana-Selbsthostprozesses erforderlich ist, ähnelt jedoch auffallend dem Code, den Sie heute möglicherweise in ASP.NET-Web-API Selbsthostanwendungen verwenden.

OwinHost.exe: Während einige einen benutzerdefinierten Prozess zum Ausführen von Katana-Webanwendungen schreiben möchten, möchten viele einfach eine vorgefertigte ausführbare Datei starten, die einen Server starten und ihre Anwendung ausführen kann. Für dieses Szenario enthält OwinHost.exedie Katana-Komponentensammlung . Wenn sie im Stammverzeichnis eines Projekts ausgeführt wird, startet diese ausführbare Datei einen Server (standardmäßig wird der HttpListener-Server verwendet) und verwendet Konventionen, um die Startklasse des Benutzers zu suchen und auszuführen. Für eine präzisere Steuerung bietet die ausführbare Datei eine Reihe zusätzlicher Befehlszeilenparameter.

Screenshot der Developer-Eingabeaufforderung mit einem Beispiel für den Code der Eingabeaufforderung beim Ausführen der Anwendung auf dem Server.

Server

Während der Host für das Starten und Verwalten des Prozesses verantwortlich ist, in dem die Anwendung ausgeführt wird, besteht die Verantwortung des Servers darin, einen Netzwerksocket zu öffnen, auf Anforderungen zu lauschen und diese über die pipeline der vom Benutzer angegebenen OWIN-Komponenten zu senden (wie Sie möglicherweise bereits bemerkt haben, wird diese Pipeline in der Startup-Klasse des Anwendungsentwicklers angegeben). Derzeit umfasst das Katana-Projekt zwei Serverimplementierungen:

  • Microsoft.Owin.Host.SystemWeb: Wie bereits erwähnt, fungiert IIS zusammen mit der ASP.NET-Pipeline sowohl als Host als auch als Server. Daher verwaltet IIS bei der Auswahl dieser Hostingoption sowohl Probleme auf Hostebene wie die Prozessaktivierung und lauscht auf HTTP-Anforderungen. Bei ASP.NET Webanwendungen werden dann die Anforderungen an die ASP.NET-Pipeline gesendet. Der Katana SystemWeb-Host registriert eine ASP.NET HttpModule und HttpHandler, um Anforderungen abzufangen, während sie die HTTP-Pipeline durchlaufen und sie über die vom Benutzer angegebene OWIN-Pipeline senden.
  • Microsoft.Owin.Host.HttpListener: Wie der Name schon sagt, verwendet dieser Katana-Server die HttpListener-Klasse des .NET Framework, um einen Socket zu öffnen und Anforderungen an eine vom Entwickler angegebene OWIN-Pipeline zu senden. Dies ist derzeit die Standard-Serverauswahl sowohl für die Katana-Selbsthost-API als auch für OwinHost.exe.

Middleware/Framework

Wie bereits erwähnt, ist der Server, wenn er eine Anforderung von einem Client akzeptiert, dafür verantwortlich, diese über eine Pipeline von OWIN-Komponenten zu übergeben, die vom Startcode des Entwicklers angegeben werden. Diese Pipelinekomponenten werden als Middleware bezeichnet.
Auf einer sehr einfachen Ebene muss eine OWIN-Middlewarekomponente einfach den OWIN-Anwendungsdelegat implementieren, damit er aufgerufen werden kann.

Func<IDictionary<string, object>, Task>

Um die Entwicklung und Zusammensetzung von Middlewarekomponenten zu vereinfachen, unterstützt Katana jedoch eine Reihe von Konventionen und Hilfstypen für Middlewarekomponenten. Die gebräuchlichste davon ist die OwinMiddleware -Klasse. Eine benutzerdefinierte Middlewarekomponente, die mit dieser Klasse erstellt wurde, sieht in etwa wie folgt aus:

public class LoggerMiddleware : OwinMiddleware
{
    private readonly ILog _logger;
 
    public LoggerMiddleware(OwinMiddleware next, ILog logger) : base(next)
    {
        _logger = logger;
    }
 
    public override async Task Invoke(IOwinContext context)
    {
        _logger.LogInfo("Middleware begin");
        await this.Next.Invoke(context);
        _logger.LogInfo("Middleware end");
    }
}

Diese Klasse wird von OwinMiddlewareabgeleitet, implementiert einen Konstruktor, der eine instance der nächsten Middleware in der Pipeline als eines ihrer Argumente akzeptiert und dann an den Basiskonstruktor übergibt. Zusätzliche Argumente, die zum Konfigurieren der Middleware verwendet werden, werden ebenfalls als Konstruktorparameter nach dem nächsten Middlewareparameter deklariert.

Zur Laufzeit wird die Middleware über die überschriebene Invoke Methode ausgeführt. Diese Methode akzeptiert ein einzelnes Argument vom Typ OwinContext. Dieses Kontextobjekt wird vom Microsoft.Owin zuvor beschriebenen NuGet-Paket bereitgestellt und bietet stark typisierten Zugriff auf die Anforderung, die Antwort und das Umgebungswörterbuch sowie einige zusätzliche Hilfstypen.

Die Middlewareklasse kann der OWIN-Pipeline im Anwendungsstartcode wie folgt hinzugefügt werden:

public class Startup
{
   public void Configuration(IAppBuilder app)
   {
      app.Use<LoggerMiddleware>(new TraceLogger());

   }
}

Da die Katana-Infrastruktur einfach eine Pipeline von OWIN-Middlewarekomponenten aufbaut und die Komponenten einfach den Anwendungsdelegat unterstützen müssen, um an der Pipeline teilzunehmen, können Middlewarekomponenten von einfachen Protokollierungen bis hin zu ganzen Frameworks wie ASP.NET, Web-API oder SignalR reichen. Wenn Sie z. B. ASP.NET-Web-API zur vorherigen OWIN-Pipeline hinzufügen, müssen Sie den folgenden Startcode hinzufügen:

public class Startup
{
   public void Configuration(IAppBuilder app)
   {
      app.Use<LoggerMiddleware>(new TraceLogger());

      var config = new HttpConfiguration();
      // configure Web API 
      app.UseWebApi(config);

      // additional middleware registrations            
   }
}

Die Katana-Infrastruktur erstellt die Pipeline von Middlewarekomponenten basierend auf der Reihenfolge, in der sie dem IAppBuilder-Objekt in der Configuration-Methode hinzugefügt wurden. In unserem Beispiel kann LoggerMiddleware dann alle Anforderungen verarbeiten, die durch die Pipeline fließen, unabhängig davon, wie diese Anforderungen letztendlich behandelt werden. Dies ermöglicht leistungsstarke Szenarien, in denen eine Middlewarekomponente (z. B. eine Authentifizierungskomponente) Anforderungen für eine Pipeline verarbeiten kann, die mehrere Komponenten und Frameworks enthält (z. B. ASP.NET-Web-API, SignalR und einen statischen Dateiserver).

Anwendungen

Wie in den vorherigen Beispielen veranschaulicht, sollten OWIN und das Katana-Projekt nicht als neues Anwendungsprogrammierungsmodell, sondern als Abstraktion zum Entkoppeln von Anwendungsprogrammierungsmodellen und -frameworks von Server- und Hostinginfrastruktur betrachtet werden. Beim Erstellen von Web-API-Anwendungen verwendet das Entwicklerframework beispielsweise weiterhin das ASP.NET-Web-API Framework, unabhängig davon, ob die Anwendung in einer OWIN-Pipeline mit Komponenten aus dem Katana-Projekt ausgeführt wird. Der einzige Ort, an dem OWIN-bezogener Code für den Anwendungsentwickler sichtbar ist, ist der Anwendungsstartcode, an dem der Entwickler die OWIN-Pipeline erstellt. Im Startcode registriert der Entwickler eine Reihe von UseXx-Anweisungen, in der Regel eine für jede Middlewarekomponente, die eingehende Anforderungen verarbeitet. Diese Erfahrung hat die gleiche Auswirkung wie das Registrieren von HTTP-Modulen in der aktuellen System.Web-Welt. In der Regel wird am Ende der Pipeline eine größere Frameworkmiddleware registriert, z. B. ASP.NET-Web-API oder SignalR. Übergreifende Middlewarekomponenten, z. B. für die Authentifizierung oder Zwischenspeicherung, werden in der Regel zu Beginn der Pipeline registriert, sodass sie Anforderungen für alle später in der Pipeline registrierten Frameworks und Komponenten verarbeiten. Durch diese Trennung der Middlewarekomponenten untereinander und von den zugrunde liegenden Infrastrukturkomponenten können sich die Komponenten mit unterschiedlichen Geschwindigkeiten weiterentwickeln und gleichzeitig sicherstellen, dass das Gesamtsystem stabil bleibt.

Komponenten – NuGet-Pakete

Wie viele aktuelle Bibliotheken und Frameworks werden die Katana-Projektkomponenten als Eine Reihe von NuGet-Paketen bereitgestellt. Für die kommende Version 2.0 sieht das Katana-Paket Abhängigkeitsdiagramm wie folgt aus. (Klicken Sie zum Vergrößern auf das Bild.)

Diagramm der Hierarchie

Fast jedes Paket im Katana-Projekt hängt direkt oder indirekt vom Owin-Paket ab. Sie erinnern sich vielleicht daran, dass dies das Paket ist, das die IAppBuilder-Schnittstelle enthält, die eine konkrete Implementierung der in Abschnitt 4 der OWIN-Spezifikation beschriebenen Anwendungsstartsequenz bietet. Darüber hinaus hängen viele der Pakete von Microsoft.Owin ab, das eine Reihe von Hilfstypen für die Arbeit mit HTTP-Anforderungen und -Antworten bereitstellt. Der Rest des Pakets kann entweder als Hostinfrastrukturpakete (Server oder Hosts) oder Als Middleware klassifiziert werden. Pakete und Abhängigkeiten, die sich außerhalb des Katana-Projekts befinden, werden orange angezeigt.

Die Hostinginfrastruktur für Katana 2.0 umfasst sowohl systemWeb- als auch HttpListener-basierte Server, das OwinHost-Paket zum Ausführen von OWIN-Anwendungen mit OwinHost.exe und das Microsoft.Owin.Hosting-Paket für selbsthostende OWIN-Anwendungen in einem benutzerdefinierten Host (z. B. Konsolenanwendung, Windows-Dienst usw.).

Für Katana 2.0 konzentrieren sich die Middlewarekomponenten in erster Linie auf die Bereitstellung unterschiedlicher Authentifizierungsmethoden. Es wird eine zusätzliche Middlewarekomponente für Diagnose bereitgestellt, die unterstützung für eine Start- und Fehlerseite ermöglicht. Wenn OWIN zur de-facto-Hosting-Abstraktion heranwächst, wird auch das Ökosystem der Middlewarekomponenten, sowohl von Microsoft als auch von Drittanbietern, an Zahl wachsen.

Zusammenfassung

Von Anfang an bestand das Ziel des Katana-Projekts nicht darin, ein weiteres Webframework zu erstellen und die Entwickler dadurch zu zwingen, ein weiteres Webframework zu erlernen. Vielmehr bestand das Ziel darin, eine Abstraktion zu erstellen, um .NET-Webanwendungsentwicklern mehr Wahlmöglichkeiten als bisher möglich zu geben. Durch Aufteilen der logischen Schichten eines typischen Webanwendungsstapels in einen Satz ersetzbarer Komponenten ermöglicht das Katana-Projekt es Komponenten im gesamten Stapel, sich mit der für diese Komponenten sinnvollen Geschwindigkeit zu verbessern. Durch die Erstellung aller Komponenten rund um die einfache OWIN-Abstraktion ermöglicht Katana, dass Frameworks und die darauf basierenden Anwendungen auf verschiedenen Servern und Hosts portierbar sind. Indem der Entwickler die Kontrolle über den Stapel übernimmt, stellt Katana sicher, dass der Entwickler die ultimative Wahl trifft, wie leicht oder wie funktionsreich sein Webstapel sein soll.

Weitere Informationen zu Katana

Danksagung