在自定web server的範例中,可看出接收客服請求可不用依賴於IIS,,本文中會使用OWIN來接管IIS請求和自行託管(self-hosting)
OWIN(Open Web Interface for .Net)是一套定義,它本身不具備任何代碼,目的是為了讓網站應用程式和網站伺服器解除依賴關係
在一個 Http 請求在進入 IIS (7.0 集成模式管道模型)後,一直到返回response之間會經歷許多事件,會有很多的Http Module專門處理這些事件,例如FormsAuthenticationModule就是註冊了AuthenticateRequest事件,也可以開發自己的 Http Module 處理一些事件,通過 web.config 把我們自定義的 Http Module 註冊進 IIS
ASP.NET 多數Modules默認全部開啟,如果不使用它們,這些Module是需要手動在config文件裡面移除的。但是大多數情況下並不會想到去移除他們,這其實是一個性能上的損失。
有了OWin之後,就不再是與ASP.NET 管道打交道了,而是OWin的管道,但是這個管道相對於ASP.NET 管道而言更靈活,更開放
Demo 1 : 讓OWin接管IIS的請求
1. 建立一個空的MVC網站2. 從Nuget中添加Microsoft.Owin.Host.SystemWeb
這個dll可以讓OWin接管IIS的請求,雖然同樣是託管在IIS,但是所有的請求都會被OWin來處理。在OWin的4層結構中(Applicaton->Middleware->Server->Host),Microsoft.Owin.Host.SystemWeb屬於Server層,還有一個同樣也在Server層的是Microsoft.Owin.Host.HttpListener,這個可以實現利用控制台程序現實自託管,就可以完全擺脫IIS了3. 添加Startup類
要使用Owin的應用程序都要有一個叫Startup的類,在這個類裡面有一個Configuration的方法,這兩個名字是默認約定,必須用同樣的名字才會被Owin找到。
public class Startup
{
/// <summary>
/// 自行定義管線
/// </summary>
/// <param name="app"></param>
public void Configuration(IAppBuilder app) // IAppBuilder using "Owin"
{
// 通過 Use 方法來添加自己的管線的處理步驟
app.Use(async (context, next) => {
await context.Response.WriteAsync("Authentication... ");
await next();
});
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("Authorization... ");
await next();
});
app.Use(async (context, next) =>
{
context.Response.ContentType = "text/plain";
await context.Response.WriteAsync("Hello World!");
});
}
}
在web.config中加入一個配置,讓OWin處理所有的請求
<?xml version="1.0" encoding="utf-8"?>
<!--
如需如何設定 ASP.NET 應用程式的詳細資訊,請造訪
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
</system.web>
<appSettings>
<!--讓 OWin 處理所有請求 -->
<add key="owin:HandleAllRequests" value="true" />
</appSettings>
</configuration>
不管我們輸入什麼URL,都會返回同樣的結果,因為不管哪個URL,對應的都是我們上面所寫的代碼。
上面的網站我們依舊是託管在IIS中的,現在想要擺脫IIS,所以接下來我們就來利用Owin的自託管功能。
Demo 2 : 利用OWIN的自託管功能
2. 用Nuget安裝Microsoft.Owin.Hosting 和Microsoft.Owin.HttpListener
利用Microsoft.Owin.Host.HttpListener來實現自寄宿(self-hosting)3. 添加Startup類 (將上面的 Startup 範例 copy 過來用)
4. 在Main方法中加入下面的一段代碼去啟動我們的網站。
static void Main(string[] args)
{
using (WebApp.Start<Startup>(new StartOptions(url: "http://localhost:8080/"))) // WebApp using "Microsoft.Owin.Hosting"
{
Console.ReadLine();
}
Console.ReadLine();
}
啟動我們的控制台程序之後,通過瀏覽器訪問http://localhost:8080/就可以看到結果。用控制台程序自寄宿的時候,就沒有使用IIS,也就沒有System.Web,而response 和 request 訊息被封裝在 Katana (微軟對於Owin的一套實現,用VS2013新建一個MVC5的項目都會自動引用相關的dll(Owin.dll, Microsoft.Owin.dll) ,也會自動添加Startup的配置類)
用Middleware來串成一個完整的管道
以上的 Startup 類裡面使用了Use方法來構成一個完整的管道,現在要將Use中的代碼轉換成Middleware,打包成dll供其它項目使用IAppBuilder 提供了一個Use的重載可以把一個Middleware作為泛型參數傳進去來實現將這個Middleware註冊進Owin的管道。下面模擬一下AuthenticationMiddleware和AuthorizationMiddleware的實現,我們可以直接從OwinMiddleware繼承
class AuthenticationMiddleware : OwinMiddleware
{
/*
* 所有的Middleware構造函數都接收一個OwinMiddleware作為參數傳給基類,
* 基類會把它作為下一下Middleware,和我們上面用到的Next一樣都是為了確定管道繼續進行下去。
*/
public AuthenticationMiddleware(OwinMiddleware next)
: base(next)
{
}
// 主要邏輯入口
public override async Task Invoke(IOwinContext context)
{
await context.Response.WriteAsync("Authentication....");
// 如果想在這裡中斷整個管道,下面的程式可以刪除。
await Next.Invoke(context);
}
}
class AuthorizationMiddleware : OwinMiddleware
{
public AuthorizationMiddleware(OwinMiddleware next)
: base(next)
{
}
// 主要邏輯入口
public override async Task Invoke(IOwinContext context)
{
await context.Response.WriteAsync("Authorization....");
await Next.Invoke(context);
}
}
修改Startup類來註冊我們的Middleware
class Startup
{
public void Configuration(IAppBuilder app)
{
app.Use<AuthenticationMiddleware>();
app.Use<AuthorizationMiddleware>();
app.Use(async (context, next) =>
{
context.Response.ContentType = "text/plain";
await context.Response.WriteAsync("Hello World!");
});
}
}
用Microsoft.Owin.StaticFiles來實現靜態站點的託管
1. 利用上面 console 的範例2. 用Nuget下載Microsoft.Owin.StaticFiles
3. 在 \bin\Debug 下添加一個 index.html
4. 修改 Startup 類
class Startup
{
public void Configuration(IAppBuilder app)
{
// var root = @"C:\工作\練習\OwinConsoleApplication\OwinConsoleApplication\bin\Debug"; // 直接寫死根目錄位置
var root = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
var fileSystem = new PhysicalFileSystem(root); // using Microsoft.Owin.FileSystems;
var options = new FileServerOptions // using Microsoft.Owin.StaticFiles;
{
EnableDefaultFiles = true,
FileSystem = fileSystem
};
app.UseFileServer(options: options);
}
}
啟動 console 應用程式後,利用瀏覽器訪問 http://localhost:8080/ (自行設定的網址) 後,就能看到 index.html參考:
Getting Started with ASP NET MVC5 6 2 Introduction to OWIN New to MVC5