直播中
線程模式的變化
ASP .NET 線程模式是多線程單元 (MTA)。這就意味著,對(duì)于目前使用的為單線程單元 (STA) 創(chuàng)建的組件,如果不采取額外的措施,將不能在 ASP .NET 中可靠地執(zhí)行或運(yùn)行。其中包括但不限于使用 Visual Basic 6.0 及其更低版本創(chuàng)建的所有 COM 組件。
ASPCOMPAT 屬性
您將很高興聽(tīng)到這樣一個(gè)消息:仍然可以使用這些 STA 組件,而不需要更改任何代碼。您需要做的工作只是在 ASP .NET 網(wǎng)頁(yè)的 <%@Page> 標(biāo)記中包含兼容性屬性 aspcompat=true,如 <%@Page aspcompat=true Language=VB%>。使用此屬性將強(qiáng)制網(wǎng)頁(yè)以 STA 模式執(zhí)行,從而確保您的組件可以繼續(xù)正確運(yùn)行。如果試圖使用 STA 組件但沒(méi)有指定此標(biāo)記,運(yùn)行時(shí)將會(huì)發(fā)生異常情況。
將此屬性的值設(shè)置為 true 時(shí),將允許網(wǎng)頁(yè)調(diào)用 COM+ 1.0 組件,該組件需要訪問(wèn)非管理的 ASP 內(nèi)置對(duì)象??梢酝ㄟ^(guò) ObjectContext 對(duì)象進(jìn)行訪問(wèn)。
如果將此標(biāo)記的值設(shè)為 true,性能會(huì)稍微有些下降。建議只在確實(shí)需要時(shí)才這樣做。
早期綁定與后期綁定
在 ASP 中,對(duì) COM 對(duì)象的所有調(diào)用都是通過(guò) IDispatch 接口進(jìn)行的。這種行為被稱為“后期綁定”,因?yàn)閷?duì)實(shí)際對(duì)象的調(diào)用是在運(yùn)行時(shí)通過(guò) IDispatch 間接處理的。在 ASP .NET 中,只要您愿意,可以繼續(xù)以這種方式調(diào)用您的組件。
Dim Obj As Object
Obj = Server.CreateObject("ProgID")
Obj.MyMethodCall
仍然可以使用這種方式訪問(wèn)您的組件,但這不是首選方式。現(xiàn)在,在 ASP .NET 中,您可以利用早期綁定直接創(chuàng)建對(duì)象,如下所示:
Dim Obj As New MyObject
MyObject.MyMethodCall()
使用早期綁定,可以通過(guò)類型安全的方式與組件交互。為了在 COM 組件中使用早期綁定,您需要像在 Visual Basic 6.0 項(xiàng)目中添加 COM 引用一樣,在項(xiàng)目中添加一個(gè)引用。假設(shè)您正在使用 Visual Studio .NET,將在 COM 組件之上后臺(tái)創(chuàng)建一個(gè)管理的代理對(duì)象,給您的感覺(jué)就好像是直接在處理一個(gè) .NET 組件,而不是 COM 組件。
現(xiàn)在,您可能會(huì)擔(dān)心性能問(wèn)題。由于代理對(duì)象而引入了一個(gè)額外的層,所以使用 COM 協(xié)同操作時(shí)確實(shí)會(huì)存在一些問(wèn)題。但是,大多數(shù)情況下,應(yīng)該不會(huì)遇到什么問(wèn)題,因?yàn)檫M(jìn)行協(xié)同操作的實(shí)際 CPU 指令數(shù)仍然遠(yuǎn)遠(yuǎn)小于間接 IDispatch 調(diào)用的要求。您所得到的將遠(yuǎn)遠(yuǎn)超出您所失去的。當(dāng)然,理想情況是使用最新創(chuàng)建的管理對(duì)象,但我們知道,由于我們?cè)?COM 組件上的投入所限,并不總是能夠立即做到這一點(diǎn)。
OnStartPage 和 OnEndPage 方法
需要特別注意的是對(duì)舊版 OnStartPage 和 OnEndPage 方法的使用。如果您依賴于這些方法訪問(wèn) ASP 固有對(duì)象,將需要使用 ASPCOMPAT 指令和 Server.CreateObject 以早期綁定方式創(chuàng)建組件,如下所示:
Dim Obj As MyObj
Obj = Server.CreateObject(MyObj)
Obj.MyMethodCall()
注意,我們并沒(méi)有使用“ProgID”,而是以早期綁定方式使用實(shí)際類型。為了讓這種方式有效,您需要在 Visual Studio 項(xiàng)目中添加 COM 組件引用,這樣才能創(chuàng)建早期綁定的包裝類。這是唯一必須繼續(xù)使用 Server.CreateObject 的情況。
COM 總結(jié)
表 2 總結(jié)了為繼續(xù)有效使用 COM 組件而必須完成的一些工作。
表 2:舊版 COM 對(duì)象的 ASP .NET 設(shè)置
COM 組件類型/方法 ASP .NET 設(shè)置/過(guò)程
自定義 STA(標(biāo)記為“Apartment”的 Visual Basic 組件或其它組件) 使用 ASPCOMPAT 和早期綁定
自定義 MTA(標(biāo)記為“Both”或“Free”的 ATL 或自定義 COM 組件) 不使用 ASPCOMPAT,使用早期綁定
固有對(duì)象(通過(guò) ObjectContext 訪問(wèn)) 使用 ASPCOMPAT 和早期綁定
OnStartPage 和 OnEndPage 使用 ASPCOMPAT 和 Server.CreateObject(Type)
無(wú)論您的組件是否部署在 COM+ 中,都將同樣應(yīng)用這些設(shè)置。
應(yīng)用程序配置的變化
在 ASP 中,所有 Web 應(yīng)用程序配置信息都存儲(chǔ)在系統(tǒng)注冊(cè)表和 IIS 配置數(shù)據(jù)庫(kù)中。由于服務(wù)器上經(jīng)常未安裝適當(dāng)?shù)墓芾砉ぞ撸沟貌榭椿蛐薷脑O(shè)置變得非常困難。ASP .NET 引入了一整套全新的配置模型,這套模型以簡(jiǎn)單的、易讀的 XML 文件為基礎(chǔ)。每個(gè) ASP .NET 應(yīng)用程序都有自己的 Web.Config 文件,該文件位于主應(yīng)用程序目錄中。可以通過(guò)此文件控制 Web 應(yīng)用程序的自定義配置、行為和安全性。
如果您與我一樣,您可能會(huì)通過(guò)“Internet 服務(wù)管理器”管理單元檢查和更改 ASP .NET 應(yīng)用程序的設(shè)置。但是,您必須了解,現(xiàn)在我們擁有兩種完全不同的配置模型。除一些安全性設(shè)置外,ASP .NET 應(yīng)用程序?qū)⒑雎允褂?IIS 管理工具配置的其它大部分設(shè)置。您需要將這些配置設(shè)置保存在 Web.Config 文件中。
有關(guān) .NET 的應(yīng)用程序配置將在另一篇文章中詳細(xì)討論,此處就不詳細(xì)介紹了。表 3 說(shuō)明了可以在自己的文件中配置的一些更有意義的設(shè)置。記住,還有更多設(shè)置。
表 3:Web.Config 設(shè)置示例
設(shè)置 說(shuō)明
<appSettings>
配置自定義應(yīng)用程序設(shè)置。
<authentication>
配置 ASP .NET 身份驗(yàn)證支持。
<pages>
標(biāo)識(shí)網(wǎng)頁(yè)特定的配置設(shè)置。
<processModel>
配置 IIS 系統(tǒng)中的 ASP .NET 進(jìn)程模型設(shè)置。
<sessionState>
指定會(huì)話狀態(tài)選項(xiàng)。
在 .NET 基本類庫(kù)中還有其它一些類可用,它們簡(jiǎn)化了對(duì)這些設(shè)置的編程訪問(wèn)。
狀態(tài)管理
如果應(yīng)用程序使用 Session 或 Application 固有對(duì)象存儲(chǔ)狀態(tài)信息,則在 ASP .NET 中可以繼續(xù)使用這些對(duì)象,而不會(huì)出現(xiàn)任何問(wèn)題。隨之帶來(lái)的好處是,現(xiàn)在提供了更多的狀態(tài)存儲(chǔ)位置選項(xiàng)。
狀態(tài)管理選項(xiàng)
ASP .NET 中還包含其它一些狀態(tài)管理模型選項(xiàng),最終可使您管理不止一個(gè) Web 服務(wù)器,并支持通過(guò) Web 場(chǎng)進(jìn)行狀態(tài)管理。
可以在 web.config 文件的 <sessionState> 一節(jié)中配置狀態(tài)管理選項(xiàng),如下所示:
<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"
/>
模式屬性指定將在何處存儲(chǔ)狀態(tài)信息。可用選項(xiàng)有 Inproc、StateServer、SqlServer 或 Off。
表 4:會(huì)話狀態(tài)存儲(chǔ)信息
選項(xiàng) 說(shuō)明
Inproc 會(huì)話狀態(tài)本地存儲(chǔ)在此服務(wù)器中(ASP 樣式)。
StateServer 會(huì)話狀態(tài)遠(yuǎn)程(或本地)存儲(chǔ)在狀態(tài)服務(wù)進(jìn)程中。
SqlServer 會(huì)話狀態(tài)存儲(chǔ)在 SQL Server 數(shù)據(jù)庫(kù)中。
Off 會(huì)話狀態(tài)被禁用。
如果使用這些選項(xiàng)之一,StateConnectionString 和 sqlConnectionString 無(wú)疑將成為至關(guān)重要的參數(shù)。每個(gè)應(yīng)用程序只能使用一個(gè)存儲(chǔ)選項(xiàng)。
存儲(chǔ) COM 組件
需記住的的一點(diǎn)是,如果您依賴于對(duì) Session 或 Application 對(duì)象中舊版 COM 組件的存儲(chǔ)引用,將無(wú)法在應(yīng)用程序中使用新的狀態(tài)存儲(chǔ)機(jī)制(StateServer 或 SqlServer)。您將需要使用 Inproc。部分原因是對(duì)象需要在 .NET 中實(shí)現(xiàn)自我串行,很顯然,COM 組件無(wú)法做到這一點(diǎn)。另一方面,新創(chuàng)建的管理組件可以相對(duì)輕松地實(shí)現(xiàn)這一點(diǎn),因此可以使用新的狀態(tài)存儲(chǔ)模式。
性能
當(dāng)然,就性能而言,每前進(jìn)一步都將付出相應(yīng)的代價(jià)。但您完全可以相信,大多數(shù)情況下,使用 Inproc 依然是最佳選擇,其后依次是 StateServer 和 SqlServer。您自己應(yīng)該對(duì)應(yīng)用程序進(jìn)行測(cè)試,確保選定的選項(xiàng)可以達(dá)到您的性能目標(biāo)。
ASP 和 ASP .NET 之間的共享狀態(tài)
需要考慮的另外一個(gè)重要問(wèn)題是,雖然應(yīng)用程序可以同時(shí)包含 ASP 和 ASP .NET 網(wǎng)頁(yè),但您無(wú)法共享固有 Session 或 Application 對(duì)象中存儲(chǔ)的狀態(tài)變量??赡苄枰獙⑦@些信息復(fù)制到這兩個(gè)系統(tǒng)中或提出其它自定義解決方案,才能完全遷移您的應(yīng)用程序。最好的情況是您未使用 Session 和 Application 對(duì)象。另一方面,如果您大量使用了這些對(duì)象,您需要一直小心謹(jǐn)慎,或許可以提出某種自定義的短期解決方案來(lái)共享狀態(tài)。
與安全性有關(guān)的變化
安全性是需要特別注意的另一個(gè)重要問(wèn)題。下面簡(jiǎn)要介紹了 ASP .NET 安全性系統(tǒng)。有關(guān)安全性問(wèn)題更完整的研究,請(qǐng)參見(jiàn) ASP .NET 安全性文檔。
ASP .NET 安全性主要受 web.config 文件中安全性部分的設(shè)置控制。ASP .NET 與 IIS 協(xié)同工作,為您的應(yīng)用程序提供完善的完全性模型。IIS 安全性設(shè)置是實(shí)際攜帶并應(yīng)用于 ASP .NET 應(yīng)用程序的少數(shù)幾個(gè)應(yīng)用程序設(shè)置,其攜帶和應(yīng)用方式與在 ASP .NET 中相似。當(dāng)然,在很多方面都得到了改進(jìn)。
身份驗(yàn)證
對(duì)于身份驗(yàn)證,ASP .NET 支持表 5 中所示的選項(xiàng)。
表 5:ASP .NET 身份驗(yàn)證選項(xiàng)
類型 說(shuō)明
Windows ASP .NET 使用 Windows 身份驗(yàn)證。
Forms 基于 Cookie 的自定義登錄表單。
Passport 非 Microsoft 提供的 Passport Service。
None 不執(zhí)行身份驗(yàn)證。
除新增加的 Passport 身份驗(yàn)證選項(xiàng)之外,其它選項(xiàng)都與 ASP 中的選項(xiàng)相同。例如,下列配置對(duì)應(yīng)用程序啟用基于 Windows 的身份驗(yàn)證。
<configuration>
<system.web>
<authentication mode="Windows"/>
</system.web>
</configuration>
授權(quán)
用戶通過(guò)身份驗(yàn)證后,將集中考慮允許他們?cè)L問(wèn)哪些資源。在下例中,授予了“jkieley”和“jstegman”訪問(wèn)權(quán)限,而其他所有人都被拒絕訪問(wèn)。
<authorization>
<allow users="NORTHAMERICA\jkieley, REDMOND\jstegman"/>
<deny users="*"/>
</authorization>
模擬
做為刷新程序,模擬是指這樣一個(gè)過(guò)程:對(duì)象以它所代表的實(shí)體的標(biāo)識(shí)執(zhí)行代碼。在 ASP 中,模擬允許您的代碼代表通過(guò)身份驗(yàn)證的用戶運(yùn)行?;蛘?,用戶也可以通過(guò)特定標(biāo)識(shí)匿名運(yùn)行。默認(rèn)情況下,ASP .NET 不會(huì)針對(duì)每個(gè)請(qǐng)求進(jìn)行模擬。這一點(diǎn)與 ASP 不同。如果您依賴于這種功能,則需要在 web.config 文件中啟用它,如下所示:
<identity>
<impersonation enable = "true"/>
</identity>
數(shù)據(jù)訪問(wèn)
遷移過(guò)程中,需要重點(diǎn)考慮的另一個(gè)關(guān)鍵問(wèn)題是數(shù)據(jù)訪問(wèn)。隨著 ADO .NET 的誕生,現(xiàn)在您具有了一種訪問(wèn)數(shù)據(jù)的強(qiáng)有力的全新方法。由于數(shù)據(jù)訪問(wèn)本身就是一個(gè)很大的主題,本文就不詳細(xì)討論了。大多數(shù)情況下,您可以像過(guò)去一樣繼續(xù)使用 ADO,但是我極力推薦您了解一下 ADO .NET,并通過(guò)它改善 ASP .NET 應(yīng)用程序中的數(shù)據(jù)訪問(wèn)方法。
準(zhǔn)備向 ASP .NET 遷移
現(xiàn)在您已了解了可能會(huì)遇到的大多數(shù)問(wèn)題,您可能會(huì)想:目前我需要做好哪些準(zhǔn)備工作以備將來(lái)最終遷移到 ASP .NET 呢?目前確實(shí)需要完成幾項(xiàng)工作,以確保將來(lái)的遷移過(guò)程順利進(jìn)行。其中的許多建議對(duì)您的 ASP 代碼大有益處,即使目前不打算向 ASP .NET 遷移。
使用 Option Explicit
這始終是一個(gè)不錯(cuò)的建議,但至今仍然有許多人沒(méi)有使用它。通過(guò)使用 Option Explicit,強(qiáng)制在 ASP 中聲明變量,您至少可以控制在何處定義每個(gè)對(duì)象以及如何使用變量。遷移到 ASP .NET 之后,我建議使用 Option Strict。在 Visual Basic .NET 中,默認(rèn)使用 Option Explicit,但是使用更具強(qiáng)制性的 Option Strict,可以確保所有變量都聲明為正確的數(shù)據(jù)類型。這樣做確實(shí)需要增加一些額外的工作,但從長(zhǎng)期考慮,您將發(fā)現(xiàn)還是很值得這樣做的。
避免使用默認(rèn)屬性
我們前面已討論過(guò),不再允許使用默認(rèn)屬性。顯式訪問(wèn)屬性并不是什么難事。它將增強(qiáng)代碼的可讀性,而且可以在將來(lái)節(jié)省您的時(shí)間。
使用括號(hào)和 Call 關(guān)鍵字
正如本文前面詳細(xì)討論過(guò)的,應(yīng)盡可能使用括號(hào)和 Call 語(yǔ)句。在 ASP .NET 中,將強(qiáng)制使用括號(hào)?,F(xiàn)在使用 Call 語(yǔ)句有助于您熟悉一些規(guī)則,為將來(lái)的工作打好基礎(chǔ)。
避免嵌套的包含文件
這一點(diǎn)可能說(shuō)起來(lái)容易做起來(lái)難,但還是應(yīng)盡可能避免嵌套包含文件。我的意思是說(shuō),應(yīng)該努力避免在包含文件中包括其它包含文件。隨著時(shí)間的推移,可能會(huì)碰到的一種情況是,您的代碼不再依賴于在其它某處的包含文件中定義的全局變量,您需要訪問(wèn)的原因僅僅是因?yàn)槠渲星短琢税嬲枰娜肿兞康牧硪粋€(gè)文件。
向 ASP .NET 遷移時(shí),您很有可能會(huì)將全局變量和程序遷移到類庫(kù)中,這種情況下,如果您清楚地了解每個(gè)對(duì)象的訪問(wèn)位置,遷移起來(lái)就很容易。您不需要將一些對(duì)象移來(lái)移去,也不需要更改多個(gè)文件中相同的那些程序名稱。
將實(shí)用函數(shù)合并到單個(gè)文件中
遷移過(guò)程中的一個(gè)策略是將服務(wù)器端包含文件中包含的所有實(shí)用函數(shù)和代碼遷移到 Visual Basic 或 C# 類庫(kù)中。這樣,您最終可以將所有代碼放到所屬對(duì)象中,這一點(diǎn)與多解釋的 ASP 文件不同。提前組織好代碼,可以節(jié)省將來(lái)的遷移時(shí)間。理論上講,您應(yīng)該可以將子程序組合到邏輯文件中,從而使您可以輕松地創(chuàng)建一組 VB 或 C# 類。這些函數(shù)可能應(yīng)位于 COM 對(duì)象中。
如果服務(wù)器端包含文件中存在一大堆全局變量或常量,也最好考慮將他們組合到單個(gè)文件中。一旦遷移到 ASP .NET 后,您就可以輕松創(chuàng)建一個(gè)類來(lái)存放全局或常量數(shù)據(jù)。這將使系統(tǒng)更干凈、更易維護(hù)。
盡可能將代碼與內(nèi)容分開(kāi)
這又是一件說(shuō)起來(lái)比做起來(lái)容易的工作,但是您應(yīng)該盡量將代碼與 HTML 內(nèi)容分開(kāi)。清理一下主體中即有代碼、又有腳本的那些函數(shù)。這樣做使您處于非常有利的位置,可以充分利用代碼--無(wú)論怎么說(shuō),這是 ASP .NET 中的最佳模式。
不要在 <% %> 塊聲明函數(shù)
ASP .NET 不支持在 <% %> 塊聲明函數(shù)。應(yīng)該在 <script> 塊進(jìn)行聲明。有關(guān)此技術(shù)的示例,請(qǐng)參閱本文前面的結(jié)構(gòu)變化一節(jié)。
避免使用生成函數(shù)
如前所述,應(yīng)該盡量避免使用“生成函數(shù)”。如果現(xiàn)在可以更改或準(zhǔn)備代碼,應(yīng)在構(gòu)造這類函數(shù)時(shí)使用 Response.Write 塊。
顯式釋放資源(調(diào)用 Close 方法)
確保對(duì)使用的對(duì)象和資源中存在的 close() 或清理方法進(jìn)行顯式調(diào)用。我們都知道,Visual Basic 和 VBScript 在清理方面的容錯(cuò)能力很強(qiáng)。通常情況下,他們能夠立即清理對(duì)象。但遷移到 .NET 后,您將無(wú)法準(zhǔn)確掌握對(duì)象何時(shí)會(huì)被清理,就像您無(wú)法確定垃圾堆中的垃圾何時(shí)會(huì)被清理一樣。如果您能夠顯式清理和釋放資源,最好顯式地進(jìn)行清理和釋放。
避免混用語(yǔ)言
應(yīng)該盡量避免在同一網(wǎng)頁(yè)中混用服務(wù)器端 VBScript 和 JScript。一般而言,這是一種不太明智的編程方式。而且向 ASP .NET 遷移時(shí)還會(huì)存在問(wèn)題,因?yàn)橛捎诓捎昧诵碌木幾g模式,每個(gè)網(wǎng)頁(yè)只要求一種內(nèi)嵌 <% %> 語(yǔ)言。但仍然可以使用過(guò)去的方式生成客戶端腳本。
總結(jié)
正如我們已經(jīng)了解的,在向 ASP .NET 遷移應(yīng)用程序之前,有許多問(wèn)題需要考慮。我在此文中歸納了遷移前后會(huì)發(fā)生的大多數(shù)變化,這應(yīng)該能使您的遷移過(guò)程變得相對(duì)簡(jiǎn)單一些。
如果您擁有一個(gè)大型站點(diǎn),完成此進(jìn)程之后,您可能會(huì)對(duì)遇到并修正了如此多的死代碼、無(wú)效代碼以及所有 Bug 而驚奇不已。另外,通常您還可以充分利用 ASP .NET 和 .NET 平臺(tái)中大量強(qiáng)大的新增功能。
Jim Kieley 是 Microsoft Consulting Services 的高級(jí)顧問(wèn)。從 .NET 發(fā)展初期,Jim 就一直與 Visual Studio 組密切合作,而且他還是早期創(chuàng)建 ASP .NET 和 .NET 框架應(yīng)用程序的用戶之一。您可以通過(guò)下列電子郵件地址與 Jim 聯(lián)系:jkieley@microsoft.com