與 COM 有關的變化
隨著 .NET 框架和 asp .NET 的誕生,COM 實際上沒有發生任何變化。但這並不表示在 ASP .Net 中使用 COM 對象時不必擔心和考慮他們的行為。有一些基本情況,您必須了解。
線程模式的變化
ASP .NET 線程模式是多線程單元 (MTA)。這就意味著,對於目前使用的為單線程單元 (STA) 創建的組件,如果不采取額外的措施,將不能在 ASP .Net 中可靠地執行或運行。其中包括但不限於使用 Visual Basic 6.0 及其更低版本創建的所有 COM 組件。
ASPCOMPAT 屬性
您將很高興聽到這樣一個消息:仍然可以使用這些 STA 組件,而不需要更改任何代碼。您需要做的工作只是在 ASP .Net 網頁的 <%@Page> 標記中包含兼容性屬性 ASPcompat=true,如 <%@Page ASPcompat=true Language=VB%>。使用此屬性將強制網頁以 STA 模式執行,從而確保您的組件可以繼續正確運行。如果試圖使用 STA 組件但沒有指定此標記,運行時將會發生異常情況。
將此屬性的值設置為 true 時,將允許網頁調用 COM+ 1.0 組件,該組件需要訪問非管理的 ASP 內置對象。可以通過 ObjectContext 對象進行訪問。
如果將此標記的值設為 true,性能會稍微有些下降。建議只在確實需要時才這樣做。
早期綁定與後期綁定
在 ASP 中,對 COM 對象的所有調用都是通過 IDispatch 接口進行的。這種行為被稱為“後期綁定”,因為對實際對象的調用是在運行時通過 IDispatch 間接處理的。在 ASP .Net 中,只要您願意,可以繼續以這種方式調用您的組件。
Dim Obj As Object
Obj = Server.CreateObject("PRogID")
Obj.MyMethodCall
仍然可以使用這種方式訪問您的組件,但這不是首選方式。現在,在 ASP .Net 中,您可以利用早期綁定直接創建對象,如下所示:
Dim Obj As New MyObject
MyObject.MyMethodCall()
使用早期綁定,可以通過類型安全的方式與組件交互。為了在 COM 組件中使用早期綁定,您需要像在 Visual Basic 6.0 項目中添加 COM 引用一樣,在項目中添加一個引用。假設您正在使用 Visual Studio .NET,將在 COM 組件之上後台創建一個管理的代理對象,給您的感覺就好像是直接在處理一個 .Net 組件,而不是 COM 組件。
現在,您可能會擔心性能問題。由於代理對象而引入了一個額外的層,所以使用 COM 協同操作時確實會存在一些問題。但是,大多數情況下,應該不會遇到什麼問題,因為進行協同操作的實際 CPU 指令數仍然遠遠小於間接 IDispatch 調用的要求。您所得到的將遠遠超出您所失去的。當然,理想情況是使用最新創建的管理對象,但我們知道,由於我們在 COM 組件上的投入所限,並不總是能夠立即做到這一點。
OnStartPage 和 OnEndPage 方法
需要特別注意的是對舊版 OnStartPage 和 OnEndPage 方法的使用。如果您依賴於這些方法訪問 ASP 固有對象,將需要使用 ASPCOMPAT 指令和 Server.CreateObject 以早期綁定方式創建組件,如下所示:
Dim Obj As MyObj
Obj = Server.CreateObject(MyObj)
Obj.MyMethodCall()
注意,我們並沒有使用“ProgID”,而是以早期綁定方式使用實際類型。為了讓這種方式有效,您需要在 Visual Studio 項目中添加 COM 組件引用,這樣才能創建早期綁定的包裝類。這是唯一必須繼續使用 Server.CreateObject 的情況。
COM 總結
表 2 總結了為繼續有效使用 COM 組件而必須完成的一些工作。
表 2:舊版 COM 對象的 ASP .Net 設置
COM 組件類型/方法 ASP .Net 設置/過程
自定義 STA(標記為“Apartment”的 Visual Basic 組件或其它組件) 使用 ASPCOMPAT 和早期綁定
自定義 MTA(標記為“Both”或“Free”的 ATL 或自定義 COM 組件) 不使用 ASPCOMPAT,使用早期綁定
固有對象(通過 ObjectContext 訪問) 使用 ASPCOMPAT 和早期綁定
OnStartPage 和 OnEndPage 使用 ASPCOMPAT 和 Server.CreateObject(Type)
無論您的組件是否部署在 COM+ 中,都將同樣應用這些設置。
應用程序配置的變化
在 ASP 中,所有 Web 應用程序配置信息都存儲在系統注冊表和 IIS 配置數據庫中。由於服務器上經常未安裝適當的管理工具,使得查看或修改設置變得非常困難。ASP .NET 引入了一整套全新的配置模型,這套模型以簡單的、易讀的 XML 文件為基礎。每個 ASP .Net 應用程序都有自己的 Web.Config 文件,該文件位於主應用程序目錄中。可以通過此文件控制 Web 應用程序的自定義配置、行為和安全性。
如果您與我一樣,您可能會通過“Internet 服務管理器”管理單元檢查和更改 ASP .NET 應用程序的設置。但是,您必須了解,現在我們擁有兩種完全不同的配置模型。除一些安全性設置外,ASP .Net 應用程序將忽略使用 IIS 管理工具配置的其它大部分設置。您需要將這些配置設置保存在 Web.Config 文件中。
有關 .Net 的應用程序配置將在另一篇文章中詳細討論,此處就不詳細介紹了。表 3 說明了可以在自己的文件中配置的一些更有意義的設置。記住,還有更多設置。
表 3:Web.Config 設置示例
設置 說明
<aPPSettings>
配置自定義應用程序設置。
<authentication>
配置 ASP .Net 身份驗證支持。
<pages>
標識網頁特定的配置設置。
<processModel>
配置 IIS 系統中的 ASP .Net 進程模型設置。
<sessionState>
指定會話狀態選項。
在 .Net 基本類庫中還有其它一些類可用,它們簡化了對這些設置的編程訪問。
狀態管理
如果應用程序使用 Session 或 application 固有對象存儲狀態信息,則在 ASP .Net 中可以繼續使用這些對象,而不會出現任何問題。隨之帶來的好處是,現在提供了更多的狀態存儲位置選項。
狀態管理選項
ASP .Net 中還包含其它一些狀態管理模型選項,最終可使您管理不止一個 Web 服務器,並支持通過 Web 場進行狀態管理。
可以在 web.config 文件的 <sessionState> 一節中配置狀態管理選項,如下所示:
<sessionState
mode="Inproc"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=127.0.0.1;user id=sa;passWord=" cookIEless="false"
timeout="20"
/>
模式屬性指定將在何處存儲狀態信息。可用選項有 Inproc、StateServer、SqlServer 或 Off。
表 4:會話狀態存儲信息
選項 說明
Inproc 會話狀態本地存儲在此服務器中(ASP 樣式)。
StateServer 會話狀態遠程(或本地)存儲在狀態服務進程中。
SqlServer 會話狀態存儲在 SQL Server 數據庫中。
Off 會話狀態被禁用。
如果使用這些選項之一,StateConnectionString 和 sqlConnectionString 無疑將成為至關重要的參數。每個應用程序只能使用一個存儲選項。
存儲 COM 組件
需記住的的一點是,如果您依賴於對 Session 或 Application 對象中舊版 COM 組件的存儲引用,將無法在應用程序中使用新的狀態存儲機制(StateServer 或 SqlServer)。您將需要使用 Inproc。部分原因是對象需要在 .Net 中實現自我串行,很顯然,COM 組件無法做到這一點。另一方面,新創建的管理組件可以相對輕松地實現這一點,因此可以使用新的狀態存儲模式。
性能
當然,就性能而言,每前進一步都將付出相應的代價。但您完全可以相信,大多數情況下,使用 Inproc 依然是最佳選擇,其後依次是 StateServer 和 SqlServer。您自己應該對應用程序進行測試,確保選定的選項可以達到您的性能目標。
ASP 和 ASP .Net 之間的共享狀態
需要考慮的另外一個重要問題是,雖然應用程序可以同時包含 ASP 和 ASP .Net 網頁,但您無法共享固有 Session 或 Application 對象中存儲的狀態變量。可能需要將這些信息復制到這兩個系統中或提出其它自定義解決方案,才能完全遷移您的應用程序。最好的情況是您未使用 Session 和 Application 對象。另一方面,如果您大量使用了這些對象,您需要一直小心謹慎,或許可以提出某種自定義的短期解決方案來共享狀態。
與安全性有關的變化
安全性是需要特別注意的另一個重要問題。下面簡要介紹了 ASP .NET 安全性系統。有關安全性問題更完整的研究,請參見 ASP .Net 安全性文檔。
ASP .NET 安全性主要受 web.config 文件中安全性部分的設置控制。ASP .NET 與 IIS 協同工作,為您的應用程序提供完善的完全性模型。IIS 安全性設置是實際攜帶並應用於 ASP .NET 應用程序的少數幾個應用程序設置,其攜帶和應用方式與在 ASP .Net 中相似。當然,在很多方面都得到了改進。
身份驗證
對於身份驗證,ASP .Net 支持表 5 中所示的選項。
表 5:ASP .Net 身份驗證選項
類型 說明
Windows ASP .Net 使用 Windows 身份驗證。
Forms 基於 CookIE 的自定義登錄表單。
Passport 非 Microsoft 提供的 Passport Service。
None 不執行身份驗證。
除新增加的 Passport 身份驗證選項之外,其它選項都與 ASP 中的選項相同。例如,下列配置對應用程序啟用基於 Windows 的身份驗證。
<configuration>
<system.web>
<authentication mode="Windows"/>
</system.web>
</configuration>
授權
用戶通過身份驗證後,將集中考慮允許他們訪問哪些資源。在下例中,授予了“jkIEley”和“JStegman”訪問權限,而其他所有人都被拒絕訪問。
<authorization>
<allow users="NORTHAMERICA\jkIEley, REDMOND\JStegman"/>
<deny users="*"/>
</authorization>
模擬
做為刷新程序,模擬是指這樣一個過程:對象以它所代表的實體的標識執行代碼。在 ASP 中,模擬允許您的代碼代表通過身份驗證的用戶運行。或者,用戶也可以通過特定標識匿名運行。默認情況下,ASP .Net 不會針對每個請求進行模擬。這一點與 ASP 不同。如果您依賴於這種功能,則需要在 web.config 文件中啟用它,如下所示:
<identity>
<impersonation enable = "true"/>
</identity>
數據訪問
遷移過程中,需要重點考慮的另一個關鍵問題是數據訪問。隨著 ADO .NET 的誕生,現在您具有了一種訪問數據的強有力的全新方法。由於數據訪問本身就是一個很大的主題,本文就不詳細討論了。大多數情況下,您可以像過去一樣繼續使用 ADO,但是我極力推薦您了解一下 ADO .NET,並通過它改善 ASP .Net 應用程序中的數據訪問方法。
准備向 ASP .Net 遷移
現在您已了解了可能會遇到的大多數問題,您可能會想:目前我需要做好哪些准備工作以備將來最終遷移到 ASP .NET 呢?目前確實需要完成幾項工作,以確保將來的遷移過程順利進行。其中的許多建議對您的 ASP 代碼大有益處,即使目前不打算向 ASP .Net 遷移。
使用 Option Explicit
這始終是一個不錯的建議,但至今仍然有許多人沒有使用它。通過使用 Option Explicit,強制在 ASP 中聲明變量,您至少可以控制在何處定義每個對象以及如何使用變量。遷移到 ASP .NET 之後,我建議使用 Option Strict。在 Visual Basic .Net 中,默認使用 Option Explicit,但是使用更具強制性的 Option Strict,可以確保所有變量都聲明為正確的數據類型。這樣做確實需要增加一些額外的工作,但從長期考慮,您將發現還是很值得這樣做的。
避免使用默認屬性
我們前面已討論過,不再允許使用默認屬性。顯式訪問屬性並不是什麼難事。它將增強代碼的可讀性,而且可以在將來節省您的時間。
使用括號和 Call 關鍵字
正如本文前面詳細討論過的,應盡可能使用括號和 Call 語句。在 ASP .Net 中,將強制使用括號。現在使用 Call 語句有助於您熟悉一些規則,為將來的工作打好基礎。
避免嵌套的包含文件
這一點可能說起來容易做起來難,但還是應盡可能避免嵌套包含文件。我的意思是說,應該努力避免在包含文件中包括其它包含文件。隨著時間的推移,可能會碰到的一種情況是,您的代碼不再依賴於在其它某處的包含文件中定義的全局變量,您需要訪問的原因僅僅是因為其中嵌套了包含您真正需要的全局變量的另一個文件。
向 ASP .Net 遷移時,您很有可能會將全局變量和程序遷移到類庫中,這種情況下,如果您清楚地了解每個對象的訪問位置,遷移起來就很容易。您不需要將一些對象移來移去,也不需要更改多個文件中相同的那些程序名稱。
將實用函數合並到單個文件中
遷移過程中的一個策略是將服務器端包含文件中包含的所有實用函數和代碼遷移到 Visual Basic 或 C# 類庫中。這樣,您最終可以將所有代碼放到所屬對象中,這一點與多解釋的 ASP 文件不同。提前組織好代碼,可以節省將來的遷移時間。理論上講,您應該可以將子程序組合到邏輯文件中,從而使您可以輕松地創建一組 VB 或 C# 類。這些函數可能應位於 COM 對象中。
如果服務器端包含文件中存在一大堆全局變量或常量,也最好考慮將他們組合到單個文件中。一旦遷移到 ASP .Net 後,您就可以輕松創建一個類來存放全局或常量數據。這將使系統更干淨、更易維護。
盡可能將代碼與內容分開
這又是一件說起來比做起來容易的工作,但是您應該盡量將代碼與 Html 內容分開。清理一下主體中即有代碼、又有腳本的那些函數。這樣做使您處於非常有利的位置,可以充分利用代碼--無論怎麼說,這是 ASP .Net 中的最佳模式。
不要在 <% %> 塊聲明函數
ASP .Net 不支持在 <% %> 塊聲明函數。應該在 <script> 塊進行聲明。有關此技術的示例,請參閱本文前面的結構變化一節。
避免使用生成函數
如前所述,應該盡量避免使用“生成函數”。如果現在可以更改或准備代碼,應在構造這類函數時使用 Response.Write 塊。
顯式釋放資源(調用 Close 方法)
確保對使用的對象和資源中存在的 close() 或清理方法進行顯式調用。我們都知道,Visual Basic 和 VBScript 在清理方面的容錯能力很強。通常情況下,他們能夠立即清理對象。但遷移到 .Net 後,您將無法准確掌握對象何時會被清理,就像您無法確定垃圾堆中的垃圾何時會被清理一樣。如果您能夠顯式清理和釋放資源,最好顯式地進行清理和釋放。
避免混用語言
應該盡量避免在同一網頁中混用服務器端 VBScript 和 JScript。一般而言,這是一種不太明智的編程方式。而且向 ASP .Net 遷移時還會存在問題,因為由於采用了新的編譯模式,每個網頁只要求一種內嵌 <% %> 語言。但仍然可以使用過去的方式生成客戶端腳本。
總結
正如我們已經了解的,在向 ASP .Net 遷移應用程序之前,有許多問題需要考慮。我在此文中歸納了遷移前後會發生的大多數變化,這應該能使您的遷移過程變得相對簡單一些。
如果您擁有一個大型站點,完成此進程之後,您可能會對遇到並修正了如此多的死代碼、無效代碼以及所有 Bug 而驚奇不已。另外,通常您還可以充分利用 ASP .NET 和 .Net 平台中大量強大的新增功能。
Jim KIEley 是 Microsoft Consulting Services 的高級顧問。從 .NET 發展初期,Jim 就一直與 Visual Studio 組密切合作,而且他還是早期創建 ASP .NET 和 .Net 框架應用程序的用戶之一。