Hi, Habr! ASP.NET Core supports an open web interface for .NET (OWIN), and OWIN allows you to unbind web applications from web servers. It defines the standard way of using middleware when 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 codeRunning middleware in an ASP.NET process
Support for OWIN from ASP.NET Core is deployed as part of the
Microsoft.AspNetCore.Owin
package. To import OWIN support into your project, add the package as a dependency to the
project.json
file:
')
"dependencies": { "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0", "Microsoft.AspNetCore.Server.Kestrel": "1.0.0", "Microsoft.AspNetCore.Owin": "1.0.0" },
The OWIN middleware meets
the OWIN specification , which requires the use of the
Func<IDictionary<string, object>, Task>
interface
Func<IDictionary<string, object>, Task>
and configure specific keys (for example,
owin.ResponseBody
). The following is an example of the OWIN middleware that displays the text Hello World:
public Task OwinHello(IDictionary<string, object> environment) { string responseText = "Hello World via OWIN"; byte[] responseBytes = Encoding.UTF8.GetBytes(responseText);
The sample signature issues
Task
and accepts
IDictionary<string, object>
as required by OWIN.
The following code shows how to add the
OwinHello
(see above) to the ASP.NET process using the
UseOwin
extension
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 be changed only before the first entry in the response stream.
You do not need to make many calls to
UseOwi
n: this reduces performance OWIN components work best when combined.
app.UseOwin(pipeline => { pipeline(next => {
ASP.NET hosting on the OWIN server
You
can host ASP.NET applications on the OWIN servers. One such server is Nowin, a .NET OWIN web server. In the sample for this article, we added a project that references Nowin and uses it to create an
IServer
that can host an 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<Startup>() .Build(); host.Run(); } } }
IServer
is an interface that requires the
Features
property and the
Start
method.
Start
is responsible for setting up and running the server. This is done using a series of API calls that configure addresses that were analyzed from IServerAddressesFeature. Note: the
_builder
variable
_builder
indicates that requests will be processed by the
appFunc
parameter previously configured in the method. This function is called for each request to process incoming requests.
We will also add the
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(); } } }
You then need to call the extension in Program.cs to execute an ASP.NET application 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(); } } }
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 functions 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<byte>(buffer), CancellationToken.None); while (!webSocket.CloseStatus.HasValue) {
This sample is configured using the same
NowinServer
as the previous one; the only difference is in the way the application is configured in the
Configure
method.
A test using a simple web socket client demonstrates the application:

Wowin
You can create an
HttpContext
using
HttpContext
.
var environment = new OwinEnvironment(HttpContext); var features = new OwinFeatureCollection(environment);
OWIN keys
To transfer information through data exchange HTTP request / response OWIN, an
IDictionary<string,object>
required. ASP.NET Core implements the keys listed below.
See Basic Specs , Extensions, and Basic Rules for Working with OWIN.
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 <string, string []> | |
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 <string, string []> | |
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
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
Additional resources