在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ C#/ ASP.NET MVC 隨想錄(7)——鋒利的 KATANA
ASP.NET MVC 使用 Bootstrap 系列(4)——使用 JavaScript 插件
ASP.NET MVC 隨想錄(6)——漫談 OWIN
ASP.NET MVC 隨想錄(5)——創(chuàng)建 ASP.NET MVC Bootstrap Helpers
ASP.NET MVC 隨想錄(3)——使用 Bootstrap 組件
ASP.NET MVC 隨想錄(7)——鋒利的 KATANA
ASP.NET MVC 隨想錄(1)——開始使用 Bootstrap
ASP.NET MVC 隨想錄(8)——創(chuàng)建自定義的 Middleware 中間件
ASP.NET MVC 隨想錄(2)——使用 Bootstrap CSS 和 HTML 元素
作者簡介

ASP.NET MVC 隨想錄(7)——鋒利的 KATANA

正如上篇文章所講解的,OWIN 在 Web Server 與 Web Application 之間定義了一套規(guī)范(Specs),意在解耦 Web Server 與 Web Application,從而推進跨平臺的實現(xiàn)。若要真正使用 OWIN 規(guī)范,那么必須要對他們進行實現(xiàn)。目前有兩個產(chǎn)品實現(xiàn)了 OWIN 規(guī)范——一是由微軟主導的 Katana,二是第三方的 Nowin。本文主要關注的還是 Katana,由微軟團隊主導,開源到 CodePlex 上。

在介紹 Katana 之前,我覺得有必要先為大家梳理一下十幾年以來 ASP.NET 發(fā)展歷程。

ASP.NET 發(fā)展歷程

ASP.NET Web Form

ASP.NET Web Form 在 2002 正式發(fā)布時,面向的開發(fā)者主要有兩類:

  • 使用混合 HTML 標記和服務端腳本開發(fā)動態(tài)網(wǎng)站的 ASP 開發(fā)者,另外,ASP 運行時抽象了底層的 HTTP 連接和 Web Server,并為開發(fā)者提供了一系列的對象模型用于交互 Http 請求,當然也提供了額外的服務諸如 Session、Cache、State 等。
  • 開發(fā) WinForm 的程序員,他們可能對 HTTP 和 HTML 一無所知,但熟悉拖控件的方式來構建應用程序。

為了迎合這兩類開發(fā)者,ASP.NET Web Form 通過使用沉重的 ViewState 來保存頁面回傳過程中的狀態(tài)值,因為 HTTP 協(xié)議是無狀態(tài)的,通過 ViewState,使原本沒有記憶的 Http 協(xié)議變得有記憶起來。這在當時是非常好的設計,能通過拖拽控件的形式快速開發(fā) Web,而不必過多的去關注底層原理。同時 ASP.NET 團隊還為 ASP.NET 豐富了更多的功能,諸如:Session、Cache、Configuration 等等。

這在當時無疑是成功的,ASP.NET 的發(fā)布迅速拉攏了開發(fā)者,在 Web 開發(fā)中形成了一股新的勢力,但同時也買下來一些隱患:

  • 所有的功能、特性都發(fā)布在一個整體框架上并且緊耦合核心的 Web 抽象庫——System.Web
  • System.Web 是.NET Framework 的重要組成部分,這意味著要修復更新 System.Web 必須更新.NET Framework,但.NET Framework 是操作系統(tǒng)的基礎,為了穩(wěn)定性往往不會頻繁更新。
  • ASP.NET Framework (System.Web)緊耦合 IIS
  • IIS 只能運行在 Windows系統(tǒng)

ASP.NET MVC

由于 Web Form 產(chǎn)生一大堆 ViewState 和客戶端腳本,這對開發(fā)者來說慢慢變成一種累贅,因為我們只想產(chǎn)生純凈的 HTML 標記。所以開發(fā)者更想去主動控制而非被動產(chǎn)生額外 HTML 標記。

所以微軟基于 MVC 設計模式推出了其重要的 Web Framework——ASP.NET MVC Framework,通過 Model-View-Control 解耦了業(yè)務邏輯和表現(xiàn)邏輯,同時沒有了服務器端控件,將頁面的控制權完全交給了開發(fā)者。

