這半年來,在開發ASP.NET Web API及SignalR的過程常看到一枚生冷術語--OWIN,不知其所以然好一陣子,今天花點功夫粗略理解一番,特筆記備忘。
OWIN(Open Web Interface for .NET)是一套開放網站介面標準,重新定義了.NET Web Application與Web Server的溝通介面。就系統架構觀點,介面被抽取出來獨立意味著"抽換"的可能性,用白話解釋,意思是ASP.NET程式可以不依賴System.Web.dll,不侷限於IIS,放在Console程式裡跑Self-Hosting模式,甚至透過Kayak網站伺服器在*nix系統運作,都不再是神話。
由下到上,OWIN架構區分為四層:
- Host
最底層,負責載入、啟動及關閉OWIN元件 - Server
負責連上TCP Port,建構OWIN Pipeline環境以處理Request - Middleware
所有在OWIN Pipeline中Request處理模組的統稱,小到很簡單的資料壓縮模組,大至ASP.NET Web API都算。 - Application
依專案需求所開發的應用程式碼
擺脫System.Web.dll的另一項好處: 網站基底架構由龐大的官方Framework轉化成多個中小型模組,可以個別機動抽換更新,不需要苦苦等待官方改版。
現今ASP.NET相關技術中,由ASP.NET Web API跨出第一步,完全排除對System.Web.dll的依賴。.NET社群仿效Ruby Rack的精神,為.NET網站定義了OWIN,而Katana專案則是微軟依OWIN規格所實作的元件,包含Host、Server、身分認證元件... 等,ASP.NET Web API與SignalR則是目前應用OWIN標準的經典範例。
光說不練令人心虛,總得來個簡單演練才踏實,以下是個範例,利用Microsoft.Owin.Hosting.WebApp + Nancy(一套支援OWIN的迷你Web Server模組),在Console Application模擬簡易Web Server。
開啟一個Console Application專案,利用NuGet安裝以下套件:
Microsoft.Owin.Hosting
Microsoft.Owin.Host.HttpListener
Nacy.Owin
簡單寫幾行程式:
- 定義MyStartup類別,在其中設定Server要掛載的模組,UseNancy是Nancy提供的Extension Method,一行就搞定Nancy設定。
- 定義HomeModule,繼承NancyModule,在建構式中宣告Get["/"]拋回HTML、Post["/money"]傳回Server時間,我們為這個小Web加入 GET / 及 POST /money 兩個功能。
- WebApp.Start<MyStarup>("http://+:1234")聆聽本機的1234 Port開始執行網站功能,透過Console.ReadLine()待使用者按Enter後結束服務。(記得要netsh開權限,這點之前提過)
- 打完收工。
using Microsoft.Owin.Hosting;
using Nancy;
using Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OWINLab
{
class Program
{
staticvoid Main(string[] args)
{
//記得開放Binding權限
//netsh http add urlacl url=http://+:port_number/ user=machine\username
using (WebApp.Start<MyStartup>("http://+:1234"))
{
Console.WriteLine("OWIN self-hosting, press enter to exit");
Console.ReadLine();
}
}
}
publicclass HomeModule : NancyModule
{
public HomeModule()
{
Get["/"] = x =>
{
return@"
<html><body>
<input type='button' value='Show Me the Money'></input>
<script src='http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.1.js'></script>
<script>
$(':button').click(function() {
$.post('/money',{},function(m) {
alert(m);
});
});
</script>
</body></htmol>";
};
Post["/money"] = x =>
{
return"MONEY @ " + DateTime.Now.ToString("HH:mm:ss");
};
}
}
publicclass MyStartup
{
publicvoid Configuration(IAppBuilder app)
{
app.UseNancy();
}
}
}
就這樣誕生一個超簡單的小Web,很感人吧!
【延伸閱讀】