ASP.NET開發規范:OWIN
今天投簡歷 准備面試了...
本節目錄:
OWIN(Open Web Interface For .Net)
OWIN是.Net開源社區借鑒Ruby而制定的.Net Web開發架構,有着非常簡單的規范定義,目標是用於解耦Web Server和Web Application.
ASP.NET的局限性
ASP.NET核心是System.Web,而System.Web緊耦合IIS.IIS綁定在Windows OS上,所以ASP.NET 無法跨平台.
System.Web是.NET Framework重要組成,所以System.Web更新需要等待.NET的發布
OWIN定義了4層:
2
Host:主要負責應用程序的配置和啟動進程,包括初始化OWIN Pipeline、運行Server。
Server:綁定套接字並監聽的HTTP請求然后將Request和Response的Body、Header封裝成符合OWIN規范的字典並發送到OWIN Middleware Pipeline中
Middleware:稱之為中間件、組件,位於Server與Application之間,用來處理發送到Pipeline中的請求
Application:這是具體的應用程序代碼,只不過我們將他們注冊到OWIN Pipeline中去處理HTTP 請求,成為OWIN管道的一部分
OWIN接口
Func<IDictionary<string, object>, Task>;
用於Server和Middleware的交互。他並不是嚴格意義上的接口,而是一個委托並且每個OWIN中間件組件必須提供。
其中參數類型為IDictionary<string,object>的變量為環境變量
微軟引入並推廣OWIN,同時依照OWIN規范,實現了Katana。
Host
宿主只是一個進程,是整個OWIN程序的載體。這個宿主可以是IIS, IIS Express, Console, Windows Service等。
Katana為我們提供了3中選擇:
- IIS / ASP.NET :使用IIS是最簡單和向后兼容方式,在這種場景中OWIN Pipeline通過標准的HttpModule和HttpHandler啟動。使用此Host你必須使用System.Web作為OWIN Server
 - Self-Host :如果你想要使用其他Server來替換掉System.Web,並且可以有更多的控制權,可以選擇創建一個自定義宿主,如使用Windows Service、控制台應用程序、Winform來承載Server
 - OwinHost :也可以使用Katana提供的OwinHost.exe:他是一個命令行應用程序,運行在項目的根部,啟動HttpListener Server並找到基於約束的Startup啟動項
 
Server
負責綁定到 TCP 端口,監聽端口發送過來的請求,同時將請求的信息依照OWIN規范,包裝成字典格式,傳遞到下層的Middleware
Katana對OWIN Server的實現分為如下幾類:
- System.Web:當使用IIS作為Host時,System.Web把自己注冊為HttpModule和HttpHandler並且處理發送給IIS的請求(Microsoft.Owin.Host.SystemWeb)
 - HttpListener:這是OwinHost.exe和自定義Host默認的Server。(Microsoft.Owin.Host.HttpListener)
 - WebListener:這是ASP.NET vNext默認的輕量級Server,他目前無法使用在Katana中
 
Middleware
這是為組成 OWIN 管道中的組件。
Middleware可以理解為提供Func<IDictionary<string, object>, Task>接口的組件。
Katana提供了一個OwinMiddleware基類更加方便我們繼承來實現OWIN Middleware.
Application
具體的代碼實現,比如ASP.NET Web API、SignalR具體代碼的實現。
事實上,對於這些類型的應用程序,Katana 組件只需使用一個小的配置類即可見。
IIS-Host
新建一個空的Web項目,Nuget引用Microsoft.Owin.Host.SystemWeb
創建Startup類
|  
                 
                  1 
                  
                
                  2 
                  
                
                  3 
                  
                
                  4 
                  
                
                  5 
                  
                
                  6 
                  
                
                  7 
                  
                
                  8 
                  
                
                  9 
                  
                
                  10 
                  
                
                  11 
                   |  
                
                public  
                  class  
                  Startup 
                 { 
                      
                  public  
                  void  
                  Configuration(IAppBuilder app) 
                      
                  { 
                          
                  app.Run(context => 
                          
                  { 
                              
                  context.Response.ContentType =  
                  "text/plain" 
                  ; 
                              
                  return  
                  context.Response.WriteAsync( 
                  "Hello World!" 
                  ); 
                          
                  }); 
                      
                  } 
                 } 
                  |  
              