為了快速更新迭代,通過 Nuget 來獲取更新,故從.NET Framework 中分離開了。但唯一不足的是,ASP.NET MVC 還是基于 ASP.NET Framework(注:ASP.NET MVC 6 已經(jīng)不依賴 System.Web),所以 Web Application 和 Web Server 依舊沒有解耦。

ASP.NET Web API

隨著時間的推移,一些問題開始暴露出來了,由于 Web Server 和 Web Application 緊耦合在一起,微軟在開發(fā)獨立、簡單的 Framework 上越發(fā)捉襟見肘,這和其他平臺下開源社區(qū)蓬勃發(fā)展形成鮮明對比,幸運的是微軟做出了改變,推出了獨立的 Web Framework ——ASP.NET Web API,它適用于移動互聯(lián)網(wǎng)并可以快速通過 Nuget 安裝,更為重要的是,它不依賴 System.Web,也不依賴 IIS,你可以使用 Self-Host 或者在其他 Web Server 部署。

Katana

隨著 Web API 能夠運行在自己的輕量級的宿主中,并且越來越多簡單、模塊化、專一的 Framework 問世,開發(fā)人員有時候不得不啟動單獨的進程來處理 Web 應用程序的各種組件(模塊)、如靜態(tài)文件、動態(tài)文件、Web API 和 Socket。為了避免進程擴散,所有的進程必須啟動、停止并且獨立進行管理。這時,我們需要一個公共的宿主進程來管理這些模塊。

這就是 OWIN 誕生的原因,解耦成最小粒度的組件,然后這些標準化框架和組件可以很容易地插入到 OWIN Pipeline 中,從而對組件進行統(tǒng)一管理。而 Katana 正是 OWIN 的實現(xiàn),為我們提供了豐富的 Host 和 Server。

走進Katana的世界

Katana 作為 OWIN 的規(guī)范實現(xiàn),除了實現(xiàn) Host 和 Server 之外,還提供了一系列的 API 幫助開發(fā)應用程序,其中已經(jīng)包括一些功能組件如身份驗證(Authentication)、診斷(Diagnostics)、靜態(tài)文件處理(Static Files)、ASP.NET Web API 和 SignalR 的綁定等。

Katana的基本原則

  • 可移植性:從 HostàServeràMiddleware,每個 Pipeline 中的組件都是可替換的,并且第三方公司和開源項目的 Framework 都是可以在 OWIN Server 上運行,也就是說不受平臺限制,從而實現(xiàn)跨平臺。
  • 模塊化:每一個組件都必須保持足夠獨立性,通常只做一件事,以混合模塊的形式來滿足實際的開發(fā)需求
  • 輕量和高效:因為每一個組件都是模塊化開發(fā),而且可以輕松的在 Pipeline 中插拔組件,實現(xiàn)高效開發(fā)

Katana 體系結構

Katana 實現(xiàn)了 OWIN 的 Layers,所以 Katana 的體系結構和 OWIN 一致,如下所示:

http://wiki.jikexueyuan.com/project/think-in-asp-net-mvc/images/Chapter7/2.png" alt="" />

1.)Host :宿主 Host 被 OWIN 規(guī)范定義在第一層(最底層),他的職責是管理底層的進程(啟動、關閉)、初始化 OWIN Pipeline、選擇 Server 運行等。

Katana 為我們提供了 3 種選擇:

  • IIS / ASP.NET :使用 IIS 是最簡單和向后兼容方式,在這種場景中 OWIN Pipeline 通過標準的 HttpModule 和 HttpHandler 啟動。使用此 Host 你必須使用 System.Web 作為 OWIN Server
  • Custom Host :如果你想要使用其他 Server 來替換掉 System.Web,并且可以有更多的控制權,那么你可以選擇創(chuàng)建一個自定義宿主,如使用 Windows Service、控制臺應用程序、Winform 來承載Server。
  • OwinHost :如果你對上面兩種 Host 還不滿意,那么最后一個選擇是使用 Katana 提供的OwinHost.exe:他是一個命令行應用程序,運行在項目的根部,啟動 HttpListener Server并找到基于約束的 Startup 啟動項。OwinHost 提供了命令行選項來自定義他的行為,比如:手動指定 Startup 啟動項或者使用其他 Server(如果你不需要默認的 HttpListener Server)。

