簡單介紹OWIN是什麼,並且提供簡單的範例了解OWIN的運作
點部落的大家好,各種因緣際會下,決定跟大家分享和記錄一些筆者的學習,由於筆者在.Net領域還是一個新手,歡迎大家來聊天或指教~
既然是第一篇文章,那我們就來談一個大一點的題目 OWIN
OWIN (Open Web Interface for .NET)
OWIN 是一套介於.Net web servers和 web applications的開放標準界面,更加簡單一點來說,.Net以前都要架於在windows系統並且依附於iis,當要寫個輕量的網站就會被.Net龐大的System.web.dll和iis拖垮,而OWIN則是脫離了這些,不依附於iis,直接可以在console程式self host起來,並且將server架在Unix的作業系統上也沒問題!
在OWIN中定義了幾個名詞:
-
Web Application
網站的應用程式,在web framework中的頂端,並且可以在OWIN的server上運作 -
Web Framework
在OWIN的最上層,包含物件模型與與應用程式的API -
Middleware
所有在OWIN pipeline中request處理模組的統稱 -
Server
直接與client溝通的HTTP server,用OWIN語法來處理request -
Host
負責開啟與關閉application startup,server與application都在裡面運行
OWIN是一個介面標準,目前已經有不少第三方的支援,而微軟自己本身也建立了Katana支援OWIN。
簡單介紹完,聽起來還是有點模糊,筆者本身是更喜歡動手的行動派,接下來直接動手做個小範例可以清楚的介紹
建立一個console application專案,利用NuGet安裝以下套件:
- Microsoft.Owin
- Microsoft.Owin.Hosting
另外需要注意的是,NuGet裡面還是有提供是運行在iis上的owin,在下載套件的時候需要注意一下描述。
Host
以下是主程式,也就是我們的host。
class Program
{
static void Main(string[] args)
{
WebApp.Start<Startup>("http://localhost:9000");
Console.WriteLine("Server Started; Press enter to Quit");
Console.ReadLine();
}
}
在第一行可以看到,我們想要開啟的是Startup這個server,並且連上網址為http://localhost:9000。
Server
接下來需要建立一個Startup的class,可以選擇自己打或者是從.Net中建
Startup必須要有一個Configuration(IAppBuilder app)的方法,為了讓一host起server就可以將想要的middleware建立好並排入pipeline中。
using AppFunc = Func<IDictionary<string, object>, Task>;
public class Startup
{
public void Configuration(IAppBuilder app)
{
var middleware = new Func<AppFunc, AppFunc>(MyMiddleWare);
// 可插入多個middleware
app.Use(middleware);
// 可在()內傳入middleware建構子需要的參數
app.Use<OtherMiddleware>();
}
}
MiddleWare
而關於middleware,是用IDictionary<string, object>收集request與response全部的資訊,並且各層middleware也是使用IDictionary<string, object>傳遞資訊。在OWIN中,會把IDictionary<string, object>包裝成IOwinContext。
*IOwinContext裏面包含Request、Response、Environment(等同於IDictionary<string, object>)。
筆者提供了兩種建立middleware的方式,分別是使用method定義middleware並且使用IDictionary<string, object>傳遞資訊;另一種為建立繼承OwinMiddleware的物件並使用IOwinContext傳遞資訊。
用method定義middleware的方式:
public AppFunc MyMiddleWare(AppFunc next)
{
AppFunc appFunc = async (IDictionary<string, object> environment) =>
{
var response = environment["owin.ResponseBody"] as Stream;
byte[] str = Encoding.UTF8.GetBytes("My First Middleware");
await response.WriteAsync(str, 0, str.Length);
// 呼叫下一個 Middleware
await next.Invoke(environment);
};
return appFunc;
}
用class定義middleware,一定要繼承OwinMiddleware:
public class OtherMiddleware : OwinMiddleware
{
public OtherMiddleware(OwinMiddleware next) : base(next) { }
public override async Task Invoke(IOwinContext context)
{
byte[] str = Encoding.UTF8.GetBytes(" Other middleware");
context.Response.Body.Write(str, 0, str.Length);
await this.Next.Invoke(context);
}
}
其中可以發現的是environment["owin.ResponseBody"]和context.Response.Body指的是同一個東西,並且都是Stream型態保存,另外需要注意的是Response Body開始被寫時,Response的其他部分(例如Header)就無法更改了。
結果
下圖為執行後的結果,簡單的web就被建立起來了!
下一篇就來介紹web api在owin上運作
參考資料
ASP.NET: Understanding OWIN, Katana, and the Middleware Pipeline