OWIN英文全称是Open Web Interface for .NET。
仅从字面意思看OWIN是针对.net平台的开放web接口。
那Web接口是谁和谁之间的接口呢?是Web应用程序与Web服务器之间的接口,OWIN就是.NET Web应用程序与Web服务器之间的接口。或者说,OWIN是一个将Web应用程序从托管它的环境中独立出来的抽象层。
为什么需要这样一个接口呢?
因为.NET Web应用程序是运行于Web服务器之中的。.NET Web应用程序需要通过Web服务器接收用户的请求,并且通过Web服务器将响应内容发送用户。如果没有这样一个接口,.NET Web应用程序就要依赖于所运行的具体Web服务器,比如ASP.NET应用程序要依赖于IIS。有了这个接口,ASP.NET应用程序只需依赖这个抽象接口,不用关心所运行的Web服务器。其思想使这个独立出来的抽象层能够使ASP.NET技术堆栈有更大的创新,使托管ASP.NET应用程序的环境有更多的灵活性,并可以是轻量级的服务器架构。
所以,OWIN的作用就是通过引入一组抽象接口,解耦了.NET Web应用程序与Web服务器,再次体现了接口的重要性。在软件开发中,每次解耦都是一次很大的进步。
OWIN (Open Web Interface for .NET):
OWIN 是一种定义 Web 服务器和应用程序组件之间的交互的规范 。这一规范的目的是发展一个广阔且充满活力的、基于 Microsoft .NET Framework 的 Web 服务器和应用程序组件生态系统。
Katana 是开源的的OWIN框架,主要用于微软.NET应用程序。Katana 2.0 将随 Visual Studio 2013 一起发布。 新版本有两个值得关注的方面:
- 为自托管提供核心基础结构组件。
- 提供了一套丰富的验证中间件(包括 Facebook、Google、Twitter 和 Microsoft Account 这样的社交提供商)以及适用于 Windows Azure Active Directory、cookie 和联合身份验证的提供程序。
【进一步的理解】
OWIN是对ASP.NET Runtime的抽象。
ASP.NET 5.0是OWIN的一种实现
通过下面几张图可以更直观地理解:
可以关注一下ASP.NET Identity对OWIN 认证的支持。
图里最上面两个就是我们自己创建的代码,分别继承自己Microsoft.AspNet.Identity.EntityFramework的IdentityUser和IdentityDbContext。最后别忘了,我们与用户相关的操作实际上是通过Microsoft.AspNet.Identity.Core的 UserManager类来完成的。通过这样一种设计,可以把具体定义和实现交给上层,但是最后的核心却完全由自己掌控,实现松耦合,高内聚。
OWIN规范
OWIN定义了四层:
Host:主要负责应用程序的配置和启动进程,包括初始化OWIN pipeline,运行Server。
Server:绑定套接字并监听HTTP请求然后将Request和Response的Body、Header封装成符合OWIN规范的字典并发送到OWIN Middleware Pipeline中
Middleware:称为中间件、组件。位于Server和Application之间,用来处理发送到Pipeline中的请求。
Application:具体应用程序代码,只不过我们这里将他当注册到OWIN Middleware中处理HTTP请求,称为OWIN管道的一部分。
微软引入并推广OWIN,同时依照OWIN规范,实现了Katana。
Host
宿主只是一个进程,是整个OWIN程序的载体。这个宿主可以是IIS, IIS Express, Console, Windows Service等。
Katana为我们提供了3中选择:
- IIS / ASP.NET :使用IIS是最简单和向后兼容方式,在这种场景中OWIN Pipeline通过标准的HttpModule和HttpHandler启动。使用此Host你必须使用System.Web作为OWIN Server
- Self-Host :如果你想要使用其他Server来替换掉System.Web,并且可以有更多的控制权,可以选择创建一个自定义宿主,如使用Windows Service、控制台应用程序、Winform来承载Server
- OwinHost :也可以使用Katana提供的OwinHost.exe:他是一个命令行应用程序,运行在项目的根部,启动HttpListener Server并找到基于约束的Startup启动项
Server
负责绑定到 TCP 端口,监听端口发送过来的请求,同时将请求的信息依照OWIN规范,包装成字典格式,传递到下层的Middleware
Katana对OWIN Server的实现分为如下几类:
- System.Web:当使用IIS作为Host时,System.Web把自己注册为HttpModule和HttpHandler并且处理发送给IIS的请求(Microsoft.Owin.Host.SystemWeb)
- HttpListener:这是OwinHost.exe和自定义Host默认的Server。(Microsoft.Owin.Host.HttpListener)
- WebListener:这是ASP.NET vNext默认的轻量级Server,他目前无法使用在Katana中
Middleware
这是为组成 OWIN 管道中的组件。
Middleware可以理解为提供Func<IDictionary<string, object>, Task>接口的组件。
Katana提供了一个OwinMiddleware基类更加方便我们继承来实现OWIN Middleware.
Application
具体的代码实现,比如ASP.NET Web API、SignalR具体代码的实现。
事实上,对于这些类型的应用程序,Katana 组件只需使用一个小的配置类即可见。
IIS-Host
新建一个空的Web项目,Nuget引用Microsoft.Owin.Host.SystemWeb
创建Startup类
1
2
3
4
5
6
7
8
9
10
11
|
public
class
Startup
{
public
void
Configuration(IAppBuilder app)
{
app.Run(context =>
{
context.Response.ContentType =
"text/plain"
;
return
context.Response.WriteAsync(
"Hello World!"
);
});
}
}
|
访问项目地址:http://localhost:xx
Self-Host
新建控制台项目,Nuget引用Microsoft.Owin.SelfHost
Main方法
1
2
3
4
|
创建Startup类
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class
Startup
{
public
void
Configuration(IAppBuilder app)
{
#if DEBUG
//诊断
app.UseErrorPage();
#endif
//欢迎页
//app.UseWelcomePage("/");
app.Run(x=>x.Response.WriteAsync(
"hello world"
));
}
}
|
访问地址:http://localhost:12345
OWIN-Host
新建类库项目,Nuget引用OwinHost
创建Startup类(需要程序集Owin和Microsoft.Owin)
1
2
3
4
5
6
7
8
9
10
11
|
public
class
Startup
{
public
void
Configuration(IAppBuilder app)
{
app.Run(context =>
{
context.Response.ContentType =
"text/plain"
;
return
context.Response.WriteAsync(
"Hello World!"
);
});
}
}
|
OwinHost.exe
这里需要注意
- Nuget下载完,OwinHost.exe会在package文件夹里
- OwinHost.exe会加载./bin文件夹下的程序集作为server assembly
所以我们将这OwinHost.exe3个文件移动到
=>
另外将Debug或者Release文件夹下的文件移动到bin文件夹下
cmd运行OwinHost.exe
访问:http://localhost:5000/
Middleware非常类似于HttpModule,会注册到Owin的pipeline中执行代码.
继承OwinMiddleware
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public
class
HelloMiddlerware : OwinMiddleware
{
public
HelloMiddlerware(OwinMiddleware next)
:
base
(next)
{
}
public
override
Task Invoke(IOwinContext context)
{
context.Response.Write(
"hello"
+DateTime.Now);<br>
//管道继续往下走
return
Next.Invoke(context);
}
}
|
Startup
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public
class
Startup
{
public
void
Configuration(IAppBuilder app)
{
// 有关如何配置应用程序的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkID=316888
//管线自由组合
app.Use<HelloMiddlerware>();
//Run是插入一个中间件,并终止继续往下流
app.Run(x => x.Response.WriteAsync(
"good"
));
//此中间件将不执行
app.Use<HelloMiddlerware>();
}
}
|
来看一下组件的执行顺序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
public
class
Startup
{
public
void
Configuration(IAppBuilder app)
{
app.Use((x, next) =>
{
x.Response.ContentType =
"text/html"
;
return
next.Invoke();
});
app.Use((x, next) =>
{
x.Response.WriteAsync(
"1 Before"
);
next.Invoke();
return
x.Response.WriteAsync(
"1 After"
);
});
app.Use((x, next) =>
{
x.Response.WriteAsync(
"2 Before"
);
next.Invoke();
return
x.Response.WriteAsync(
"2 After"
);
});
app.Run(x => x.Response.WriteAsync(
"<br/>hello world<br/>"
));
}
}
|
浏览结果:
扩展
Startup类如何被关联
1.默认名称匹配
可以定义Startup.cs类,只要这个类的namespace和Assembly的名称相同。那么,这个Startup.cs中的Configuration方法,就会在OWIN管道初始化的时候执行。
2.使用OwinStartup Attribute
这就是我们例子中使用的方式,直接指定哪个具体类是Startup类。
3.在配置文件的appSetting 节点设置
1
2
3
|
<appSettings>
<add key=
"owin:appStartup"
value=
"StartupDemo.ProductionStartup"
/>
</appSettings>
|
Pipeline
Owin的pipeline在IIS Host上本质是注册到Httpapplication的pipeline上.
如:app.UseStageMarker(PipelineStage.Authenticate);
本文参考:
http://www.cnblogs.com/JustRun1983/p/3955238.html
Katana:http://www.asp.net/aspnet/overview/owin-and-katana/an-overview-of-project-katan