2.)Server

Host 之后的 Layer 被稱為 Server,他負責打開套接字并監(jiān)聽 Http 請求,一旦請求到達,根據(jù)Http 請求來構建符合 OWIN 規(guī)范的 Environment Dictionary(環(huán)境字典)并將它發(fā)送到 Pipeline 中交由 Middleware 處理。Katana 對 OWIN Server 的實現(xiàn)分為如下幾類:

  • System.Web:如前所述那樣,System.Web 和 IIS/ASP.NET Host 兩者彼此耦合,當你選擇使用System.Web 作為 Server ,Katana System.Web Server 把自己注冊為 HttpModule 和HttpHandler 并且處理發(fā)送給 IIS 的請求,最后將 HttpRequest、HttpResponse 對象映射為 OWIN 環(huán)境字典并將它發(fā)送至 Pipeline 中處理。
  • HttpListener:這是 OwinHost.exe 和自定義 Host 默認的 Server。
  • WebListener:這是 ASP.NET vNext 默認的輕量級 Server,他目前無法使用在 Katana 中

3)Middleware

Middleware(中間件)位于 Host、Server 之后,用來處理 Pipeline 中的請求,Middleware 可以理解為實現(xiàn)了 OWIN 應用程序委托 AppFun 的組件。

Middleware 處理請求之后并可以交由下一個 Pipeline 中的 Middleware 組件處理,即鏈式處理請求,通過環(huán)境字典可以獲取到所有的 Http 請求數(shù)據(jù)和自定義數(shù)據(jù)。Middleware 可以是簡單的 Log 組件,亦可以為復雜的大型 Web Framework,諸如:ASP.NET Web API、Nancy、SignlR 等,如下圖所示:Pipeline 中的 Middleware 用來處理請求:

http://wiki.jikexueyuan.com/project/think-in-asp-net-mvc/images/Chapter7/3.png" alt="" />

4.)Application

最后一層即為 Application,是具體的代碼實現(xiàn),比如 ASP.NET Web API、SignalR 具體代碼的實現(xiàn)。

現(xiàn)在,我想你應該了解了什么事 Katana 以及 Katana 的基本原則和體系結構,那么現(xiàn)在就是具體應用到實際當中去了。

使用 ASP.NET/IIS 托管 Katana-based 應用程序

在 Startup 的 Configuration 方法中實現(xiàn) OWIN Pipeline 處理邏輯,如下代碼所示:

public class Startup
{
    public void Configuration(IAppBuilder app)

    {
        app.Run(context =>

        {

            context.Response.ContentType = "text/plain";

            return context.Response.WriteAsync("Hello World");

        });

    }

}

app.Run 方法將一個接受 IOwinContext 對象最為輸入?yún)?shù)并返回 Task 的 Lambda 表達式作為 OWIN Pipeline 的最后處理步驟,IOwinContext 強類型對象是對 Environment Dictionary 的封裝,然后異步輸出"Hello World"字符串。

細心的你可能觀察到,在 Nuget 安裝 Microsoft.Owin.Host.SystemWeb 程序集時,默認安裝了依賴項 Microsoft.Owin 程序集,正式它為我們提供了擴展方法 Run 和 IOwinContext 接口,當然我們也可以使用最原始的方式來輸出"Hello World"字符串,即 Owin 程序集為我們提供的最原始方式,這僅僅是學習上參考,雖然我們不會在正式場景下使用:

using AppFunc = Func<IDictionary<string, object>, Task>;

public class Startup

{

    public void Configuration(IAppBuilder app)

    {

        app.Use(new Func<AppFunc, AppFunc>(next => (env =>

        {

            string text = "Hello World";

            var response = env["owin.ResponseBody"] as Stream;

            var headers = env["owin.ResponseHeaders"] as IDictionary<string, string[]>;

            headers["Content-Type"] = new[] { "text/plain" };

            return response.WriteAsync(Encoding.UTF8.GetBytes(text), 0, text.Length);

        })));

    }

}

