Open Web Interface for .NET (OWIN)
- Transfer
Hello, Habr! ASP.NET Core supports the open web interface for .NET (OWIN), and OWIN allows you to untie web applications from web servers. It defines a standard way to use middleware in processing requests and corresponding responses. ASP.NET Core applications and middleware are compatible with OWIN-based applications, servers, and middleware. Read more about this pair under the cut.
View or download sample code
OWIN support from ASP.NET Core is deployed as part of the package
OWIN middleware complies with the OWIN specification , which requires an interface and the configuration of certain keys (for example, ). The following is an example of OWIN middleware that displays Hello World text:
A signature sample is issued
You can configure other actions for the OWIN process.
The response headers should only be changed before the first entry into the response stream.
No need to make many calls to
OWIN servers can host ASP.NET applications. One such server is Nowin, the .NET OWIN web server. As an example for this article, we added a project that references Nowin and uses it to create one
We will also add an extension
Then you need to call the extension in Program.cs to run the ASP.NET application using this user server:
Learn more about ASP.NET servers .
Another way to use OWIN servers in ASP.NET Core is to access features like WebSockets. The .NET OWIN web server from the previous example supports embedded web sockets that can be used in an ASP.NET Core application. The example below shows a simple web application that supports web sockets and returns to the sender all the data sent to servers via web sockets.
This pattern is configured using the same
You can create an OWIN environment with
An OWIN HTTP request / response is required to transmit information through data exchange . ASP.NET Core implements the keys listed below. See the basic specification , extensions, and OWIN General Rules.
View or download sample code
Executing middleware in an ASP.NET process
OWIN support from ASP.NET Core is deployed as part of the package
Microsoft.AspNetCore.Owin
. To import OWIN support into your project, add the package as a dependency to the file project.json
:"dependencies": {
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
"Microsoft.AspNetCore.Owin": "1.0.0"
},
OWIN middleware complies with the OWIN specification , which requires an interface and the configuration of certain keys (for example, ). The following is an example of OWIN middleware that displays Hello World text:
Func, Task>
owin.ResponseBody
public Task OwinHello(IDictionary environment)
{
string responseText = "Hello World via OWIN";
byte[] responseBytes = Encoding.UTF8.GetBytes(responseText);
// OWIN Environment Keys: http://owin.org/spec/spec/owin-1.0.0.html
var responseStream = (Stream)environment["owin.ResponseBody"];
var responseHeaders = (IDictionary)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);
}
A signature sample is issued
Task
and accepted in accordance with OWIN requirements.
The following code shows how to add middleware (see above) to an ASP.NET process using the extension method .IDictionary
OwinHello
UseOwin
public void Configure(IApplicationBuilder app)
{
app.UseOwin(pipeline =>
{
pipeline(next => OwinHello);
});
}
You can configure other actions for the OWIN process.
The response headers should only be changed before the first entry into the response stream.
No need to make many calls to
UseOwi
n: this reduces performance. OWIN components work better when combined.app.UseOwin(pipeline =>
{
pipeline(next =>
{
// do something before
return OwinHello;
// do something after
});
});
ASP.NET hosting on an OWIN server
OWIN servers can host ASP.NET applications. One such server is Nowin, the .NET OWIN web server. As an example for this article, we added a project that references Nowin and uses it to create one
IServer
that can host ASP.NET Core on its own.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()
.Build();
host.Run();
}
}
}
IServer
Is an interface that requires a property Features
and method Start
. Start
responsible for setting up and starting the server. To do this, use a series of API calls that configure the addresses that were parsed from IServerAddressesFeature. Note: the configuration of the variable _builder
indicates that the request will be processed by the parameter appFunc
previously configured in the method. This function is called for each request to process incoming requests. We will also add an extension
IWebHostBuilder
to simplify the addition and configuration of 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();
});
}
public static IWebHostBuilder UseNowin(this IWebHostBuilder builder, Action configure)
{
builder.ConfigureServices(services =>
{
services.Configure(configure);
});
return builder.UseNowin();
}
}
}
Then you need to call the extension in Program.cs to run the ASP.NET application using this user 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()
.Build();
host.Run();
}
}
}
Learn more about ASP.NET servers .
Run ASP.NET Core on the OWIN server and use WebSockets support
Another way to use OWIN servers in ASP.NET Core is to access features like WebSockets. The .NET OWIN web server from the previous example supports embedded web sockets that can be used in an ASP.NET Core application. The example below shows a simple web application that supports web sockets and returns to the sender all the data sent to servers via web sockets.
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(buffer), CancellationToken.None);
while (!webSocket.CloseStatus.HasValue)
{
// Echo anything we receive
await webSocket.SendAsync(new ArraySegment(buffer, 0, received.Count),
received.MessageType, received.EndOfMessage, CancellationToken.None);
received = await webSocket.ReceiveAsync(new ArraySegment(buffer),
CancellationToken.None);
}
await webSocket.CloseAsync(webSocket.CloseStatus.Value,
webSocket.CloseStatusDescription, CancellationToken.None);
}
}
This pattern is configured using the same
NowinServer
as the previous one; the only difference is the way the application is configured in the method Configure
. The test using a simple web socket client demonstrates the application:OWIN Environment
You can create an OWIN environment with
HttpContext
.var environment = new OwinEnvironment(HttpContext);
var features = new OwinFeatureCollection(environment);
OWIN keys
An OWIN HTTP request / response is required to transmit information through data exchange . ASP.NET Core implements the keys listed below. See the basic specification , extensions, and OWIN General Rules.
IDictionary
Data Request (OWIN v1.0.0)
Key | Value (type) | Description |
---|---|---|
owin.RequestScheme | Line | |
owin.RequestMethod | Line | |
owin.RequestPathBase | Line | |
owin.RequestPath | Line | |
owin.RequestQueryString | Line | |
owin.RequestProtocol | Line | |
owin.RequestHeaders | IDictionary | |
owin.RequestBody | Flow |
Data Request (OWIN v1.1.0)
Key | Value (type) | Description |
---|---|---|
owin.RequestId | Line | Not necessary |
Response Data (OWIN v1.0.0)
Key | Value (type) | Description |
---|---|---|
owin.ResponseStatusCode | int | Not necessary |
owin.ResponseReasonPhrase | Line | Not necessary |
owin.ResponseHeaders | IDictionary | |
owin.ResponseBody | Flow |
Other data (OWIN v1.0.0)
Key | Value (type) | Description |
---|---|---|
owin.CallCancelled | CancellationToken | |
owin.Version | Line |
Shared Keys
Key | Value (type) | Description |
---|---|---|
ssl.ClientCertificate | X509Certificate | |
ssl.LoadClientCertAsync | Functask | |
server.RemoteIpAddress | Line | |
server.RemotePort | Line | |
server.LocalIpAddress | Line | |
server.LocalPort | Line | |
server.IsLocal | bool | |
server.OnSendingHeaders | ActionActionobject, object |
SendFiles v0.3.0
Key | Value (type) | Description |
---|---|---|
sendfile.SendAsync | See Signature Transfer | Upon request |
Opaque v0.3.0
Key | Value (type) | Description |
---|---|---|
opaque.Version | Line | |
opaque.Upgrade | Opaqueupgrade | See Signature Transfer |
opaque.Stream | Flow | |
opaque.CallCancelled | CancellationToken |
WebSocket v0.3.0
Key | Value (type) | Description |
---|---|---|
websocket.Version | Line | |
websocket.Accept | WebSocketAccept | See Signature Transfer |
websocket.AcceptAlt | Not indicated | |
websocket.SubProtocol | Line | See step 5.5 in Section 4.2.2 of RFC6455 |
websocket.SendAsync | WebSocketSendAsync | See Signature Transfer |
websocket.ReceiveAsync | WebSocketReceiveAsync | See Signature Transfer |
websocket.CloseAsync | WebSocketCloseAsync | See Signature Transfer |
websocket.CallCancelled | CancellationToken | |
websocket.ClientCloseStatus | int | Not necessary |
websocket.ClientCloseDescription | Line | Not necessary |