Open Web Interface for .NET (OWIN) mit ASP.NET Core

Von Steve Smith und Rick Anderson

ASP.NET Core:

  • unterstützt Open Web Interface for .NET (OWIN)
  • enthält mit .NET Core kompatiblen Ersatz für Microsoft.Owin.*-Bibliotheken (Katana)

Mit OWIN können Web-Apps von Webservern entkoppelt werden. OWIN legt eine Standardmöglichkeit des Einsatzes von Middleware in einer Pipeline zum Verarbeiten von Anforderungen und den entsprechenden Antworten fest. ASP.NET Core-Anwendungen und -Middleware können mit auf OWIN basierten Anwendungen, Servern und OWIN basierter Middleware zusammenarbeiten.

OWIN bietet eine Entkopplungsebene, die das gemeinsame Verwenden zweier Frameworks mit unterschiedlichen Objektmodellen zulässt. Das Microsoft.AspNetCore.Owin-Paket bietet zwei Adapterimplementierungen:

  • ASP.NET Core auf OWIN
  • OWIN auf ASP.NET Core

So kann ASP.NET Core auf einem mit OWIN kompatiblen Server bzw. Host gehostet werden. Alternativ können andere mit OWIN kompatible Komponenten über ASP.NET Core ausgeführt werden.

Hinweis

Das Verwenden dieser Adapter führt zu Leistungseinbußen. Apps, die nur ASP.NET Core-Komponenten verwenden, sollten keine Microsoft.AspNetCore.Owin-Pakete oder Adapter verwenden.

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)

Ausführen von OWIN-Middleware in der ASP.NET Core-Pipeline

Die OWIN-Unterstützung von ASP.NET Core wird im Rahmen des Microsoft.AspNetCore.Owin-Pakets bereitgestellt. Sie können OWIN-Unterstützung in Ihrem Projekt ermöglichen, indem Sie dieses Paket installieren.

OWIN-Middleware stimmt mit der OWIN-Spezifikation überein, die eine Func<IDictionary<string, object>, Task>-Schnittstelle und das Festlegen spezifischer Schlüssel erfordert (wie z.B. owin.ResponseBody). Die folgende einfache OWIN-Middleware zeigt „Hello World“ (Hallo Welt) an:

public Task OwinHello(IDictionary<string, object> environment)
{
    string responseText = "Hello World via OWIN";
    byte[] responseBytes = Encoding.UTF8.GetBytes(responseText);

    // OWIN Environment Keys: https://owin.org/spec/spec/owin-1.0.0.html
    var responseStream = (Stream)environment["owin.ResponseBody"];
    var responseHeaders = (IDictionary<string, string[]>)environment["owin.ResponseHeaders"];

    responseHeaders["Content-Length"] = new string[] { responseBytes.Length.ToString(CultureInfo.InvariantCulture) };
    responseHeaders["Content-Type"] = new string[] { "text/plain" };

    return responseStream.WriteAsync(responseBytes, 0, responseBytes.Length);
}

Die Beispielsignatur gibt ein Task-Objekt zurück und akzeptiert ein IDictionary<string, object>, wie OWIN es erfordert.

Der folgende Code veranschaulicht, wie Sie die OwinHello-Middleware (siehe oben) der ASP.NET Core-Pipeline mit der UseOwin-Erweiterungsmethode hinzufügen.

public void Configure(IApplicationBuilder app)
{
    app.UseOwin(pipeline =>
    {
        pipeline(next => OwinHello);
    });
}

Sie können andere Aktionen konfigurieren, die in der OWIN-Pipeline durchgeführt werden sollen.

Hinweis

Antwortheader sollten nur vor dem ersten Schreiben in den Antwortstream modifiziert werden.

Hinweis

Mehrere Aufrufe von UseOwin werden aus Leistungsgründen nicht empfohlen. OWIN-Komponenten funktionieren am besten, wenn sie gruppiert werden.

app.UseOwin(pipeline =>
{
    pipeline(next =>
    {
        return async environment =>
        {
            // Do something before.
            await next(environment);
            // Do something after.
        };
    });
});

Ausführen von ASP.NET Core auf einem auf OWIN basierten Server und Nutzen der WebSockets-Unterstützung

