1,OWIN介绍
OWIN是Open Web Server Interface for .Net的首字母缩写。OWIN在.Net Web Server与Web Application之间定义了一套标准接口。OWIN的目标用于解耦Web Server与Web Application。OWIN只是一个契约、规范,而非代码的实现(Katana实现了OWIN)
2,OWIN规范
1)OWIN定义了Host、Server、Middleware、Application四层
①Host:主要负责应用程序的配置和启动进程,包括初始化OWIN Pipeline(管道,包含了Middleware)、运行Server
②Server:绑定套接字并监听Http请求,然后将Request和Response的Body、Header封装成符合OWIN规范的字典并发送到OWIN Middleware Pipeline中处理
②Middleware:中间件、组件,位于Server与Application之间,用来处理发送到Pipeline中的请求
④Application:具体的应用程序代码
2)Application Delegate(应用程序委托),用于Server与Middleware的交互。他并不是严格意义上的接口,而是一个委托并且每个OWIN中间件组件必须提供。
3)Environment Dictionary(环境字典),对http请求的封装
request data:
Required
|
Key Name
|
Value Description
|
Yes
|
"owin.RequestBody"
|
请求体。Stream类型
|
Yes
|
"owin.RequestHeaders"
|
请求头。IDictionary<string, string[]>类型
|
Yes
|
"owin.RequestMethod"
|
包含请求的HTTP请求方法(例如,“GET”,“POST”)的字符串。
|
Yes
|
"owin.RequestPath"
|
包含请求路径的字符串。 该路径必须是相对于应用程序委托的“根”的
|
Yes
|
"owin.RequestPathBase"
|
包含与应用程序委托的“根”对应的请求路径部分的字符串
|
Yes
|
"owin.RequestProtocol"
|
包含协议名称和版本的字符串(例如“HTTP / 1.0”或“HTTP / 1.1”)。
|
Yes
|
"owin.RequestQueryString"
|
包含HTTP请求URI的查询字符串组件的字符串,不含前导“?”(例如,“foo = bar&baz = quux”)。 该值可能是一个空字符串。
|
Yes
|
"owin.RequestScheme"
|
包含用于请求的URI方案(例如“http”,“https”)的字符串
|
response data:
Required
|
Key Name
|
Value Description
|
Yes
|
"owin.ResponseBody"
|
响应体。Stream类型
|
Yes
|
"owin.ResponseHeaders"
|
响应头。IDictionary<string, string[]>类型
|
No
|
"owin.ResponseStatusCode"
|
包含RFC 2616第6.1.1节中定义的HTTP响应状态代码的可选项。 默认值是200。
|
No
|
"owin.ResponseReasonPhrase"
|
包含原因短语的可选字符串关联给定的状态码。 如果没有提供,则服务器应该按照RFC 2616第6.1.1节的规定提供默认值
|
No
|
"owin.ResponseProtocol"
|
包含协议名称和版本的可选字符串(例如“HTTP / 1.0”或“HTTP / 1.1”)。 如果没有提供,则“owin.RequestProtocol”键的值是默认值。
|
other data:
Required
|
Key Name
|
Value Description
|
Yes
|
"owin.CallCancelled"
|
指示请求是否被取消/中止
|
Yes
|
"owin.Version"
|
表示OWIN版本的字符串“1.0”
|
1,Katana介绍
①Katana实现了OWIN的Layers
②Pileline中的Middleware是链式执行的,有开发人员控制
③层
2,使用ASP.NET/IIS托管Katana-based应用程序
nuget Microsoft.Owin.Host.SystemWeb
添加Startup启动类将Middleware中间件注册到Pileline中
using System; using System.Threading.Tasks; using Microsoft.Owin; using Owin; [assembly: OwinStartup(typeof(Katana.Systen.Web.Startup))] namespace Katana.Systen.Web { public class Startup { public void Configuration(IAppBuilder app) { // 有关如何配置应用程序的详细信息,请访问 https://go.microsoft.com/fwlink/?LinkID=316888 app.Run(context => { return context.Response.WriteAsync("holle World"); }); } } }
3,自托管Katana-based应用程序
nuget Microsoft.Owin.SelfHost
在Main方法中使用Startup配置项构建Pipeline并监听端口
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.Owin.Hosting; namespace Katana.SelfHost { class Program { static void Main(string[] args) { using (WebApp.Start<Startup>("http://localhost:7000")) { Console.WriteLine("程序启动"); Console.ReadLine(); } } } }
using System; using System.Threading.Tasks; using Microsoft.Owin; using Owin; [assembly: OwinStartup(typeof(Katana.SelfHost.Startup))] namespace Katana.SelfHost { public class Startup { public void Configuration(IAppBuilder app) { // 有关如何配置应用程序的详细信息,请访问 https://go.microsoft.com/fwlink/?LinkID=316888 app.Run(context => { return context.Response.WriteAsync("holle World"); }); } } }
3.1,使用Katana Diagnostic Helpers
将应用程序运行在自定义Host中,将失去IIS中所有的管理、诊断功能,但我们可以使用Katana提供的内置Helper比如Diagnostic helper来获取
nuget Micorost.Owin.Diagnostic
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.Owin.Hosting; namespace Katana.SelfHost { class Program { static void Main(string[] args) { using (WebApp.Start<DiagnosticStartup>("http://localhost:7000")) { Console.WriteLine("程序启动"); Console.ReadLine(); } } } }
using System; using System.Threading.Tasks; using Microsoft.Owin; using Owin; using System.Diagnostics; [assembly: OwinStartup(typeof(Katana.SelfHost.DiagnosticStartup))] namespace Katana.SelfHost { public class DiagnosticStartup { public void Configuration(IAppBuilder app) { // 有关如何配置应用程序的详细信息,请访问 https://go.microsoft.com/fwlink/?LinkID=316888 //将一个WelcomePage Middleware注册到pipeline中 //(在此输出WelcomePage渲染页面,并且不会执行余下的pipeline middleware组件) app.UseWelcomePage("/"); //将一个错误页注册到pipeline中 app.UseErrorPage(); app.Run(context => { if (context.Request.Path.ToString().Equals("/error")) { Trace.WriteLine(context.Request.Path); throw new Exception("抛出异常"); } return context.Response.WriteAsync("Hello World"); }); } } }
5,使用OwinHost.exe托管Katana-based应用程序
nuget OwinHost
nuget Micosoft.Owin
配置web属性
using System; using System.Threading.Tasks; using Microsoft.Owin; using Owin; [assembly: OwinStartup(typeof(Katana.OwinHost.WebApp.Startup))] namespace Katana.OwinHost.WebApp { public class Startup { public void Configuration(IAppBuilder app) { // 有关如何配置应用程序的详细信息,请访问 https://go.microsoft.com/fwlink/?LinkID=316888 app.Run(context => { return context.Response.WriteAsync("holle World"); }); } } }
6,几种制定Startup启动项方式
①默认名称约束:Host会去查找root namespace 下名为Startup的类作为启动项
②OwinStartup Attribute:当创建Owin Startup类时,自动会加上Attribute如:
[assembly: OwinStartup(typeof(Katana.OwinHost.WebApp.Startup))]
③配置文件:如:
<add key="owin:appStartup" value="Katana.OwinHost.WebApp.Startup">
④如果使用自定一host,那么可以通过 WebApp.Start<DiagnosticStartup>("http://localhost:7000") 来设置启动项
⑤如果使用OwinHost,那么可以通过命名行参数来实现
using System; using System.Threading.Tasks; using System.Collections; using Microsoft.Owin; using Owin; [assembly: OwinStartup(typeof(Katana.OwinHost.WebApp.Startup))] namespace Katana.OwinHost.WebApp { public class Startup { public void Configuration(IAppBuilder app) { // 有关如何配置应用程序的详细信息,请访问 https://go.microsoft.com/fwlink/?LinkID=316888 app.Use(async (context, next) => { await context.Response.WriteAsync("begin"+Environment.NewLine); await next(); await context.Response.WriteAsync("end" + Environment.NewLine); }); app.Use<MyMiddleware>(); app.Run(context => { return context.Response.WriteAsync("holle World" + Environment.NewLine); }); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Web; using Microsoft.Owin; namespace Katana.OwinHost.WebApp { public class MyMiddleware : OwinMiddleware { public MyMiddleware(OwinMiddleware next) : base(next) { } public override async Task Invoke(IOwinContext context) { await context.Response.WriteAsync("MyMiddleware-begin" + Environment.NewLine); await this.Next.Invoke(context); await context.Response.WriteAsync("MyMiddleware-end" + Environment.NewLine); } } }