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

Von Steve Smith und Rick AndersonBy Steve Smith and Rick Anderson

ASP.NET Core unterstützt Open Web Interface for .NET (OWIN).ASP.NET Core supports the Open Web Interface for .NET (OWIN). Mit OWIN können Web-Apps von Webservern entkoppelt werden.OWIN allows web apps to be decoupled from web servers. OWIN legt eine Standardmöglichkeit des Einsatzes von Middleware in einer Pipeline zum Verarbeiten von Anforderungen und den entsprechenden Antworten fest.It defines a standard way for middleware to be used in a pipeline to handle requests and associated responses. ASP.NET Core-Anwendungen und -Middleware können mit auf OWIN basierten Anwendungen, Servern und OWIN basierter Middleware zusammenarbeiten.ASP.NET Core applications and middleware can interoperate with OWIN-based applications, servers, and middleware.

OWIN bietet eine Entkopplungsebene, die das gemeinsame Verwenden zweier Frameworks mit unterschiedlichen Objektmodellen zulässt.OWIN provides a decoupling layer that allows two frameworks with disparate object models to be used together. Das Microsoft.AspNetCore.Owin-Paket bietet zwei Adapterimplementierungen:The Microsoft.AspNetCore.Owin package provides two adapter implementations:

  • ASP.NET Core auf OWINASP.NET Core to OWIN
  • OWIN auf ASP.NET CoreOWIN to 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.This allows ASP.NET Core to be hosted on top of an OWIN compatible server/host or for other OWIN compatible components to be run on top of ASP.NET Core.

Hinweis

Das Verwenden dieser Adapter führt zu Leistungseinbußen.Using these adapters comes with a performance cost. Apps, die nur ASP.NET Core-Komponenten verwenden, sollten keine Microsoft.AspNetCore.Owin-Pakete oder Adapter verwenden.Apps using only ASP.NET Core components shouldn't use the Microsoft.AspNetCore.Owin package or adapters.

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)View or download sample code (how to download)

Ausführen von OWIN-Middleware in der ASP.NET Core-PipelineRunning OWIN middleware in the ASP.NET Core pipeline

Die OWIN-Unterstützung von ASP.NET Core wird im Rahmen des Microsoft.AspNetCore.Owin-Pakets bereitgestellt.ASP.NET Core's OWIN support is deployed as part of the Microsoft.AspNetCore.Owin package. Sie können OWIN-Unterstützung in Ihrem Projekt ermöglichen, indem Sie dieses Paket installieren.You can import OWIN support into your project by installing this package.

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).OWIN middleware conforms to the OWIN specification, which requires a Func<IDictionary<string, object>, Task> interface, and specific keys be set (such as owin.ResponseBody). Die folgende einfache OWIN-Middleware zeigt „Hello World“ (Hallo Welt) an:The following simple OWIN middleware displays "Hello World":

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.The sample signature returns a Task and accepts an IDictionary<string, object> as required by OWIN.

Der folgende Code veranschaulicht, wie Sie die OwinHello-Middleware (siehe oben) der ASP.NET Core-Pipeline mit der UseOwin-Erweiterungsmethode hinzufügen.The following code shows how to add the OwinHello middleware (shown above) to the ASP.NET Core pipeline with the UseOwin extension method.

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.You can configure other actions to take place within the OWIN pipeline.

Hinweis

Antwortheader sollten nur vor dem ersten Schreiben in den Antwortstream modifiziert werden.Response headers should only be modified prior to the first write to the response stream.

Hinweis

Mehrere Aufrufe von UseOwin werden aus Leistungsgründen nicht empfohlen.Multiple calls to UseOwin is discouraged for performance reasons. OWIN-Komponenten funktionieren am besten, wenn sie gruppiert werden.OWIN components will operate best if grouped together.

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

ASP.NET Core-Hosting auf einem auf OWIN basierten ServerUsing ASP.NET Core Hosting on an OWIN-based server

Auf OWIN basierte Server können ASP.NET Core-Anwendungen hosten.OWIN-based servers can host ASP.NET Core apps. Ein derartiger Server ist Nowin, ein Webserver von .NET OWIN.One such server is Nowin, a .NET OWIN web server. Das Beispiel für diesen Artikel enthält ein Projekt, das auf Nowin verweist und ihn verwendet, um einen IServer zu erstellen, der ASP.NET Core eigenständig hosten kann.In the sample for this article, I've included a project that references Nowin and uses it to create an IServer capable of self-hosting ASP.NET Core.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;