Der Zugriff auf Features wie WebSockets ist ein weiteres Beispiel dafür, wie ASP.NET Core Features von auf OWIN basierten Servern nutzen kann. Der .NET OWIN-Webserver, der im vorherigen Beispiel verwendet wurde, verfügt über integrierte Unterstützung für WebSockets. Dies kann von einer ASP.NET Core-Anwendung genutzt werden. Das unten stehende Beispiel zeigt eine einfache Web-App, die WebSockets unterstützt und alles zurück gibt, was über WebSockets an den Server gesendet wurde.

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.Use(async (context, next) =>
        {
            if (context.WebSockets.IsWebSocketRequest)
            {
                WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
                await EchoWebSocket(webSocket);
            }
            else
            {
                await next();
            }
        });

        app.Run(context =>
        {
            return context.Response.WriteAsync("Hello World");
        });
    }

    private async Task EchoWebSocket(WebSocket webSocket)
    {
        byte[] buffer = new byte[1024];
        WebSocketReceiveResult received = await webSocket.ReceiveAsync(
            new ArraySegment<byte>(buffer), CancellationToken.None);

        while (!webSocket.CloseStatus.HasValue)
        {
            // Echo anything we receive
            await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, received.Count), 
                received.MessageType, received.EndOfMessage, CancellationToken.None);

            received = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), 
                CancellationToken.None);
        }

        await webSocket.CloseAsync(webSocket.CloseStatus.Value, 
            webSocket.CloseStatusDescription, CancellationToken.None);
    }
}

OWIN-Umgebung

Sie können mit HttpContext eine OWIN-Umgebung erstellen.


   var environment = new OwinEnvironment(HttpContext);
   var features = new OwinFeatureCollection(environment);

OWIN-Schlüssel

OWIN ist von einem IDictionary<string,object>-Objekt abhängig, um Informationen innerhalb eines Austauschs einer HTTP-Anforderung und einer Antwort weiterzugeben. ASP.NET Core implementiert die unten aufgelisteten Schlüssel. Weitere Informationen finden Sie in den Hauptspezifikationen und Erweiterungen und in den OWIN Key Guidelines and Common Keys (Wichtigste Richtlinien und gängige Schlüsse von OWIN).

Anforderungsdaten (OWIN v1.0.0)

Key Wert (Typ) Beschreibung
owin.RequestScheme String
owin.RequestMethod String
owin.RequestPathBase String
owin.RequestPath String
owin.RequestQueryString String
owin.RequestProtocol String
owin.RequestHeaders IDictionary<string,string[]>
owin.RequestBody Stream

Anforderungsdaten (OWIN v1.1.0)

Key Wert (Typ) Beschreibung
owin.RequestId String Optional

Antwortdaten (OWIN v1.0.0)

Key Wert (Typ) Beschreibung
owin.ResponseStatusCode int Optional
owin.ResponseReasonPhrase String Optional
owin.ResponseHeaders IDictionary<string,string[]>
owin.ResponseBody Stream

Andere Daten (OWIN v1.0.0)

Key Wert (Typ) Beschreibung
owin.CallCancelled CancellationToken
owin.Version String

Gängige Schlüssel

Key Wert (Typ) Beschreibung
ssl.ClientCertificate X509Certificate
ssl.LoadClientCertAsync Func<Task>
server.RemoteIpAddress String
server.RemotePort String
server.LocalIpAddress String
server.LocalPort String
server.OnSendingHeaders Action<Action<object>,object>

SendFiles v0.3.0

Key Wert (Typ) Beschreibung
sendfile.SendAsync Siehe Delegatsignatur Pro Anforderung

Opaque v0.3.0

Key Wert (Typ) Beschreibung
opaque.Version String
opaque.Upgrade OpaqueUpgrade Siehe Delegatsignatur
opaque.Stream Stream
opaque.CallCancelled CancellationToken

WebSocket v0.3.0

Key Wert (Typ) Beschreibung
websocket.Version String
websocket.Accept WebSocketAccept Siehe Delegatsignatur
websocket.AcceptAlt n/v
websocket.SubProtocol String Siehe RFC6455 Abschnitt 4.2.2, Schritt 5.5
websocket.SendAsync WebSocketSendAsync Siehe Delegatsignatur
websocket.ReceiveAsync WebSocketReceiveAsync Siehe Delegatsignatur
websocket.CloseAsync WebSocketCloseAsync Siehe Delegatsignatur
websocket.CallCancelled CancellationToken
websocket.ClientCloseStatus int Optional
websocket.ClientCloseDescription String Optional

Zusätzliche Ressourcen