訪問項目地址:http://localhost:xx
Self-Host
新建控制台項目,Nuget引用Microsoft.Owin.SelfHost
Main方法
|  
                 
                  1 
                  
                
                  2 
                  
                
                  3 
                  
                
                  4 
                   |  
               
創建Startup類
|  
                 
                  1 
                  
                
                  2 
                  
                
                  3 
                  
                
                  4 
                  
                
                  5 
                  
                
                  6 
                  
                
                  7 
                  
                
                  8 
                  
                
                  9 
                  
                
                  10 
                  
                
                  11 
                  
                
                  12 
                  
                
                  13 
                   |  
                
                     
                  class  
                  Startup 
                      
                  { 
                          
                  public  
                  void  
                  Configuration(IAppBuilder app) 
                          
                  { 
                 #if DEBUG 
                              
                  //診斷 
                              
                  app.UseErrorPage(); 
                 #endif 
                              
                  //歡迎頁 
                              
                  //app.UseWelcomePage("/"); 
                              
                  app.Run(x=>x.Response.WriteAsync( 
                  "hello world" 
                  )); 
                          
                  } 
                      
                  } 
                  |  
              
訪問地址:http://localhost:12345
OWIN-Host
新建類庫項目,Nuget引用OwinHost
創建Startup類(需要程序集Owin和Microsoft.Owin)
|  
                 
                  1 
                  
                
                  2 
                  
                
                  3 
                  
                
                  4 
                  
                
                  5 
                  
                
                  6 
                  
                
                  7 
                  
                
                  8 
                  
                
                  9 
                  
                
                  10 
                  
                
                  11 
                   |  
                
                public  
                  class  
                  Startup 
                 { 
                      
                  public  
                  void  
                  Configuration(IAppBuilder app) 
                      
                  { 
                          
                  app.Run(context => 
                          
                  { 
                              
                  context.Response.ContentType =  
                  "text/plain" 
                  ; 
                              
                  return  
                  context.Response.WriteAsync( 
                  "Hello World!" 
                  ); 
                          
                  }); 
                      
                  } 
                 } 
                  |  
              
OwinHost.exe
這里需要注意
- Nuget下載完,OwinHost.exe會在package文件夾里
 - OwinHost.exe會加載./bin文件夾下的程序集作為server assembly
 
所以我們將這OwinHost.exe3個文件移動到
=>
另外將Debug或者Release文件夾下的文件移動到bin文件夾下

cmd運行OwinHost.exe

訪問:http://localhost:5000/
Middleware非常類似於HttpModule,會注冊到Owin的pipeline中執行代碼.
繼承OwinMiddleware
|  
                 
                  1 
                  
                
                  2 
                  
                
                  3 
                  
                
                  4 
                  
                
                  5 
                  
                
                  6 
                  
                
                  7 
                  
                
                  8 
                  
                
                  9 
                  
                
                  10 
                  
                
                  11 
                  
                
                  12 
                  
                
                  13 
                   |  
                
                public  
                  class  
                  HelloMiddlerware : OwinMiddleware 
                 { 
                      
                  public  
                  HelloMiddlerware(OwinMiddleware next) 
                          
                  :  
                  base 
                  (next) 
                      
                  { 
                      
                  } 
                      
                  public  
                  override  
                  Task Invoke(IOwinContext context) 
                      
                  { 
                          
                  context.Response.Write( 
                  "hello" 
                  +DateTime.Now);<br>         
                  //管道繼續往下走 
                          
                  return  
                  Next.Invoke(context); 
                      
                  } 
                 } 
                  |  
              
