Open Web Interface for .NET (OWIN) con ASP.NET Core
Di Steve Smith e Rick Anderson
ASP.NET Core:
- Supporta Open Web Interface per .NET (OWIN).
- Include sostituzioni compatibili con .NET Core per le
Microsoft.Owin.*
librerie (Katana).
OWIN consente alle app Web di essere disaccoppiate dai server Web. Definisce un modo standard per usare il middleware in una pipeline per gestire le richieste e le risposte associate. Le applicazioni ASP.NET Core e il middleware possono interagire con middleware, server e applicazioni basati su OWIN.
OWIN specifica un livello di disaccoppiamento che consente di usare contemporaneamente due framework con modelli a oggetti diversi. Il pacchetto Microsoft.AspNetCore.Owin
offre due implementazioni dell'adattatore:
- Da ASP.NET Core a OWIN
- Da OWIN a ASP.NET Core
In questo modo ASP.NET Core può essere ospitato in un server/host compatibile con OWIN o altri componenti compatibili con OWIN possono essere eseguiti su ASP.NET Core.
Nota
L'uso di questi adattatori comporta una riduzione delle prestazioni. Le app che usano solo componenti di ASP.NET Core non devono usare il pacchetto o gli adattatori Microsoft.AspNetCore.Owin
.
Visualizzare o scaricare il codice di esempio (procedura per il download)
Esecuzione del middleware OWIN nella pipeline ASP.NET Core
Il supporto di OWIN per ASP.NET Core viene distribuito come parte del pacchetto Microsoft.AspNetCore.Owin
. Per importare il supporto OWIN nel progetto è necessario installare il pacchetto.
Il middleware OWIN è conforme alle specifiche OWIN, che richiedono l'interfaccia Func<IDictionary<string, object>, Task>
e che siano impostate chiavi specifiche, come ad esempio owin.ResponseBody
. Il semplice middleware OWIN illustrato di seguito visualizza "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);
}
La firma di esempio restituisce un oggetto Task
e accetta un oggetto IDictionary<string, object>
come richiesto da OWIN.
Il codice seguente illustra come aggiungere il middleware OwinHello
, illustrato in precedenza, alla pipeline ASP.NET Core con il metodo di estensione UseOwin
.
public void Configure(IApplicationBuilder app)
{
app.UseOwin(pipeline =>
{
pipeline(next => OwinHello);
});
}
È possibile configurare altre azioni da eseguire all'interno della pipeline OWIN.
Nota
Le intestazioni di risposta devono essere modificate solo prima della prima scrittura nel flusso di risposta.
Nota
Le chiamate multiple al metodo UseOwin
sono sconsigliate per non compromettere le prestazioni. I componenti OWIN funzionano meglio se raggruppati insieme.
app.UseOwin(pipeline =>
{
pipeline(next =>
{
return async environment =>
{
// Do something before.
await next(environment);
// Do something after.
};
});
});
Eseguire ASP.NET Core in un server basato su OWIN e usare il supporto di WebSocket
Un altro esempio di funzionalità dei server basati su OWIN che può essere sfruttata da ASP.NET Core è l'accesso a funzionalità quali i WebSocket. Il server Web OWIN .NET usato nell'esempio precedente include il supporto per WebSockets integrato, che può essere sfruttato da un'applicazione ASP.NET Core. L'esempio seguente mostra una semplice app Web che supporta WebSocket e restituisce tutti gli elementi inviati al server tramite WebSocket.
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);
}
}
Ambiente OWIN
È possibile creare un ambiente OWIN tramite HttpContext
.
var environment = new OwinEnvironment(HttpContext);
var features = new OwinFeatureCollection(environment);
Chiavi OWIN
OWIN dipende da un oggetto IDictionary<string,object>
per comunicare informazioni attraverso uno scambio di richiesta/risposta HTTP. ASP.NET Core implementa le chiavi elencate di seguito. Vedere le specifiche principali e le estensioni, nonché la pagina OWIN Key Guidelines and Common Keys (Linee guida sulle chiavi OWIN e chiavi comuni).
Dati della richiesta (OWIN versione 1.0.0)
Chiave | Valore (tipo) | Descrizione |
---|---|---|
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 |
Dati della richiesta (OWIN versione 1.1.0)
Chiave | Valore (tipo) | Descrizione |
---|---|---|
owin.RequestId | String |
Facoltativo |
Dati della risposta (OWIN versione 1.0.0)
Chiave | Valore (tipo) | Descrizione |
---|---|---|
owin.ResponseStatusCode | int |
Facoltativo |
owin.ResponseReasonPhrase | String |
Facoltativo |
owin.ResponseHeaders | IDictionary<string,string[]> |
|
owin.ResponseBody | Stream |
Altri dati (OWIN versione 1.0.0)
Chiave | Valore (tipo) | Descrizione |
---|---|---|
owin.CallCancelled | CancellationToken |
|
owin.Version | String |
Chiavi comuni
Chiave | Valore (tipo) | Descrizione |
---|---|---|
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
Chiave | Valore (tipo) | Descrizione |
---|---|---|
sendfile.SendAsync | Vedere Delegate signature (Firma delegato) | Per richiesta |
Opaque v0.3.0
Chiave | Valore (tipo) | Descrizione |
---|---|---|
opaque.Version | String |
|
opaque.Upgrade | OpaqueUpgrade |
Vedere Delegate signature (Firma delegato) |
opaque.Stream | Stream |
|
opaque.CallCancelled | CancellationToken |
WebSocket v0.3.0
Chiave | Valore (tipo) | Descrizione |
---|---|---|
websocket.Version | String |
|
websocket.Accept | WebSocketAccept |
Vedere Delegate signature (Firma delegato) |
websocket.AcceptAlt | Non specificata | |
websocket.SubProtocol | String |
Vedere RFC6455 sezione 4.2.2 passaggio 5.5 |
websocket.SendAsync | WebSocketSendAsync |
Vedere Delegate signature (Firma delegato) |
websocket.ReceiveAsync | WebSocketReceiveAsync |
Vedere Delegate signature (Firma delegato) |
websocket.CloseAsync | WebSocketCloseAsync |
Vedere Delegate signature (Firma delegato) |
websocket.CallCancelled | CancellationToken |
|
websocket.ClientCloseStatus | int |
Facoltativo |
websocket.ClientCloseDescription | String |
Facoltativo |
Risorse aggiuntive
- Vedere l'origine in GitHub per le chiavi OWIN supportate nel livello di conversione.
- Middleware
- Server