namespace NowinSample
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var host = new WebHostBuilder()
                .UseNowin()
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseIISIntegration()
                .UseStartup<Startup>()
                .Build();

            host.Run();
        }
    }
}

IServer ist eine Schnittstelle, die eine Features-Eigenschaft und eine Start-Methode erfordert.IServer is an interface that requires a Features property and a Start method.

Start ist für die Konfiguration und das Starten des Server zuständig. In diesem Fall erfolgt dies durch eine Folge von Aufrufen von Fluent-APIs, die Adressen festgelegt haben, die von IServerAddressesFeature analysiert wurden.Start is responsible for configuring and starting the server, which in this case is done through a series of fluent API calls that set addresses parsed from the IServerAddressesFeature. Beachten Sie, dass die fließende Konfiguration der _builder-Variablen angibt, das Anforderungen vom appFunc-Objekt verarbeitet werden, das bereits in der Methode festgelegt wurde.Note that the fluent configuration of the _builder variable specifies that requests will be handled by the appFunc defined earlier in the method. Dieses Func-Objekt wird bei jeder Anforderung aufgerufen, um eingehende Anforderungen zu verarbeiten.This Func is called on each request to process incoming requests.

Außerdem fügen wir eine IWebHostBuilder-Erweiterung hinzu, um den Nowin-Server leicht hinzufügen und konfigurieren zu können.We'll also add an IWebHostBuilder extension to make it easy to add and configure the Nowin server.

using System;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.Extensions.DependencyInjection;
using Nowin;
using NowinSample;

namespace Microsoft.AspNetCore.Hosting
{
    public static class NowinWebHostBuilderExtensions
    {
        public static IWebHostBuilder UseNowin(this IWebHostBuilder builder)
        {
            return builder.ConfigureServices(services =>
            {
                services.AddSingleton<IServer, NowinServer>();
            });
        }

        public static IWebHostBuilder UseNowin(this IWebHostBuilder builder, Action<ServerBuilder> configure)
        {
            builder.ConfigureServices(services =>
            {
                services.Configure(configure);
            });
            return builder.UseNowin();
        }
    }
}

Rufen Sie anschließend die Erweiterung in Program.cs auf, um eine ASP.NET Core-App auszuführen, die diesen benutzerdefinierten Server verwendet:With this in place, invoke the extension in Program.cs to run an ASP.NET Core app using this custom server:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;

namespace NowinSample
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var host = new WebHostBuilder()
                .UseNowin()
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseIISIntegration()
                .UseStartup<Startup>()
                .Build();

            host.Run();
        }
    }
}

Weitere Informationen zu ASP.NET Core-Servern.Learn more about ASP.NET Core Servers.

Ausführen von ASP.NET Core auf einem auf OWIN basierten Server und Nutzen der WebSockets-UnterstützungRun ASP.NET Core on an OWIN-based server and use its WebSockets support

Der Zugriff auf Features wie WebSockets ist ein weiteres Beispiel dafür, wie ASP.NET Core Features von auf OWIN basierten Servern nutzen kann.Another example of how OWIN-based servers' features can be leveraged by ASP.NET Core is access to features like WebSockets. 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.The .NET OWIN web server used in the previous example has support for Web Sockets built in, which can be leveraged by an ASP.NET Core application. 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.The example below shows a simple web app that supports Web Sockets and echoes back everything sent to the server through WebSockets.

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

Dieses Beispiel wird mit dem gleichen NowinServer wie vorher konfiguriert. Der einzige Unterschied besteht in der Konfiguration der Anwendung in deren Configure-Methode.This sample is configured using the same NowinServer as the previous one - the only difference is in how the application is configured in its Configure method. Ein Text mit einem einfachen WebSocket-Client veranschaulicht die Anwendung:A test using a simple websocket client demonstrates the application:

WebSocket-Testclient

OWIN-UmgebungOWIN environment

Sie können mit HttpContext eine OWIN-Umgebung erstellen.You can construct an OWIN environment using the HttpContext.


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

OWIN-SchlüsselOWIN keys