使用自定義 Host(self-host)托管 Katana-based 應用程序

使用自定義 Host 托管 Katana 應用程序與使用 IIS 托管差別不大,你可以使用控制臺、WinForm、WPF 等實現(xiàn)托管,但要記住,這會失去 IIS 帶有的一些功能(SSL、Event Log、Diagnostics、Management…),當然這可以自己來實現(xiàn)。

  • 創(chuàng)建控制臺應用程序*
  • Install-Package Microsoft.Owin.SelfHost
  • 在 Main 方法中使用 Startup 配置項構建 Pipeline 并監(jiān)聽端口

      using (WebApp.Start("http://localhost:10002"))  
      {
    
         System.Console.WriteLine("啟動站點:http://localhost:10002");
    
         System.Console.ReadLine();
    
      }

使用自定義的 Host 將失去 IIS 的一些功能,當然我們可以自己去實現(xiàn)。幸運的是,Katana 為我們默認實現(xiàn)了部分功能,比如 Diagnostic,包含在程序集 Microsoft.Owin.Diagnostic 中。

public void Configuration(IAppBuilder app)
{

    app.UseWelcomePage("/");

    app.UseErrorPage();

    app.Run(context =>
    {

        //將請求記錄在控制臺

        Trace.WriteLine(context.Request.Uri);

        //顯示錯誤頁

        if (context.Request.Path.ToString().Equals("/error"))

        {

            throw new Exception("拋出異常");

        }

        context.Response.ContentType = "text/plain";

        return context.Response.WriteAsync("Hello World");

    });

}

在上述代碼中,當請求的路徑(Request.Path)為根目錄時,渲染輸出 Webcome Page并且不繼續(xù)執(zhí)行 Pipeline 中的其余 Middleware 組件,如下所示:

http://wiki.jikexueyuan.com/project/think-in-asp-net-mvc/images/Chapter7/4.png" alt="" />

如果請求的路徑為 Error時,拋出異常,顯示錯誤頁,如下所示:

http://wiki.jikexueyuan.com/project/think-in-asp-net-mvc/images/Chapter7/5.png" alt="" />

使用 OwinHost.exe 托管 Katana-based 應用程序

當然我們還可以使用 Katana 提供的 OwinHost.exe 來托管應用程序,毫無疑問,通過 Nuget 來安裝 OwinHost。

如果你按照我的例子一步一步執(zhí)行的話,你會發(fā)現(xiàn)不管使用 ASP.NET/IIS 托管還是自托管,Startup 配置類都是不變的,改變的僅僅是托管方式。同理 OwinHost 也是一樣的,但它更靈活,我們可以使用類庫或者 Web 應用程序來作為 Application。

類庫作為 Application,可以最小的去引用程序集,創(chuàng)建一個類庫后,刪除默認的 Class1.cs,然后并且添加 Startup 啟動項,這會默認像類庫中添加 Owin 和 Microsoft.Owin 程序集的引用。

然后,使用 Nuget 來安裝 OwinHost.exe,如 Install-Package OwinHost,注意它并不是一個程序集,而是.exe 應用程序位于/packages/OwinHost.(version)/tools 文件夾。

因為類庫不能直接運行,那么只能在它的根目錄調(diào)用 OwinHost.exe 來托管,它將加載.bin 文件下所有的程序集,所以需要改變類庫的默認輸出,如下所示:

http://wiki.jikexueyuan.com/project/think-in-asp-net-mvc/images/Chapter7/6.png" alt="" />

然后編譯解決方案,打開 cmd,鍵入如下命令:

http://wiki.jikexueyuan.com/project/think-in-asp-net-mvc/images/Chapter7/7.png" alt="" />

如上圖成功啟動了宿主 Host 并且默認監(jiān)聽 5000 端口。

OwinHost.exe 還提供自定義參數(shù),通過追加-h 來查看,如下所示:

http://wiki.jikexueyuan.com/project/think-in-asp-net-mvc/images/Chapter7/8.png" alt="" />

既然類庫不能直接運行,當然你也不能直接進行調(diào)試,我們可以附加 OwinHost 進程來進行調(diào)試,如下所示:

