早在
年
月和
月發行的 MSDN Magazine 中
我講述了如何構建 ASP 應用程序的客戶端環境
也就是運行 ASP 網頁的無服務器環境(參見 前沿技術
A Client
side Environment for ASP Pages 和 前沿技術
A Client
side Environment for ASP Pages art
)
這些專欄的靈感源自下面的情況
假設您的一個客戶需要利用一張 CD 來在線發布某些內容
例如
百科全書
黃頁或文檔集
客戶需要在 CD 內包含一個查看器應用程序和一種靈活的軟件體系結構來傳送內容
另外
除了有處理器最低性能和使用最新版本的 Windows 要求外
客戶希望 CD 沒有什麼特殊的系統要求
從而方便用戶使用
這意味著最終的應用程序不應依賴於國內版本 Windows 中包括的 Microsoft Internet 信息服務 (IIS) 或個人 Web 服務器
它應在純粹的
無服務器的環境下離線運行
在很多情況下
客戶有現成的在線內容 Web 站點
在其它情況下
作為項目的一部分
她計劃為在線內容創建 Web 站點
在這種情況下
利用 ASP 或 ADO
NET 來做這項工作是很明智的選擇
因為它們非常靈活並且功能強大
可使您快速
有效地構建查看器應用程序
但是自定義應用中果真能夠宿主 ASP 或 ADO
NET 嗎?
大約三年前當我第一次探討這個問題時
ADO
NET 還沒有發布
只是謠傳有一種暫定被稱為 ASP+ 的東西
這種東西很炫
並且不久即將發行
那時
沒有可用來在 IIS 之外以離線方式呈現 ASP 頁的工具
更糟糕的是
設計 ASP 並不能輕松地完成這樣的宿主操作
因此我提出一種由兩部分構成的 ASP 模擬器
一種專用的浏覽器以及一個 ASP 服務器模塊
構建的浏覽器用來截取任何形式的提交與 URL 請求
並且將它們重定向到我自己的 ASP 服務器模塊
反過來
ASP 服務器將從磁盤加載資源
解析其內容
從而動態生成 HTML 代碼
該浏覽器還負責利用與各種響應
請求和服務器 ASP 對象幾乎完全相同的編程接口來實例化與初始化偽對象
圖
概括了總體體系結構
雖然不是理想的解決方案
但它還是滿足了客戶的期待
並整合成一種較大型的產品
今天仍然能夠使很多專業人士使用在線和離線的內容
根據從這些專欄發布起我獲得的反饋信息可以判斷出
很多開發人員都面臨過類似的挑戰
幾個月後
Microsoft 發布了第一個 beta 版的 ADO
NET
我思考著利用該新產品重新訪問我的解決方案
ADO
NET 的設計是模塊化的
所以很適合於宿主在外部應用中
包括 IIS 自身
但是
能夠在自定義應用程序中宿主 ADO
NET 並不等於構建了一種由 CD 提供的離線 Web 浏覽器的現成解決方案
在自定義應用程序中宿主 ADO
NET 運行庫引擎僅是離線提供動態內容的第一步
如果看看圖
中所示的體系結構您就會發現
它基於兩個不同的組件 — 一個還接受用戶輸入的請求處理器和一個生成實際 HTML 代碼的 ASP 源處理器
宿主 ADO
NET 引擎只是取代了圖
中的 ASP 服務器模塊
實際上
您需要更多的東西 — 在理想情況下
需要的是一個浏覽器和一個嵌入的 Web 服務器
ADO
NET Cassini 示例 Web 服務器(參/Projects/Cassini/Download)是一種可以集成
部署解決方案的壓縮
本地 Web 服務器
Cassini 采用 ADO
NET 宿主 API(System
Web
Hosting 命名空間)來創建簡單的托管 Web 服務器
套接字連接是通過 System
Net API 來處理的
可從 Microsoft 獲得 Cassini 的源代碼
圖
顯示了基於 Cassini 的離線 Web 應用程序的典型體系結構
您可以看到
整個方案就像是一種基於 Internet 的典型 Web 應用程序
但是更為簡單
很顯然
Cassini 既不是 IIS 的完全代替物
也不是 Microsoft 版的開放源代碼 Web 服務器
Cassini 是本地的 Web 服務器
用來處理對本地文件夾的本地調用
我將回顧一下 Cassini 組件
然後為您說明如何在 CD 上部署 Web 站點
並以此作為結束
宿主 ADONET 運行庫 ADO
NET 應用程序並不要求將 IIS 作為主機模塊
事實上
ADO
NET 甚至不要求用 Web 服務器來運行
它公開了一個任何調用方都能使用的盡人皆知的接口
連接並要求內部的 HTTP 管道處理請求
宿主 ADO
NET 引擎時
兩個類起著重要的作用 — ttpRuntime 和 ApplicationHost
前者是對象的管道的入口點
它更像一條裝配鏈
可以將
aspx 資源的原始 HTTP 請求轉變為全新的 HTML 文本
後者使得客戶端應用程序宿主 ADO
NET 引擎成為可能
ApplicationHost 類負責創建主機進程中的 AppDomain
該進程將處理新應用程序的所有傳入請求
Tim Ewald 和 Keith Brown 在他們的文章
HTTP Pipelines: Securely Implement Processing
Filtering
and Content Redirection with HTTP Pipelines in ADO
NET
(MSDN 雜志
年
月刊)中全面講述了 HttpRuntime 類的內部組成
只在應用程序主機收到並預處理請求時
才使用 HttpRuntime 類
應用程序主機將所有請求信息打包到一個請求類中
該請求類派生於 HttpWorkerRequest 抽象類
或更可能派生於其名為 SimpleWorkerRequest 的標准實現類
在准備好使用請求類實例後
主機將處理權移交給 HttpRuntime
調用其 ProcessRequest 靜態方法
如下列代碼所示
SimpleWorkerRequest req;
req = new SimpleWorkerRequest(aspx
null
Console
Out);
HttpRuntime
ProcessRequest(req);
前面的代碼片斷顯示了啟動對 ADO
NET 網頁進行處理的核心代碼
該代碼的執行由通過 ApplicationHost 創建的主機類的某個特殊方法來控制
稍後我將回到該主題
現在
絕對可以說
SimpleWorkerRequest 的構造函數根據 ASPX 資源的虛擬路徑進行處理
采用一個可選的查詢字符串
並采用文本編寫器對象作為輸出
您可以使用流編寫器對象(而不是標准輸出控制台)將 HTML 代碼保存到磁盤
ApplicationHost 類 主機和 ADO
NET HTTP 運行庫之間的交互是由名為 ApplicationHost 的特定 Microsoft
NET Framework 類來控制的
從 ADO
NET HTTP 運行庫的角度來看
主機只是調用方 — 即創建了當前的 AppDomain 並且通過調用 ProcessRequest 方法為特定的請求提供服務的模塊
ADO
NET HTTP 運行庫和主機之間的接口都由 ApplicationHost 類的操作來完成
HTTP 運行庫全然沒有調用方的特性 — 而完全是一個像 IIS 一樣的 Web 服務器
一個像 Cassini 一樣的的本地 Web 服務器
或者甚至就是一個片刻就可以創建的簡單應用程序
ADO
NET 可以為調用 HttpRuntimeProcessRequest 並傳遞正確信息的任何模塊提供服務
圖
說明了 ADO
NET HTTP 運行庫和其它部分的關系
將 ADO
NET 宿主在應用程序中的第一步就是創建新的應用程序主機
這可以通過調用 ApplicationHost 類的 CreateApplicationHost 靜態方法來完成
CreateApplicationHost 在調用方進程中創建新的 AppDomain
之所以需要新的 AppDomain 是因為 ADO
NET 要依靠一些設置
這些設置只能在 AppDomain 級進行設置
並且某些設置只能在創建 AppDomain 之前進行
這些設置的一部分是投影復制緩存位置的應用程序基本路徑和目錄
CreateApplicationHost 需要一個虛擬文件夾才能工作
這意味著在第一次訪問某個新的虛擬文件夾時就會創建一個新主機並隨後創建新的 AppDomain
(注意像 Cassini 這樣的簡單 Web 服務器一次只需要一個虛擬文件夾
但這只是一種特殊情況
)
在創建主機接口對象後
典型的主機應用程序就開始監聽請求
如果主機的工作方式與 Web 服務器的相同
它就要通過端口
開始監聽傳入的消息
否則它可以是您指定的任何端口
然後將請求打包到請求類中
並傳遞給 ADO
NET 運行庫
HttpRuntime
ProcessRequest 方法通過對象的管道路由 Request 對象
在通道末端會出現一個新對象 — 就是動態創建類的一個實例
該類是 Page 類的繼承類
該實例表示被請求的
aspx 頁
要結束該請求
HTTP 運行庫要調用 Page 類的ProcessRequest 方法
該頁的 ProcessRequest 方法執行 Page 對象的大量任務
每項任務都以事件作為信號
通過利用 runat=server 屬性集來為該頁的每個組成元素創建服務器控件實例
對該頁進行首次初始化
接著
ADO
NET 代碼加載該頁的視圖狀態
並將它與發送的數據(如文本框和復選框的值)合並
最後
運行庫執行客戶請求的任何服務器代碼(大部分為回發事件)
保存視圖狀態
並將 HTML 寫到輸出編寫器中
CreateApplicationHost 靜態方法是 ApplicationHost 類的唯一成員
它的 C# 原型如下所示
public static object CreateApplicationHost(
Type hostType
string virtualDir
string physicalDir
);
以上代碼片斷所示的 virtualDir 參數表示所創建的應用域的虛擬目錄
而 physicalDir 參數表示此虛擬路徑後的文件系統路徑 — 被請求的
aspx 文件必須從該磁盤文件夾為該 Web 應用程序進行加載
這些信息都與域相關
並由 ADO
NET 工廠對象用來創建 HttpApplication 對象 (global
asax) 和網頁對象 (
aspx)
CreateApplicationHost 的第一個參數是類型對象
它的賦值是應用程序定義的主機類的類型
這種方法返回用戶提供的類的實例
該類用來連接主機程序的默認 AppDomain 和新近創建的 AppDomain(參見圖
)
主機類型對象是類似服務器應用程序的核心代碼和目標 AppDomain(CreateApplicationHost 先前創建)中 ADO
NET HTTP 運行庫之間的一種代理
From:http://tw.wingwit.com/Article/program/net/201311/13529.html