OWIN入門

  • 4025
  • 0
  • 2015-10-26

簡單介紹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上運作

參考資料

官方的範例

黑暗執行緒

MUHAMMAD SHUJAAT SIDDIQI

腾飛(Jesse)

ASP.NET: Understanding OWIN, Katana, and the Middleware Pipeline