http://wiki.jikexueyuan.com/project/think-in-asp-net-mvc/images/Chapter7/9.png" alt="" />

注:我在使用 OwinHost.exe 3.0.1 時,Startup 如果是如下情況下,它提示轉(zhuǎn)換失敗,不知是否是該版本的 Bug。

   using AppFunc = Func<idictionary<string, object="">, Task>;
   public class Startup  
   {  
       public void Configuration(IAppBuilder app)
       {

       //使用OwinHost.exe,報錯,提示轉(zhuǎn)換失敗

       app.Run(context=>context.Response.WriteAsync("Hello World"));

       //使用OwinHost.exe 不報錯

       //app.Use(new Func<appfunc, appfunc="">(next => (env =>

       //{

           // string text = "Hello World";

           // var response = env["owin.ResponseBody"] as Stream;

           // var headers = env["owin.ResponseHeaders"] as IDictionary<string, string[]="">;

           // headers["Content-Type"] = new[] { "text/plain" };

           // return response.WriteAsync(Encoding.UTF8.GetBytes(text), 0, text.Length);

       //})));

       }

   }

報錯信息如下:

http://wiki.jikexueyuan.com/project/think-in-asp-net-mvc/images/Chapter7/10.png" alt="" />

Web Application 比類庫使用起來輕松多了,你可以直接運行和調(diào)試,唯一比較弱的可能是它引用較多的程序集,你完全可以刪掉,比如 System.Web。

通過 Nuget 安裝了 OwinHost.exe 之后,可以在 Web 中使用它,如下所示:

http://wiki.jikexueyuan.com/project/think-in-asp-net-mvc/images/Chapter7/11.png" alt="" />

幾種指定啟動項 Startup 的方法

  • 默認名稱約束:默認情況下 Host 會去查找 root namespace 下的名為 Startup 的類作為啟動項。
  • OwinStartup Attribute:當創(chuàng)建 Owin Startup 類時,自動會加上 Attribute 如:[**assembly: OwinStartup(typeof(JKXY.KatanaDemo.OwinHost.Startup))]**
  • 配置文件,如:
  • 如果使用自定義 Host,那么可以通過 WebApp.Start("http://localhost:10002") 來設置啟動項。
  • 如果使用 OwinHost,那么可以通過命令行參數(shù)來實現(xiàn),如下截圖所示

http://wiki.jikexueyuan.com/project/think-in-asp-net-mvc/images/Chapter7/12.png" alt="" />

啟動項 Startup 的高級應用

啟動項 Startup 支持 Friendly Name,通過 Friendly Name 我們可以動態(tài)切換 Startup。

比如在部署時,我們會有 UAT 環(huán)境、Production 環(huán)境,在不同的環(huán)境中我們可以動態(tài)切換 Startup 來執(zhí)行不同的操作。

舉個例子,我創(chuàng)建來兩個帶有 Friendly Name 的 Startup,如下所示:

  [assembly: OwinStartup("Production", typeof(JKXY.KatanaDemo.Web.StartupProduction))]
  namespace JKXY.KatanaDemo.Web
  {
      using AppFunc = Func<idictionary<string, object="">, Task&gt;;
      public class StartupProduction
      {
          public void Configuration(IAppBuilder app)
          {
             app.Run(context=&gt;context.Response.WriteAsync("Production"));
         }
     }
 }

  [assembly: OwinStartup("UAT",typeof(JKXY.KatanaDemo.Web.StartupUAT))]

  namespace JKXY.KatanaDemo.Web
  {
      public class StartupUAT
      {
          public void Configuration(IAppBuilder app)
         {
             app.Run(context=&gt;context.Response.WriteAsync("UAT"));
         }
     }
 }

根據(jù) Friendly Name 使用配置文件或者 OwinHost 參數(shù)來切換 Startup

  <appsettings>
    <add key="owin:appStartup" value="Production">
  </add></appsettings>

小結

這篇博客為大家講解了 Katana 的世界,那么接下來我將繼續(xù) OWIN & Katana 之旅,探索 Middleware 的創(chuàng)建,謝謝大家支持。