📜 ⬆️ ⬇️

Open web interface for .NET (OWIN)

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 code

Running 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); // OWIN Environment Keys: http://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); } 

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 => { // do something before return OwinHello; // do something after }); }); 

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

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)

KeyValue (type)Description
owin.RequestSchemeLine
owin.RequestMethodLine
owin.RequestPathBaseLine
owin.RequestPathLine
owin.RequestQueryStringLine
owin.RequestProtocolLine
owin.RequestHeadersIDictionary <string, string []>
owin.RequestBodyFlow

Data Request (OWIN v1.1.0)

KeyValue (type)Description
owin.RequestIdLineNot necessary

Response data (OWIN v1.0.0)

KeyValue (type)Description
owin.ResponseStatusCodeintNot necessary
owin.ResponseReasonPhraseLineNot necessary
owin.ResponseHeadersIDictionary <string, string []>
owin.ResponseBodyFlow

Other data (OWIN v1.0.0)

KeyValue (type)Description
owin.CallCancelledCancellationToken
owin.VersionLine

Shared keys

KeyValue (type)Description
ssl.ClientCertificateX509Certificate
ssl.LoadClientCertAsyncFunctask
server.RemoteIpAddressLine
server.RemotePortLine
server.LocalIpAddressLine
server.LocalPortLine
server.IsLocalbool
server.OnSendingHeadersActionActionobject, object

SendFiles v0.3.0

KeyValue (type)Description
sendfile.SendAsyncSee Signature TransferOn request

Opaque v0.3.0

KeyValue (type)Description
opaque.VersionLine
opaque.UpgradeOpaqueUpgradeSee Signature Transfer
opaque.StreamFlow
opaque.CallCancelledCancellationToken

WebSocket v0.3.0

KeyValue (type)Description
websocket.VersionLine
websocket.AcceptWebSocketAcceptSee Signature Transfer
websocket.AcceptAltNot specified
websocket.SubProtocolLineSee step 5.5 in Section 4.2.2 of RFC6455
websocket.SendAsyncWebSocketSendAsyncSee Signature Transfer
websocket.ReceiveAsyncWebSocketReceiveAsyncSee Signature Transfer
websocket.CloseAsyncWebSocketCloseAsyncSee Signature Transfer
websocket.CallCancelledCancellationToken
websocket.ClientCloseStatusintNot necessary
websocket.ClientCloseDescriptionLineNot necessary

Additional resources


Source: https://habr.com/ru/post/342900/


All Articles