Startup
|  
                 
                  1 
                  
                
                  2 
                  
                
                  3 
                  
                
                  4 
                  
                
                  5 
                  
                
                  6 
                  
                
                  7 
                  
                
                  8 
                  
                
                  9 
                  
                
                  10 
                  
                
                  11 
                  
                
                  12 
                  
                
                  13 
                   |  
                
                public  
                  class  
                  Startup 
                 { 
                      
                  public  
                  void  
                  Configuration(IAppBuilder app) 
                      
                  { 
                          
                  // 有關如何配置應用程序的詳細信息,請訪問 http://go.microsoft.com/fwlink/?LinkID=316888 
                          
                  //管線自由組合 
                          
                  app.Use<HelloMiddlerware>(); 
                          
                  //Run是插入一個中間件,並終止繼續往下流 
                          
                  app.Run(x => x.Response.WriteAsync( 
                  "good" 
                  )); 
                          
                  //此中間件將不執行 
                          
                  app.Use<HelloMiddlerware>(); 
                      
                  } 
                 } 
                  |  
              
來看一下組件的執行順序
|  
                 
                  1 
                  
                
                  2 
                  
                
                  3 
                  
                
                  4 
                  
                
                  5 
                  
                
                  6 
                  
                
                  7 
                  
                
                  8 
                  
                
                  9 
                  
                
                  10 
                  
                
                  11 
                  
                
                  12 
                  
                
                  13 
                  
                
                  14 
                  
                
                  15 
                  
                
                  16 
                  
                
                  17 
                  
                
                  18 
                  
                
                  19 
                  
                
                  20 
                  
                
                  21 
                  
                
                  22 
                  
                
                  23 
                  
                
                  24 
                   |  
                
                public  
                  class  
                  Startup 
                 { 
                      
                  public  
                  void  
                  Configuration(IAppBuilder app) 
                      
                  { 
                          
                  app.Use((x, next) => 
                          
                  { 
                              
                  x.Response.ContentType =  
                  "text/html" 
                  ; 
                              
                  return  
                  next.Invoke(); 
                          
                  }); 
                          
                  app.Use((x, next) => 
                          
                  { 
                              
                  x.Response.WriteAsync( 
                  "1 Before" 
                  ); 
                              
                  next.Invoke(); 
                              
                  return  
                  x.Response.WriteAsync( 
                  "1 After" 
                  ); 
                          
                  }); 
                          
                  app.Use((x, next) => 
                          
                  { 
                              
                  x.Response.WriteAsync( 
                  "2 Before" 
                  ); 
                              
                  next.Invoke(); 
                              
                  return  
                  x.Response.WriteAsync( 
                  "2 After" 
                  ); 
                          
                  }); 
                          
                  app.Run(x => x.Response.WriteAsync( 
                  "<br/>hello world<br/>" 
                  )); 
                      
                  } 
                 } 
                  |  
              
瀏覽結果:

擴展
Startup類如何被關聯
1.默認名稱匹配
可以定義Startup.cs類,只要這個類的namespace和Assembly的名稱相同。那么,這個Startup.cs中的Configuration方法,就會在OWIN管道初始化的時候執行。
2.使用OwinStartup Attribute
這就是我們例子中使用的方式,直接指定哪個具體類是Startup類。
3.在配置文件的appSetting 節點設置
|  
                 
                  1 
                  
                
                  2 
                  
                
                  3 
                   |  
                
                <appSettings>  
                    
                  <add key= 
                  "owin:appStartup"  
                  value= 
                  "StartupDemo.ProductionStartup"  
                  /> 
                 </appSettings> 
                  |  
              
Pipeline
Owin的pipeline在IIS Host上本質是注冊到Httpapplication的pipeline上.
如:app.UseStageMarker(PipelineStage.Authenticate);
本文參考:
http://www.cnblogs.com/JustRun1983/p/3955238.html
Katana:http://www.asp.net/aspnet/overview/owin-and-katana/an-overview-of-project-katana
