概述
OWIN (Open Web Server Interface for .NET) 是一個(gè)規(guī)范和標(biāo)準(zhǔn),OWIN 定義了 Web 服務(wù)器與 Web 應(yīng)用之間的標(biāo)準(zhǔn)接口,將應(yīng)用與服務(wù)器解耦,使得便攜式 Web 應(yīng)用以及跨平臺(tái)的愿望成為現(xiàn)實(shí),標(biāo)準(zhǔn)的 OWIN 應(yīng)用可以在任何 OWIN 兼容的服務(wù)器上運(yùn)行,不再依賴(lài)與 Windows 和 IIS 。
微軟的 Katana、Identity、SignalR 等技術(shù)都是基于 OWIN 的標(biāo)準(zhǔn)中間件實(shí)現(xiàn)。
OWIN 4層結(jié)構(gòu)
在 OWIN 規(guī)范下可將一個(gè) Web 應(yīng)用解耦為4層:
- Host(宿主):應(yīng)用程序的主進(jìn)程,主要負(fù)責(zé) Server 的啟動(dòng)、關(guān)閉 ,為
Server 加載各種 Middleware,同時(shí)也裝載 Application。
- Server(服務(wù)器):綁定套接字并監(jiān)聽(tīng)的HTTP請(qǐng)求,將請(qǐng)求的信息依照 OWIN 規(guī)范,包裝成字典格式,傳遞到下層的 Middleware。
- Middleware(中間件):當(dāng)從客戶(hù)端發(fā)送一個(gè)請(qǐng)求,這個(gè)請(qǐng)求就會(huì)傳到 OWIN 管道中處理,Middleware 就是組成管道的組件。
- Application(應(yīng)用):具體的應(yīng)用程序代碼。

OWIN 規(guī)范約束
如下圖,基于 OWIN,Web Framework 不再依賴(lài) IIS 和 OS,這意味著理論上你可以使用任何其他 Web Server 來(lái)替換 IIS,OWIN 提供了明晰的規(guī)范以便我們快速靈活的去擴(kuò)展管道來(lái)處理 Http 請(qǐng)求,甚至可以不寫(xiě)任何一句代碼來(lái)切換不同的 Web Server,前提是這些 Web Server 遵循 OWIN 規(guī)范。

測(cè)試
下面我們分別以 IIS 為 Server 和 HttpListener 為 Server 來(lái)測(cè)試??赡芪覀儽容^熟悉的是以 IIS 作為 Server,按照上面的4層結(jié)構(gòu),應(yīng)用部署到 IIS 的時(shí)候并沒(méi)有設(shè)置Host,其實(shí)不用奇怪,因?yàn)?IIS 比較特殊,它既是 Server,也充當(dāng)了 Host。
IIS
實(shí)現(xiàn)步驟:
- 新建一個(gè)空Web應(yīng)用程序;
- Nuget 安裝 Microsoft.Owin.Host.SystemWeb;
- 根目錄下新建 Startup.cs 啟動(dòng)類(lèi)
注冊(cè)中間件到 OWIN 管道的三種方式:
- 默認(rèn)名稱(chēng)匹配(Startup.cs),只要這個(gè)類(lèi)的 namespace 和 Assembly 的名稱(chēng)相同,那類(lèi)中的 Configuration 方法就會(huì)在 OWIN 管道初始化的時(shí)候執(zhí)行。
public class Startup
{
public void Configuration(IAppBuilder app)
{
// 注冊(cè)中間件
// app.Use<xxxxx>();
app.Run(context =>
{
context.Response.ContentType = "text/palin";
return context.Response.WriteAsync("Hello OWIN");
});
}
}
- 使用 OwinStartupAttribute
[assembly: OwinStartup(typeof(IISExample.Startup1))]
namespace IISExample
{
public class Startup1
{
public void Configuration(IAppBuilder app)
{
// some code
}
}
}
- 配置文件的 appSetting 節(jié)點(diǎn)
<appSettings>
<add key="owin:appStartup" value="IISExample.Startup2" />
</appSettings>
說(shuō)明:
由于 IIS 既是 Host,又是 Server。所以 Microsoft.Owin.Host.SystemWeb 這個(gè) Server 實(shí)現(xiàn)的是注冊(cè) ASP.NET HttpModule 和 HttpHandler,阻斷原有的處理流程,轉(zhuǎn)而把請(qǐng)求發(fā)送到 OWIN 管道中處理。
結(jié)果:
F5 運(yùn)行

HttpListener
實(shí)現(xiàn)步驟:
- 新建一個(gè)控制臺(tái)應(yīng)用程序;
- NuGet 安裝 Microsoft.Owin.Hosting 、Microsoft.Owin.Host.HttpListener;
- 設(shè)置 StartOptions
- Startup 函數(shù)注冊(cè)
- 中間件注冊(cè)
static void Main(string[] args)
{
// 初始化StartOptions參數(shù)
StartOptions options = new StartOptions();
// 服務(wù)器Url設(shè)置
options.Urls.Add("http://localhost:9000");
options.Urls.Add("http://localhost:9001");
options.ServerFactory = "Microsoft.Owin.Host.HttpListener";
// 以O(shè)ptions和Startup啟動(dòng)Server
using (WebApp.Start(options, Startup))
{
Console.WriteLine("Owin Host/Server started,press enter to exit it...");
Console.ReadLine();
}// Server在Dispose中關(guān)閉
}
private static void Startup(IAppBuilder app)
{
Console.WriteLine("Sample Middleware loaded...");
// 注冊(cè)中間件
app.Use<SampleMiddleware>();
}
說(shuō)明:
Urls 參數(shù)是以 http 標(biāo)準(zhǔn) url 為格式字符串來(lái)定義Server監(jiān)聽(tīng)的 HostName 和 Port ,可以加多個(gè),表示支持不同的 HostName 和 Port 映射。
ServerFactory 指定這個(gè) Server 實(shí)現(xiàn)類(lèi)的 assembly name。通過(guò) HttpListener 打開(kāi) Socket 端口,監(jiān)聽(tīng)請(qǐng)求,然后將請(qǐng)求包裝發(fā)送到 OWIN 管道中處理。
當(dāng) using 的結(jié)尾觸發(fā) Dispose 時(shí) Server 被自動(dòng)關(guān)閉,Server 是獨(dú)立線(xiàn)程運(yùn)行的,所以宿主進(jìn)程必須駐留。
以上代碼沒(méi)有依賴(lài) Windows 和 IIS ,就能正常運(yùn)行了。
結(jié)果:
