ASP.NET Core 中文文档 第三章 原理(16).NET开放Web接口(OWIN)
2016-08-24 09:30
1296 查看
原文:Open Web Interface for .NET (OWIN)
作者:Steve Smith、 Rick Anderson
翻译:谢炀(kiler398)
校对:孟帅洋(书缘)
ASP.NET Core 支持 OWIN(即 Open Web Server Interface for .NET 的首字母缩写),OWIN的目标是用于解耦Web Server和Web Application。此外, OWIN为中间件定义了一个标准方法用来处理单个请求以及相关联的响应。ASP.NET Core 的程序和中间件可以和 OWIN-based 应用程序、服务器以及中间件相互交互。
章节:
在 ASP.NET 管道中运行 OWIN 中间件
在基于 OWIN 的服务器上宿主 ASP.NET
在 OWIN-based 服务器上运行 ASP.NET Core 并使用 WebSockets 支持
OWIN 键值
附录资源
查看下载示例代码
OWIN 中间件遵循 OWIN 标准, OWIN 标准定义了一系列
OWIN 最简单的方法签名是接收一个
添加 OWIN 中间件到 ASP.NET 管道是最简单的办法是使用
当然你也可以在 OWIN 管道中配置其他 actions 来替代。
注意
响应头信息只能在第一次写入响应流的时机之前修改。
注意
因为性能原因同时调用多个
我们同样会添加
上述操作就绪以后,所有的需要使用自定义服务器运行 ASP.NET 应用程序的设置都在下面的 project.json 文件的命令中:
了解更多关于 ASP.NET
这个 例子 和前一个配置一样使用相同
Servers
返回目录
作者:Steve Smith、 Rick Anderson
翻译:谢炀(kiler398)
校对:孟帅洋(书缘)
ASP.NET Core 支持 OWIN(即 Open Web Server Interface for .NET 的首字母缩写),OWIN的目标是用于解耦Web Server和Web Application。此外, OWIN为中间件定义了一个标准方法用来处理单个请求以及相关联的响应。ASP.NET Core 的程序和中间件可以和 OWIN-based 应用程序、服务器以及中间件相互交互。
章节:
在 ASP.NET 管道中运行 OWIN 中间件
在基于 OWIN 的服务器上宿主 ASP.NET
在 OWIN-based 服务器上运行 ASP.NET Core 并使用 WebSockets 支持
OWIN 键值
附录资源
查看下载示例代码
在 ASP.NET 管道中运行 OWIN 中间件
ASP.NET Core 对于 OWIN 的支持基于Microsoft.AspNetCore.Owin包。你可以在你的应用程序把这个包作为一个依赖导入到你的 project.json 文件里来实现对 OWIN 支持, 如下所示:
"dependencies": { "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0", "Microsoft.AspNetCore.Server.Kestrel": "1.0.0", "Microsoft.AspNetCore.Owin": "1.0.0" //手动高亮 },
OWIN 中间件遵循 OWIN 标准, OWIN 标准定义了一系列
Func<IDictionary<string, object>, Task>需要用到的属性接口, 并且规定了某些键值必须被设置 (例如
owin.ResponseBody)。 下面的简单的中间件的例子来显示 "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); }
OWIN 最简单的方法签名是接收一个
IDictionary<string, object>输入参数并且返回
Task结果。
添加 OWIN 中间件到 ASP.NET 管道是最简单的办法是使用
UseOwin扩展方法完成。参考上面所示的
OwinHello方法,将它添加到管道是一个简单的事情:
public void Configure(IApplicationBuilder app) { app.UseOwin(pipeline => { pipeline(next => OwinHello); }); }
当然你也可以在 OWIN 管道中配置其他 actions 来替代。
注意
响应头信息只能在第一次写入响应流的时机之前修改。
注意
因为性能原因同时调用多个
UseOwin是不被鼓励的。 OWIN 组件如果能组合在一起将运作是最好的。
app.UseOwin(pipeline => { pipeline(next => { // do something before return OwinHello; // do something after }); });
在基于 OWIN 的服务器上宿主 ASP.NET
基于 OWIN 的服务器可以宿主 ASP.NET 应用程序,Nowin就是其中之一,一个.NET 的 OWIN Web 服务器。在本文的例子中,我已经包含一个非常简单的项目并引用 Nowin 并用它来创建一个能够自托管 ASP.NET 核心的一个简单的服务器。
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Hosting.Server.Features; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Owin; using Microsoft.Extensions.Options; using Nowin; namespace NowinSample { public class NowinServer : IServer //手动高亮 { private INowinServer _nowinServer; private ServerBuilder _builder; public IFeatureCollection Features { get; } = new FeatureCollection(); public NowinServer(IOptions<ServerBuilder> options) { Features.Set<IServerAddressesFeature>(new ServerAddressesFeature()); _builder = options.Value; } public void Start<TContext>(IHttpApplication<TContext> application) { // Note that this example does not take into account of Nowin's "server.OnSendingHeaders" callback. // Ideally we should ensure this method is fired before disposing the context. Func<IDictionary<string, object>, Task> appFunc = async env => { // The reason for 2 level of wrapping is because the OwinFeatureCollection isn't mutable // so features can't be added var features = new FeatureCollection(new OwinFeatureCollection(env)); var context = application.CreateContext(features); try { await application.ProcessRequestAsync(context); } catch (Exception ex) { application.DisposeContext(context, ex); throw; } application.DisposeContext(context, null); }; // Add the web socket adapter so we can turn OWIN websockets into ASP.NET Core compatible web sockets. // The calling pattern is a bit different appFunc = OwinWebSocketAcceptAdapter.AdaptWebSockets(appFunc); // Get the server addresses var address = Features.Get<IServerAddressesFeature>().Addresses.First(); var uri = new Uri(address); var port = uri.Port; IPAddress ip; if (!IPAddress.TryParse(uri.Host, out ip)) { ip = IPAddress.Loopback; } _nowinServer = _builder.SetAddress(ip) .SetPort(port) .SetOwinApp(appFunc) .Build(); _nowinServer.Start(); } public void Dispose() { _nowinServer?.Dispose(); } } }
IServer是一个需要
Features属性和
Start方法的接口。
Start的职责是配置和启动服务器,在本示例中是通过一系列 fluent API 调用IServerAddressesFeature硬编码服务器地址来监听请求。注意 fluent 的
builder变量指定了请求会被方法
appFunc所处理。
Func方法在每一个请求被处理前调用。
我们同样会添加
IWebHostBuilder扩展来使得 Nowin 服务器易于添加和配置。
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(); } } }
上述操作就绪以后,所有的需要使用自定义服务器运行 ASP.NET 应用程序的设置都在下面的 project.json 文件的命令中:
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(); } } }
了解更多关于 ASP.NET
Servers。
在 OWIN-based 服务器上运行 ASP.NET Core 并使用 WebSockets 支持
如何基于OWIN的服务器功能,可以通过ASP.NET核心加以利用另一个例子是获得像WebSockets的功能。在前面的例子中使用的.NET OWIN Web服务器具有内置的网络插座,可通过一个ASP.NET的核心应用加以利用的支持。下面的例子显示了支持网络套接字和简单的回显然后直接通过WebSockets发送到服务器的任何一个简单的Web应用程序。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); } } }
这个 例子 和前一个配置一样使用相同
NowinServer唯一的区别是在该应用程序是如何在其
Configure方法是如何配置的。用 一个简单的 websocket 客户端的演示实际效果:
OWIN 键值
OWIN 依赖一个IDictionary<string,object>对象用来在一个完整的 HTTP 请求/响应交互中通讯信息。ASP.NET Core 实现所有的 OWIN 规范中列出的要求的必需和可选的以及自身实现的键。在OWIN规范不要求任何键是可选的,并且可以仅在某些情况下可以使用。 在使用 OWIN 键的时候,参阅 OWIN Key Guidelines and Common Keys 是一个好习惯。
请求数据 (OWIN v1.0.0)
键 | 值 (类型) | 描述 |
---|---|---|
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 |
请求数据 (OWIN v1.1.0)
键 | 值 (类型) | 描述 |
---|---|---|
owin.RequestId | String | 可选项 |
响应数据 (OWIN v1.0.0)
键 | 值 (类型) | 描述 |
---|---|---|
owin.ResponseStatusCode | int | 可选项 |
owin.ResponseReasonPhrase | String | 可选项 |
owin.ResponseHeaders | IDictionary<string,string[]> | |
owin.ResponseBody | Stream |
其他数据 (OWIN v1.0.0)
键 | 值 (类型) | 描述 |
---|---|---|
owin.CallCancelled | CancellationToken | |
owin.Version | String |
通用键值
键 | 值 (类型) | 描述 |
---|---|---|
ssl.ClientCertificate | X509Certificate | |
ssl.LoadClientCertAsync | Func<Task> | |
server.RemoteIpAddress | String | |
server.RemotePort | String | |
server.LocalIpAddress | String | |
server.LocalPort | String | |
server.IsLocal | bool | |
server.OnSendingHeaders | Action<Action<object>,object> |
发送文件 v0.3.0
键 | 值 (类型) | 描述 |
---|---|---|
sendfile.SendAsync | 参考 delegate signature | 每请求 |
Opaque v0.3.0
键 | 值 (类型) | 描述 |
---|---|---|
opaque.Version | String | |
opaque.Upgrade | OpaqueUpgrade | 参考 delegate signature |
opaque.Stream | Stream | |
opaque.CallCancelled | CancellationToken |
WebSocket v0.3.0
键 | 值 (类型) | 描述 |
---|---|---|
websocket.Version | String | |
websocket.Accept | WebSocketAccept | 参考 delegate signature |
websocket.AcceptAlt | 没有规定 | |
websocket.SubProtocol | String | 参考 RFC6455 Section 4.2.2 Step 5.5 |
websocket.SendAsync | WebSocketSendAsync | 参考 delegate signature |
websocket.ReceiveAsync | WebSocketReceiveAsync | 参考 delegate signature |
websocket.CloseAsync | WebSocketCloseAsync | 参考 delegate signature |
websocket.CallCancelled | CancellationToken | |
websocket.ClientCloseStatus | int | 可选项 |
websocket.ClientCloseDescription | String | 可选项 |
附录资源
MiddlewareServers
返回目录
相关文章推荐
- 在PetShop 4.0中ASP.NET缓存的实现
- [ASP.NET MVC] Child actions are not allowed to perform redirect
- Asp.NetWebForm的控件属性
- [总览]Asp.net
- 带你读开源—ASP.NET_MVC(一)
- [raspberry pi3] zram设置
- asp.net mvc 简易通用自定义Pager实现分页
- Asp.net Session 保存到MySql中
- asp.net微信开发第九篇----模板消息的使用
- Asp.net SignalR 实现服务端消息推送到Web端
- BouncyCastle使用教程
- C#利用NPOI导出Excel-ASP.NET MVC示例
- log4net使用教程
- asp.net 伪静态实现(UrlRewritingNet)
- ASP.NET MVC——URL路由
- ASP.NET 从数据库中导出数据
- ASP.NET 下拉列表绑定数据
- ASP.NET 使用Ajax
- ASP.NET 发起微信扫码支付
- 解读ASP.NET 5 & MVC6系列(11):Routing路由