OWIN ist von einem IDictionary<string,object>-Objekt abhängig, um Informationen innerhalb eines Austauschs einer HTTP-Anforderung und einer Antwort weiterzugeben.OWIN depends on an IDictionary<string,object> object to communicate information throughout an HTTP Request/Response exchange. ASP.NET Core implementiert die unten aufgelisteten Schlüssel.ASP.NET Core implements the keys listed below. 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).See the primary specification, extensions, and OWIN Key Guidelines and Common Keys.

Anforderungsdaten (OWIN v1.0.0)Request data (OWIN v1.0.0)

KeyKey Wert (Typ)Value (type) BeschreibungDescription
owin.RequestSchemeowin.RequestScheme String
owin.RequestMethodowin.RequestMethod String
owin.RequestPathBaseowin.RequestPathBase String
owin.RequestPathowin.RequestPath String
owin.RequestQueryStringowin.RequestQueryString String
owin.RequestProtocolowin.RequestProtocol String
owin.RequestHeadersowin.RequestHeaders IDictionary<string,string[]>
owin.RequestBodyowin.RequestBody Stream

Anforderungsdaten (OWIN v1.1.0)Request data (OWIN v1.1.0)

KeyKey Wert (Typ)Value (type) BeschreibungDescription
owin.RequestIdowin.RequestId String OptionalOptional

Antwortdaten (OWIN v1.0.0)Response data (OWIN v1.0.0)

KeyKey Wert (Typ)Value (type) BeschreibungDescription
owin.ResponseStatusCodeowin.ResponseStatusCode int OptionalOptional
owin.ResponseReasonPhraseowin.ResponseReasonPhrase String OptionalOptional
owin.ResponseHeadersowin.ResponseHeaders IDictionary<string,string[]>
owin.ResponseBodyowin.ResponseBody Stream

Andere Daten (OWIN v1.0.0)Other data (OWIN v1.0.0)

KeyKey Wert (Typ)Value (type) BeschreibungDescription
owin.CallCancelledowin.CallCancelled CancellationToken
owin.Versionowin.Version String

Gängige SchlüsselCommon keys

KeyKey Wert (Typ)Value (type) BeschreibungDescription
ssl.ClientCertificatessl.ClientCertificate X509Certificate
ssl.LoadClientCertAsyncssl.LoadClientCertAsync Func<Task>
server.RemoteIpAddressserver.RemoteIpAddress String
server.RemotePortserver.RemotePort String
server.LocalIpAddressserver.LocalIpAddress String
server.LocalPortserver.LocalPort String
server.IsLocalserver.IsLocal bool
server.OnSendingHeadersserver.OnSendingHeaders Action<Action<object>,object>

SendFiles v0.3.0SendFiles v0.3.0

KeyKey Wert (Typ)Value (type) BeschreibungDescription
sendfile.SendAsyncsendfile.SendAsync Siehe DelegatsignaturSee delegate signature Pro AnforderungPer Request

Opaque v0.3.0Opaque v0.3.0

KeyKey Wert (Typ)Value (type) BeschreibungDescription
opaque.Versionopaque.Version String
opaque.Upgradeopaque.Upgrade OpaqueUpgrade Siehe DelegatsignaturSee delegate signature
opaque.Streamopaque.Stream Stream
opaque.CallCancelledopaque.CallCancelled CancellationToken

WebSocket v0.3.0WebSocket v0.3.0

KeyKey Wert (Typ)Value (type) BeschreibungDescription
websocket.Versionwebsocket.Version String
websocket.Acceptwebsocket.Accept WebSocketAccept Siehe DelegatsignaturSee delegate signature
websocket.AcceptAltwebsocket.AcceptAlt n/vNon-spec
websocket.SubProtocolwebsocket.SubProtocol String Siehe RFC6455 Abschnitt 4.2.2, Schritt 5.5See RFC6455 Section 4.2.2 Step 5.5
websocket.SendAsyncwebsocket.SendAsync WebSocketSendAsync Siehe DelegatsignaturSee delegate signature
websocket.ReceiveAsyncwebsocket.ReceiveAsync WebSocketReceiveAsync Siehe DelegatsignaturSee delegate signature
websocket.CloseAsyncwebsocket.CloseAsync WebSocketCloseAsync Siehe DelegatsignaturSee delegate signature
websocket.CallCancelledwebsocket.CallCancelled CancellationToken
websocket.ClientCloseStatuswebsocket.ClientCloseStatus int OptionalOptional
websocket.ClientCloseDescriptionwebsocket.ClientCloseDescription String OptionalOptional

Zusätzliche RessourcenAdditional resources