面向開發人員的 Web 部件介紹

背景知識

近幾年來,在 Microsoft 內部一直有開發強有力的搜索技術的構思。那就是使信息工作者只需通過拖放即插即用組件來創建個性化用戶界面。非編程人員應能夠將他們所關心的信息集合在一起並自定義其外觀。他們應能夠在一個位置上組合一個圖形,並在其中顯示他們部門的銷售額、一個本地通信監視器、一個股票報價機、一個針對所選主題的新聞提要,可能還包含一個顯示每日約會的日曆。

在第一個具體實現中,這種想法最初被命名爲數字儀表板,它的第一個應用環境是 Microsoft Outlook。最終,瀏覽器演變成可插入 Web 部件的首選容器,這種想法融合到行業範圍的趨勢(即,開發可自定義的 Web 門戶)中。

數字儀表板和 Web 部件的早期實現在主題演講中受到廣泛吹捧,並引起了具有前瞻看法的開發人員的興趣。但是,早期技術很難實現,其性能、可伸縮性、可維護性、本地化功能和安全性都不夠完善。

與此同時,在 Microsoft 中有兩個 Web 技術創新活動正在迅速推廣。ASP.NET 是在新興的公共語言運行庫的基礎上構建的,它爲 Web 開發人員提供一個高級框架,以使用面嚮對象的技術來創建快速可靠的站點。同樣重要的是,Microsoft SharePoint? 產品和技術組正開發一個高級結構,用於構建和維護基於瀏覽器的協作式工作區。

ASP.NET 和 Microsoft Windows SharePoint Services(它們均與 Microsoft Windows Server 2003 捆綁在一起)一同爲 Web 部件的全新實現提供了平臺,該平臺就是基於最初的想法構建的。

Web 部件基礎結構

新的 Web 部件基礎結構通過提供一個 .NET 對象模型(其中包含從 ASP.NET 類派生並對其進行擴展的類)在 ASP.NET 的基礎上構建。其他類和數據庫對象負責存儲(在 Microsoft SQL Server? 或 MSDE 中)和站點管理。

Web 部件是 ASP.NET 服務器控件。要創建新類型的 Web 部件,您可以創建一個 ASP.NET 自定義控件。然而,與標準 ASP.NET 控件(由程序員在設計時添加到 Web 窗體頁中)不同的是,Web 部件將由用戶在運行時添加到 Web 部件頁上的 Web 部件區域。

根據將用戶分配到的站點組以及分配給這些組的權限,用戶在修改 Web 部件和 Web 部件頁時可以具有不同的自由度。他們可以進行適用於某個共享頁所有用戶的更改,也可以進行僅在其查看該頁時適用的更改。

在許多方面,Web 部件使設計時和運行時之間的傳統區別變得很模糊。對於在瀏覽器中使用 Web 部件的用戶來說,其運行時體驗類似於 Microsoft Visual Basic 程序員在向窗體中添加控件並設置其屬性時的設計時體驗。Web 頁設計者也可以在 Microsoft Office FrontPage疇2003 中構建 Web 部件頁,以便能夠在設計環境中呈現 Web 部件。

Web 部件在很大程度上依賴 Windows SharePoint Services 來支持下列操作:

創建新站點和新頁面

管理站點的用戶名單

存儲 Web 部件的自定義(包括共享屬性設置和個人屬性設置)

管理站點備份和存儲限制

可處理數千個站點和上百萬個用戶的可伸縮體系結構

將用戶分配給可自定義的站點組

Microsoft SharePoint 產品和技術不再依賴基於角色的安全性爲用戶分配權利和權限。相反,SharePoint 產品和技術使用站點組和跨站點組爲用戶分配權利和權限。站點組是適用於特定 Web 站點的自定義安全組,跨站點組是適用於多個 Web 站點的自定義安全組。有關詳細信息,請參閱 Microsoft Windows SharePoint Services 幫助。

並且,SharePoint 產品和技術依賴 Web 部件來提供可配置和可擴展的用戶界面。

對於 Web 部件來說,最有趣、最具創新的新功能可能是一個基礎結構,Web 部件可以在其中使用標準接口來互相通信。用戶可以使用簡單的菜單選項來連接能夠交換數據的 Web 部件,而且 Web 部件在開發時可以完全相互獨立。例如,一個供應商的圖形 Web 部件可以連接到另一個供應商的數據表視圖 Web 部件,或者,一個股票報價 Web 部件可以顯示另一個列出供應商的 Web 部件中選定公司的當前股票價格。

安裝 Web 部件

本文附帶了一個下載文件,其中包含一個以 Microsoft Visual Studio .NET 2002 創建的解決方案。如果您使用的是 Visual Studio .NET 2003,則可以打開該解決方案,它將自動進行升級。

示例解決方案的名稱爲 Northwind,其中包含兩個項目。第一個項目的名稱也爲 Northwind,它輸出一個名爲 Northwind.dll 的 Web 控件庫,其中包含兩個 Web 部件控件。該解決方案中的第二個項目是一個名爲 NorthwindCab 的 Cab 項目,它輸出一個名爲 NorthwindCab.cab 的 .cab 文件。使用這個 .cab 文件,可以在運行 Microsoft Windows Server 2003 和 Windows SharePoint Services 的服務器上安裝示例 Web 部件。

NorthwindCab.cab 文件的發行版本位於示例文件的 /Northwind/NorthwindCab/Release 目錄中。要從這個 .cab 文件安裝 Web 部件,請使用位於服務器以下目錄中的 Stsadm.exe 命令行工具:

local_drive:/Program Files/Common Files/Microsoft Shared/Web Server Extensions/60/bin

用具有管理權限的帳戶登錄服務器,打開命令提示符,然後運行以下命令:


警告 要允許示例 Northwind Web 部件從 XML 文件加載數據,您可能需要在運行 Windows SharePoint Services 的服務器上調整安全策略設置。

向 Web 部件頁中添加 Web 部件

Windows SharePoint Services 提供四種可包含 Web 部件的庫:

虛擬服務器庫

<Site Name=>庫

Web 部件頁庫

聯機庫

虛擬服務器庫列出可供服務器上所有站點使用的 Web 部件。<Site_Name> 庫包含可供特定站點使用的 Web 部件。在默認情況下,當您運行 Stsadm.exe 來安裝某個 Web 部件時,Stsadm.exe 會將該 Web 部件添加到虛擬服務器庫中。有關如何使用 Windows SharePoint Services 中提供的管理工具來填充<Site_Name> Web 站點庫的詳細信息可在本文的後面找到。

Web 部件頁庫包含已經添加到當前頁面中的 Web 部件,這乍看起來很荒謬。爲什麼需要添加已經添加到頁面上的 Web 部件呢?這之所以有用,是因爲您可以將某個 Web 部件添加到頁面中,然後關閉該 Web 部件。要關閉某個 Web 部件,請單擊該 Web 部件標題欄右側的箭頭,然後單擊“關閉”。已關閉的 Web 部件不再出現在該頁面上,但它仍是該頁面 Web 部件頁庫的成員。此 Web 部件仍然通過運行 Windows SharePoint Services 的服務器的配置數據庫中的某個項目與該頁面相關聯,此頁面還存儲該 Web 部件的所有共享屬性設置或個性化屬性設置。

您可以將 Web 部件添加到頁面中,以獨佔方式個性化該部件,關閉該部件,然後將其重新添加到該頁中並使個性化設置保持不變。要取回已關閉的 Web 部件,請從 Web 部件頁庫中選擇它。

要將某個 Web 部件從頁面中實際刪除,您必須單擊“修改我的網頁”菜單(或共享視圖中的“修改共享網頁”菜單),然後單擊“設計此網頁”,將“刪除”命令添加到該 Web 部件的下拉菜單中。要將該 Web 部件從頁面中刪除,而不將其添加到 Web 部件頁庫中,請單擊該 Web 部件標題欄右側的箭頭,然後單擊“刪除”。

聯機庫是一組可通過 Web 服務使用的 Web 部件,它允許許多服務器共享訪問一個集中維護的公共 Web 部件庫。該 Web 服務的 URL 在站點的 Web.config 文件的 OnlineLibrary 元素中指定。

要點 要啓用聯機庫,您必須編輯服務器上的 Web.config 文件,並將 OnlineLibrary 元素的 URL 特性更改爲以下特性:


要點 如果您使用代理服務器,還必須添加以下部分:


要將上述四個默認庫的其中一個內出現的 Web 部件添加到 SharePoint 頁中,請按照下列步驟操作:

1.

要將 Web 部件只添加到自己版本的頁面中,請確保“修改我的網頁”菜單出現在頁面頂部。如果“修改共享網頁”菜單出現在頁面頂部,請單擊“修改共享網頁”菜單,然後單擊“個人視圖”。

要將 Web 部件添加到所有用戶的頁面中,請確保“修改共享網頁”菜單出現在頁面頂部。如果“修改我的網頁”菜單出現在頁面頂部,請單擊“修改我的網頁”菜單,然後單擊“共享視圖”。

2.

在“修改我的網頁”菜單(個人視圖)或“修改共享網頁”菜單(共享視圖)上,指向“添加 Web 部件”,然後單擊“瀏覽”或“搜索”。

如果您單擊“瀏覽”,則可以選擇這四個庫中的任意一個,以便查看該庫中 Web 部件的列表。如果您單擊“搜索”,則可以將選擇限制在名稱中包含搜索文本的 Web 部件範圍內。“瀏覽”和“搜索”命令都可以打開四個可用庫的列表,併爲每個庫顯示一個數字,指出該庫中可用 Web 部件的數量。當您選擇某個庫時,會出現該庫中 Web 部件的列表。

3.

將希望添加的 Web 部件從任務窗格拖到 Web 部件頁的 Web 部件區域中,然後可以關閉任務窗格或選擇更多的 Web 部件。

圖 1 顯示正從虛擬服務器庫拖到頁面上的示例 CustomerCellConsumer Web 部件。正如本文前面所述的那樣,該庫是在使用 Stsadm.exe 工具時,在其中安裝示例 Web 部件的庫。


1. 在 Internet Explorer 中向頁面添加 Web 部件

向頁面添加 Web 部件時,可以在支持豐富的用戶交互功能的瀏覽器中使用拖放操作。但是,Web 部件不需要 Microsoft Internet Explorer,甚至也不需要支持動態 HTML 的瀏覽器。其中一個原因在於,圖 1 中顯示的任務窗格包含一個用於在頁面上選擇 Web 部件區域的下拉列表,以及一個用於將所選的 Web 部件添加到選定區域的“添加”按鈕。另外,這些替換控件可讓不使用鼠標的用戶訪問 Web 部件。

本文中的幾幅圖顯示了站點主頁上的 Web 部件快照。您在將 Web 部件添加到站點主頁中時不受限制。要創建新的 Web 部件頁,請在菜單欄中單擊“創建”,滾至“創建頁面”頁底部的“網頁”標題,然後單擊“Web 部件頁”。在“新建 Web 部件頁”頁上,您可以命名新頁面,從列表中選擇一個頁面佈局,還可以選擇包含這個新頁的文檔庫。然後,您可以向這個新頁中添加 Web 部件。

設置 Web 部件的屬性

Web 部件可共享公共屬性,如 Title、Height 和 AllowClose。在其中出現 Web 部件的區域也是 Web 部件的一個屬性。您可以通過將標準 .NET 屬性添加到 Web 部件的類中,來向 Web 部件添加自定義屬性。

當您在瀏覽器中設置 Web 部件的屬性時,修改範圍取決於頁面是位於個人視圖還是共享視圖中。在個人視圖中進行的更改僅適用於當前用戶,且優先於在共享視圖中進行的更改。可使用共享視圖爲該頁的所有用戶設置默認值。

要更改某個 Web 部件的屬性,請單擊該 Web 部件標題欄右側的箭頭,然後單擊“修改我的 Web 部件”(在個人視圖中)或“修改共享 Web 部件”(在共享視圖中)。您無需將頁面切換到設計視圖,即可進行該選擇。但是,當出現用於設置屬性的任務窗格時,頁面會自動更改到設計視圖。在設計視圖中,您可以看到每個 Web 部件區域的輪廓以及該區域的標題。

示例 CustomerRowProvider Web 部件有一個自定義布爾屬性 DetailViewEnabled,該屬性可決定在該 Web 部件中顯示多少有關所選客戶的信息。圖 2 顯示屬性如何顯示在瀏覽器的任務窗格中。


2. 在 Internet Explorer 中設置自定義屬性

在 C# 代碼中,該屬性的特性(在本文的後面介紹)提供該屬性的自定義視圖類別,以及出現在任務窗格中的友好名稱和工具提示。因爲該屬性有一個布爾數據類型,所以 Web 部件基礎結構可自動爲該屬性創建一個複選框控件。

連接 Web 部件

Web 部件基礎結構爲 Web 部件之間的通信提供了強大的支持。開發人員可以使用標準接口來創建可互相交換信息的 Web 部件。例如,用來實現 ICellConsumer 接口的 Web 部件可以從用來實現 ICellProvider 接口的 Web 部件接收信息。用戶可以使用瀏覽器中的簡單菜單命令將 Web 部件互相連接。

另外,Web 部件基礎結構還提供了轉換器,從而允許接口不完全互補的 Web 部件互相通信。Web 部件基礎結構可自動檢測接口不匹配的情況並顯示一個對話框,該對話框允許用戶將一個接口的值映射到另一個接口。例如,如果用戶將用來實現 IRowProvider 接口的 Web 部件連接到用來實現 ICellConsumer 接口的 Web 部件,就會顯示一個對話框,允許用戶從 IRowProvider Web 部件中選擇要發送到 ICellConsumer Web 部件的單列數據。示例 Northwind Web 部件中提供了這樣的示例。

要在將 CustomerRowProvider 和 OrderCellConsumer Web 部件添加到頁面之後將它們連接在一起,請按照下列步驟操作:

1.

如果頁面尚未處於設計視圖中,請單擊“修改我的網頁”菜單或“修改共享網頁”菜單,然後單擊“設計此網頁”。

只有當頁面處於設計視圖時,才能創建連接。

2.

單擊 Orders Web 部件標題欄中的箭頭,指向“Connections”,指向“Get Customer ID from”(該標籤分配給由此 Web 部件提供的唯一連接接口),然後單擊“Customer (Row Provider)”,如圖 3 所示。請注意,頁面上的幾個 Web 部件會出現在這個子菜單中,這是因爲它們都實現與 Orders Web 部件的 ICellConsumer 接口相兼容的連接接口。


3. 在 Internet Explorer 中連接 Web 部件

3.

在選擇了要連接的 Web 部件之後,會出現一個對話框,如圖 4 所示。創建此對話框無需任何代碼。此對話框會自動出現,請求將 ICellConsumer Web 部件連接到 IRowProvider Web 部件所必需的額外信息。


4. 一個對話框請求創建連接所需的信息。

4.

選擇 Customer ID(這是默認選項,因爲它是列表上的第一個選項),然後單擊“Finish”。

5.

要查看 Orders Web 部件中特定客戶的定單,請在 Customer Web 部件中選擇一個客戶 ID,如圖 5 所示。


5. Orders Web 部件顯示 Customer Web 部件中所選客戶的定單。

您可能想知道 Customer Web 部件爲什麼不實現 ICellProvider 接口以提供客戶 ID,而是需要一個轉換器來連接到 Orders Web 部件。通過實現 IRowProvider 接口(而非 ICellProvider 接口),Customer Web 部件會更通用。它可以與用來實現 IRowConsumerIFilterConsumer 接口的 Web 部件進行連接,也可以與各種 ICellConsumer Web 部件進行連接。例如,Customer Web 部件可以將其 PostalCode 列中的數據提供給 ICellConsumer Web 部件(該部件顯示指定郵政編碼地區的天氣狀況)。

在瀏覽器中,可以使用四對接口來連接 Web 部件:

ICellProvider/ICellConsumer 此接口對可與單個單元格中的數據進行通信。通過使用轉換器,ICellConsumer 還可以與 IRowProvider 進行連接。

IRowProvider/IRowConsumer 此接口對可與一行數據進行通信。通過使用轉換器,IRowProvider 可以與 ICellConsumerIFilterConsumer 進行連接。

IListProvider/IListConsumer 此接口對可與整個數據列表進行通信。

IFilterProvider/IFilterConsumer 此接口對可與包含一對或多對列名和值的篩選器表達式進行通信。IFilterConsumer 可以使用轉換器與 IRowProvider 進行連接,但是這種類型的連接只能處理一對列名/值。換言之,如果您使用轉換器連接到 IRowProvider,則只能針對單列進行篩選。

另外,在 FrontPage 2003 中(而不是在瀏覽器中),可以使用兩個接口對來連接 Web 部件。您還可以使用下列接口來創建跨頁面連接,這些連接使用查詢字符串來交換數據:

IParametersOutProvider/IParametersOutConsumer IParametersOutProvider Web 部件定義了一組參數,它可以將這些參數發送到與之兼容的 IParametersOutConsumer Web 部件。通過使用轉換器,IParametersOutProvider Web 部件還可以與 IParametersInConsumer Web 部件進行連接。

IParametersInProvider/IParametersInConsumer IParametersInConsumer Web 部件定義了一組參數,它可以從與之兼容的 IParametersInProvider Web 部件接收這些參數。通過使用轉換器,IParametersInConsumer Web 部件還可以與 IParametersOutProvider Web 部件或 IRowProvider Web 部件進行連接。

IParametersOut 和 IParametersIn 接口對之間的區別可能會令人混淆。二者的重要區別在於,提供者爲 IParametersOut 接口對定義參數,而使用者爲 IParametersIn 接口對定義參數。當用戶嘗試將 IParametersOutProvider Web 部件連接到 IParmetersInConsumer Web 部件時,會出現一個對話框,用戶可以使用該對話框定義如何將提供者 Web 部件的參數映射到使用者 Web 部件的參數。這些接口的通用性很強,但請記住,用戶必須使用 FrontPage 2003 才能連接這些接口,而不能在瀏覽器中連接這些接口。

下表顯示可以通過轉換器互相連接的接口對,以及這些連接是否需要 FrontPage 2003。

可通過轉換器進行連接 可在瀏覽器中進行連接 可在 FrontPage 中進行連接

IRowProvider 到 ICellConsumer

IRowProvider 到 IFilterConsumer

IParametersOutProvider 到 IParametersInConsumer

IRowProvider 到 IParametersInConsumer

下表顯示可跨頁面進行連接的接口。要連接不同頁面上的 Web 部件,您必須使用 FrontPage 2003。

源頁面接口 目標頁面接口

IRowProvider

IFilterConsumer

IRowProvider

IParametersInConsumer

IFilterProvider

IFilterConsumer

IParametersOutProvider

IParametersInConsumer

IParametersInProvider

IParametersInConsumer

 

在 Visual Studio .NET 中使用 Web 部件模板

所有的 Web 部件都是 ASP.NET 自定義控件,因此 Visual Studio .NET 可爲創建和調試 Web 部件提供絕佳的環境。

要在 Visual Studio 中爲 Web 部件自定義控件創建項目,您可以使用用來構建 Web 控件庫的標準模板,也可以使用用來構建 Web 部件庫的特殊模板。Web 部件庫模板不隨附在 Visual Studio .NET 中,它們可從 Web Part Templates for Microsoft Visual Studio .NET 中免費下載。

Web 部件庫模板對於 C# 和 Visual Basic .NET 均可用。在運行模板的安裝程序時,您可以選擇要安裝的語言。要安裝模板,您還必須指定 Microsoft.SharePoint.dll 文件的路徑。在默認情況下,Microsoft.SharePoint.dll 文件安裝在運行 Windows SharePoint Services 的計算機的以下位置:

local_drive:/Program Files/Common Files/Microsoft Shared/Web Server Extensions/60/ISAPI

與使用標準的 Web 控件庫模板相比,使用 Web 部件庫模板有幾個好處。從 Web 部件庫模板生成的項目自動包括以下有用的項目和功能:

對 Microsoft.Sharepoint.dll 文件的引用

Web 部件類文件和與之匹配的 .dwp 文件(.dwp 文件是 XML 文件,它們引用 Web 部件的程序集、命名空間、類名以及 Web 部件的可選屬性設置)。

能夠添加包含以下類型項目的示例代碼的文件:

基本 Web 部件,它繼承自 Microsoft.SharePoint.WebPartPages.WebPart 並可替代 RenderWebPart

包含示例代碼的使用者或提供者 Web 部件,可實現 ICellConsumerICellProvider 接口,替代必需的方法並處理必需的事件

包含示例代碼的工具部件類,它繼承自 Microsoft.SharePoint.WebPartPages.ToolPart 並可替代 ApplyChanges、SyncChangesCancelChanges 方法

Web 部件的 .dwp 文件,其中包含必需 XML 元素的示例項

Web 部件的 Manifest.xml 文件,其中包含必需 XML 元素的示例項(在安裝 Web 部件時,Manifest.xml 文件由 Stsadm.exe 工具使用)

 

設置 Web 部件項目的輸出路徑屬性

當您在 Visual Studio .NET 中創建 Web 部件時,必須更改“輸出路徑”屬性,使其指向 Windows SharePoint Services 站點的 bin 文件夾,即使在使用 Web 部件庫模板創建項目時也是如此。如果您希望對本文附帶的示例 Northwind 項目進行更改、重新編譯並測試所作的更改,則也需要進行上述更改。在默認情況下,“輸出路徑”屬性指向項目目錄中的本地 Bin 文件夾。

要在 Visual Studio .NET 中編輯“輸出路徑”屬性,請按照下列步驟操作:

1.

在解決方案資源管理器中,右鍵單擊該項目,然後單擊“屬性”。

2.

在左窗格中,單擊“配置屬性”,然後單擊“生成”。

3.

在“輸出”下,單擊“輸出路徑”屬性值,鍵入虛擬服務器上 Bin 文件夾的路徑(或者單擊省略號 (...) 按鈕,以瀏覽至 Bin 文件夾所在的位置),然後單擊“確定”。

該路徑會從絕對路徑轉換爲相對路徑,如圖 6 所示。


6. 編輯“輸出路徑”屬性以指向站點的 Bin 文件夾。

當您重新編譯項目時,編譯器會自動將包含 Web 部件程序集的 .dll 文件放在由“輸出路徑”屬性指定的目錄中。如果該目錄中已經存在同名的文件,則它會被新文件替換。

警告 如果您在編輯“輸出路徑”屬性之前重新編譯示例 Northwind 項目,則編譯器會創建一組文件夾,這些文件夾與原始屬性設置(可能與 SharePoint 站點的 Bin 目錄所在的位置不對應)指定的相對路徑相匹配。

將 Web 部件用作 ASP.NET 自定義控件

Web 部件的創建過程不同於 ASP.NET 自定義控件的創建過程。因此,在鑽研如何創建 Web 部件的細節之前,快速回顧一下 ASP.NET 可擴展模型將有所幫助。

ASP.NET 爲擴展服務器控件框架提供了兩個抽象:用戶控件和自定義控件。

用戶控件實質上是可插入其他頁面中的 ASP.NET 頁面,它們在一定程度上類似於傳統 ASP 中使用的 Include 文件。使用 Visual Studio .NET,您可以使用將控件拖到頁面設計器的方式,將服務器控件拖到用戶控件設計器上,從而輕鬆地構建用戶控件。用戶控件會創建一些 .ascx 文件,這些文件非常類似於在構建 ASP.NET 頁面時創建的 .aspx 文件。但是,您不能通過構建用戶控件來創建 Web 部件。要創建 Web 部件,您必須創建 ASP.NET 自定義控件。

與用戶控件不同的是,ASP.NET 自定義控件不受 Visual Studio .NET 中圖形工具的支持。要構建自定義控件,您必須創建一個從 System.Web.UI.Control 直接或間接繼承的類,還必須編寫自己的代碼來發出 HTML。ASP.NET 附帶的所有服務器控件都是以這種方式創建的。爲了幫助您創建自定義控件,ASP.NET 框架提供了 HtmlTextWriter 類。HtmlTextWriter 類有許多方法、屬性和附帶枚舉,您可以使用它們輕鬆地生成可靠的 HTML,而不只是構造字符串。ASP.NET 基礎結構對頁面上所有控件的呈現進行協調。

當您創建從 Control 類直接繼承的 ASP.NET 自定義控件時,可以通過替代基類的 Render 方法來生成 HTML。此方法將 HtmlTextWriter 對象作爲參數。此對象由 ASP.NET 基礎結構在運行時傳遞給該方法,代碼會通過調用該 HtmlTextWriter 對象上的方法來發出 HTML。

爲了避免混淆,請記住,ASP.NET 使用“呈現”一詞,這不同於通常的用法。呈現通常是指將 HTML 文本轉換爲圖形顯示,此任務通常由瀏覽器執行。但是,在 ASP.NET 中,呈現是指在服務器控件中生成 HTML。

在創建 ASP.NET 自定義控件時,建議不要直接從 System.Web.UI.Control 類繼承。從 System.Web.UI.WebControls.WebControl(它本身從 System.Web.UI.Control 類繼承)繼承通常會更高效、更可靠。WebControl 類包括與公用樣式相關的屬性(如 BackColorBorderWidthFont 等)的實現,並負責將這些屬性呈現爲 HTML 特性。

當您創建從 WebControl 類派生(而不是直接從 Control 類派生)的類時,不要替代 Render 方法,而是替代一個名爲 RenderContents 的方法,該方法是 WebControl 類的方法。WebControl 類替代 Render 方法來爲控件創建外部標記,其特性與其樣式相關的屬性相對應。替代控件中的 RenderContents 方法使您可以發出 HTML,該 HTML 已正確嵌入到由控件的 Render 方法創建的標記中。RenderContents 方法將 HtmlTextWriter 對象作爲參數,正如 Render 那樣。

Web 部件自定義控件的開發遵循相似的模式。但是,您應創建一個從 Microsoft.SharePoint.WebPartPages.WebPart 類繼承的類,而不是創建從 WebControl 類繼承的類。這個 WebPart 類從 System.Web.UI.Control 類繼承,正如 WebControl 那樣。WebPart 類負責創建控件的鉻印效果(例如,標題欄和邊框),用戶可以通過設置屬性和應用主題來自定義鉻印效果。WebPart 類還處理與 WebPartPageWebPartZone 類的交互,從而支持在頁面上添加、移動、隱藏、刪除、連接、自定義和個性化 Web 部件。圖 7 顯示 WebPart 類的層次結構,並顯示 Web 部件與其他自定義控件的比較。


7. Web 部件派生自 Microsoft.SharePoint.WebPartPages.WebPart 類,該類派生自 System.Web.UI.Control。

如果您曾經創建過 ASP.NET 自定義控件,則會發現 Web 部件的創建過程非常熟悉。在書籍、文章及示例代碼中演示的適於自定義控件的方法,同樣適用於 Web 部件自定義控件的構建任務。只需記住從 WebPart 類(而非 WebControl)繼承,以及替代 RenderWebPart 方法(而非 RenderContents 方法)。

在標準的自定義控件中,如果您確實需要直接替代 Render 方法,則可以選擇這樣做,即使您從 WebControl 類繼承也是如此。但是,在 WebPart 類中,Render 方法是密封的。在從 WebPart 派生的類中,您必須替代 RenderWebPart,而不是 Render

與其他自定義 ASP.NET 控件相比,Web 部件基礎結構爲 Web 部件提供了以下幾點優勢:

用戶可以將 Web 部件庫中的 Web 部件添加到 Web 部件區域中。

用戶可以修改 Web 部件的個人屬性或共享屬性,並使所作的更改保持穩定。

Web 部件可以使用標準接口相互連接,用戶可以啓動這些連接。

 

創建 Web 部件類

本文附帶的兩個示例 Web 部件(CustomerRowProvider 和 OrdersCellConsumer)包含有註釋代碼,您可以將該代碼用作創建自己的 Web 部件的指南。

在創建 Web 部件控件時,第一步是定義一個從 WebPart 類繼承的類,該類可以實現一個或多個 Web 部件通信接口。下面的代碼包括 CustomerRowProvider Web 部件的類聲明:


該類應用了三個特性。如果您在 Visual Studio .NET 中使用 Web 部件模板或 Web 控件模板,則這些特性會自動插入。前兩個特性(DefaultPropertyToolboxData)控制設計環境(如 Visual Studio)中的行爲 — 它們指定屬性窗口中默認選擇的屬性,以及插入 ASPX 或 ASCX 文件的文本(如果將控件拖到頁面或用戶控件上)。{0} 標記由 Page 指令(或者對於用戶控件來說,是 Control 指令)中已註冊到控件的標記前綴替換。

這強調了一個事實,即可以像對任何其他服務器控件那樣,將 Web 部件控件拖到 ASP.NET Web 窗體頁上。但是,使用此方法將 Web 部件直接嵌入 ASP.NET 頁不是一個好辦法,因爲這會失去 Web 部件基礎結構的功能 — 用戶不能保存對個人屬性或共享屬性進行的更改,也不能將 Web 部件互相連接在一起。要實現此功能,必須將 Web 部件添加到 Web 部件區域中,這是在瀏覽器或 FrontPage(而非 Visual Studio)中完成的。

XmlRoot 特性也是由模板添加的 — 在將基於此類的對象序列化爲 XML 時,該特性會生效。

OrdersCellConsumer 類的類定義類似於上面的代碼示例,唯一的區別在於它實現 ICellConsumer,而非 IRowProvider

向 Web 部件中添加子控件

即使 Web 部件服務器控件中的所有 HTML 呈現都是通過在 RenderWebPart 中調用 HtmlTextWriter 對象的方法來執行的,您仍然可以在 Web 部件內部使用 ASP.NET 控件,這些控件被稱作子控件。您可以使用在 ASP.NET 頁的類中相同的方式爲這些子控件創建變量。

CustomerRowProvider 代碼包含了幾個 ASP.NET 子控件的聲明、一個下拉列表和十個標籤:


要在 Web 部件中使用這些子控件,您必須替代 System.Web.UI.ControlCreateChildControls 方法。在該方法中,您可以實例化這些控件,設置它們的屬性,並掛鉤任何事件處理程序。您還必須將這些控件添加到從 System.Web.UI.Control 繼承的 Web 部件的 Controls 集合屬性中。該代碼首先實例化 ErrorLabel 控件,該控件在默認情況下不可見。如果在嘗試加載 Web 部件的數據時出現異常,該控件會顯示一則錯誤消息。


接着,該代碼將實例化下拉列表控件,掛鉤它的事件處理程序,並將該控件添加到 Web 部件的 Controls 集合中:


使用類似的代碼實例化其餘的標籤控件,設置它們的屬性,並將它們添加到 Controls 集合中。

在 ASP.NET Web 窗體或用戶控件中,可以將某些控件屬性設置指定爲 .ASPX 或 .ASCX 文件中的特性。但是,與在任何自定義控件中一樣,在 Web 部件中,必須在代碼中指定所有的屬性設置。這類似於 .NET Windows 窗體中使用的模式,在該模式中,所有的控件屬性設置都出現在代碼中,並且所有的控件都顯式添加到窗體的 Controls 集合屬性中。

CustomerRowProvider 代碼包含下拉列表的兩個事件處理程序 — 一個用來加載列表,另一個用來對選擇做出響應。在 Load 事件處理程序中,該代碼將 XML 文件中的架構和數據讀入 ADO.NET 數據集中。該代碼假設 XML 文件位於 Wpresources 目錄中。每個 Web 部件都能夠訪問此目錄,因此最好將圖像、本地化資源或 Web 部件所需的其他文件放在此處。但是,要訪問任何文件(即使是存儲在 Wpresources 目錄中的文件),您的代碼必須具有充分的權限。用於確保向 Web 部件分配充分權限的各種選項將在本文的後面討論。

ReadXml 方法需要的是文件路徑(而非 URL),因此該代碼使用 Server.MapPath 方法將 Wpresources 目錄的相對路徑映射到服務器上的實際文件路徑。該代碼包裝在 try/catch 塊中,因此,當文件 I/O 權限不可用時,它可以做出正確的響應:


只有當首次加載頁面時,該代碼才需要填充下拉列表。在回發請求的過程中,列表會自動從 ViewState 屬性加載,正如在任何 ASP.NET 頁面上一樣。但是,您不能依賴在 ASP.NET 頁面中(甚至在 ASP.NET 自定義控件中)編寫代碼時使用的方式,檢查頁面的 IsPostBack 屬性值。

您確實可以使用以下方法來訪問 IsPostBack 屬性:this.Page.IsPostBack。但是,在將某個 Web 部件添加到頁面中時,會出現回發請求,即使在該 Web 部件的 ViewState 數據尚未填充時也是如此。對於直接嵌入 ASP.NET 頁面的服務器控件,決不會出現這種類型的回發請求,回發請求只出現在 Web 部件已加載過一次之後。這強調了 Web 部件和其他自定義控件之間的微妙區別:用戶可以在運行時將 Web 部件添加到頁面中,該操作可觸發回發請求。

下面的示例代碼檢查列表中是否已包含任何項目,而不是檢查 IsPostBack 屬性:


列表的 SelectedIndexChanged 事件代碼是任一標準 ASP.NET 頁面的典型代碼,因此它未包括在此處。該代碼可在客戶被選定時填充 Web 部件的標籤。

呈現 Web 部件的 HTML

在 Web 部件中使用子控件是可選的,但是,向用戶顯示內容的每個 Web 部件都必須替代 RenderWebPart 方法,Web 部件正是在此處生成在 Web 部件框架中呈現的 HTML。

如果您的 Web 部件使用子控件,則應通過調用 EnsureChildControls 來開始執行 RenderWebPart 方法。System.Web.UI.ControlRenderWebPart 方法會自動檢查 ChildControlsCreated 屬性。如果該屬性爲 false,此方法會調用 CreateChildControlsEnsureChildControls 可作爲一種安全方式在 Web 部件代碼中的許多位置上調用,這樣可確保當您需要子控件時,它們就位於相應的位置,而不必多次創建它們:


CustomerRowProvider Web 部件包含一個名爲 ErrorLabel 的標籤,該標籤在默認情況下處於隱藏狀態。只有在嘗試讀取 CustomerIdLoad 事件處理程序中的 XML 數據文件的過程中出現異常時,該標籤才變得可見。

確保已創建所有子控件之後,RenderWebPart 代碼會檢查 ErrorLabel 是否仍舊不可見,從而指出數據是否已成功加載:


在編寫用來在 RenderWebPart 中發出 HTML 的代碼時,涉及到調用傳遞到 RenderWebPart 方法的 HtmlTextWriter 對象的方法。要創建某個 HTML 標記,首先需要調用 AddAttribute 方法以定義要添加到該標記中的所有特性,然後調用 RenderBeginTag 方法並指定要創建的 HTML 元素。在需要關閉某個標記時,調用 RenderEndTag 來關閉打開的最後一個標記。

CustomerRowProvider 的呈現代碼通過創建一個 div 標記開始,該標記指定單元格填充值爲 2 個像素:


還有一個更可靠的方法來創建此標記。您可以使用 HtmlTextWriterTag 枚舉,而不是對標記的名稱進行硬編碼:


枚舉值可用於所有常見的 HTML 標記,您可以使用它們針對標記的拼寫錯誤來提供編譯時保護。

如果您需要設置 HTML 標記的多個特性,則可以在調用 RenderBeginTag 之前多次調用 AddAttribute。指定的所有特性值都添加到開始標記中。下面的代碼設置了 table 標記的幾個特性:


當 Web 部件在瀏覽器中呈現時,上面的代碼可創建下面的 HTML:


您還可以通過調用 AddStyleAttribute(而非 AddAttribute)來創建 CSS 樣式的標記,這些標記可將幾個設置組合到一個特性中:


上面的幾行代碼可發出下面的 HTML:


另外,您可以通過調用 HtmlTextWriter 對象的 Write 方法來發出硬編碼的 HTML 字符串:


要關閉 HTML 標記,請調用 RenderEndTag。當您執行上述操作時,HtmlTextWriter 會自動創建一個與最近的開始標記相匹配的結束標記。您無需指定結束標記的類型,但是添加一個使代碼更清楚的註釋會有所幫助:


在需要呈現某個子控件時,應調用該控件的 RenderControl 方法並將 HtmlTextWriter 對象傳遞給它。由於 RenderControl 方法是 System.Web.UI.Control 基類的方法,所以它可用於所有的控件。下面的代碼可呈現表單元格中的下拉列表:


RenderWebPart 方法中的其餘代碼調用要顯示的標籤控件的 RenderControl 方法,RenderControl 方法可添加用於將控件嵌入表單元格的標記。如果 ErrorLabel 控件可見,則唯一運行的呈現代碼就是顯示錯誤消息(此消息被指定給該控件的文本屬性)的代碼:


如果您熟悉 ASP.NET 服務器控件和 HTML 的處理,就會發現爲 Web 部件編寫呈現代碼非常簡單。您只需將對 HtmlTextWriter 對象方法的調用與對子控件 RenderControl 方法的調用組合在一起。請記住替代 CreateChildControls,以便創建控件並將它們添加到 Controls 集合中。若您需要在 CreateChildControls 以外的方法中引用子控件,請首先調用 EnsureChildControls

創建和顯示自定義屬性

當用戶選擇修改您的 Web 部件時,可以在瀏覽器任務窗格中方便地將您爲 Web 部件類創建的任何自定義屬性公開給用戶。

您可以將幾個特性添加到代碼的屬性定義中,以便調整如何將屬性提供給用戶。CustomerRowProvider Web 部件有一個名爲 DetailViewEnabled 的屬性,該屬性決定顯示多少數據。RenderWebPart 方法中用來呈現標籤控件的部分檢查 DetailViewEnabled 屬性,並在 DetailViewEnabled 爲真時呈現所有的標籤。

添加到如下代碼示例的 DetailViewEnabled 屬性的特性爲該屬性指定了一個說明、一個自定義類別、一個默認值和一個友好名稱。另外,如果將 WebPartStorage 特性設置爲 Storage.Personal,則指定可以針對不同的用戶存儲該屬性的不同值。圖 2 顯示了此代碼在任務窗格的用戶界面中的效果。


爲了確保該屬性顯示在任務窗格中,您必須做的全部工作就是定義它,如上面的示例代碼所示。但是,您可以替代 GetToolParts 方法以自定義屬性的顯示方式。此方法可返回要在任務窗格中顯示的 ToolPart 對象的數組。

下面的代碼首先將 CustomPropertyToolPart 對象添加到此方法返回的 ToolPart 數組中。即使沒有此代碼,也會顯示包含自定義屬性的自定義視圖類別。但是,在默認情況下,自定義屬性顯示在標準屬性後面。要將自定義屬性移到任務窗格的頂部,請將它移到數組的第一個位置。CustomPropertyToolPart 對象自動顯示所有自定義屬性,WebPartToolPart 對象自動顯示標準屬性。此代碼還指定應展開自定義視圖類別。在默認情況下,其他類別在任務窗格打開時處於摺疊狀態。


在這些示例 Web 部件中,可自動創建標準控件以顯示自定義屬性 #151; 一個複選框(用於 Customer Web 部件中的 DetailViewEnabled 布爾屬性)和一個文本框(用於 Orders Web 部件中的 CustomerID 字符串屬性)。但是,您可以使用 Web 部件基礎結構,通過創建從 Microsoft.SharePoint.WebPartPages.ToolPart 類繼承的類來爲自己的屬性創建自定義用戶界面。Visual Studio .NET 的 Web 部件模板包括一個用來創建自定義 ToolPart 類的模板。

創建可連接的 Web 部件

Web 部件基礎結構的一個非常誘人的功能就是它支持 Web 部件之間通信的方式。其他控件容器(可能從最初的 Visual Basic“Ruby”窗體包開始)已經使用事件驅動的模型來支持控件之間的交互。但是,在所有這些窗體包(包括 ASP.NET 中的頁面框架)中,控件會引發某些事件,這些事件由容器中運行的代碼處理。例如,Web 窗體或 Windows 窗體可能包括一個用於按鈕單擊事件的處理程序,該事件處理程序可以在窗體上的另一個控件中設置屬性,並且有可能觸發其他事件。但是,一個控件不能直接處理由另一個控件激發的事件。

Web 部件之間的通信模型有所不同。事件不是由頁面、甚至是包含 Web 部件的 Web 部件區域來處理,而是由頁面上其他 Web 部件中的處理程序來處理。Web 部件對於它們正與其他哪些 Web 部件進行通信沒有硬編碼知識,這將產生進一步的挑戰。Web 部件之間的連接由用戶在運行時實時創建。

這些挑戰由 Web 部件連接基礎結構來解決,該基礎結構通過針對頁面上每個已連接的 Web 部件調用 WebPart 基類的標準方法來調解 Web 部件之間的通信。要參與 Web 部件之間的通信,您的 Web 部件必須替代這些方法。

另外,可連接的 Web 部件必須實現本文前面描述的其中一個標準連接接口。Web 部件只能與其他可實現補充其自身的接口的 Web 部件進行通信,儘管基礎結構能夠提供可充當某些接口之間適配器的轉換器。例如,該示例使用一個轉換器將 IRowProvider Web 部件連接到 ICellConsumer Web 部件。在與 IRowProvider 通信時,該轉換器充當 IRowConsumer,在與 ICellConsumer 通信時,該轉換器充當 ICellProvider

Web 部件基礎結構調用 Web 部件的方法,來發現每頁上可連接的 Web 部件。爲了使連接選項可供用戶使用,它將填充已添加到每個可連接 Web 部件中的菜單。

大多數連接接口都要求您聲明事件委託。當用戶創建連接時,Web 部件基礎結構會將這些事件掛鉤到其他 Web 部件中的處理程序。在構造頁面時,該基礎結構會針對每個可連接的 Web 部件調用一系列方法,因此,Web 部件可以通過激發由它們所連接的 Web 部件處理的事件來互相通信。

實現 IRowProvider

要創建 IRowProvider Web 部件,您必須聲明兩個事件並替代六個方法。以下各個部分介紹了這些任務,並提供了 CustomerRowProvider Web 部件中的示例代碼。

聲明 IRowProvider 事件

CustomerRowProvider 代碼聲明實現 IRowProvider 接口所必需的兩個事件 — RowProviderInitRowReady 事件。下面的代碼顯示這些事件的聲明:


在技術上,這兩個事件聲明就是這個 Web 部件類實現 IRowProvider 接口所必需的全部內容。因爲該接口的互補接口 IRowConsumer 不引發任何事件,所以該接口不需要任何事件處理程序。

但是,要參與 Web 部件之間的通信,IRowProvider Web 部件還必須替代 WebPart 基類的六個方法,即使這些方法未包括在 IRowProvider 接口定義中也是如此。在這方面,Web 部件連接接口實際上是不僅僅需要實現所定義接口的設計模式。

替代 EnsureInterfaces

Web 部件基礎結構調用某個 Web 部件的 EnsureInterfaces 方法,並期望該 Web 部件針對它的每個連接接口調用 WebPart 基類受保護的 RegisterInterface 方法。

RegisterInterface 方法包含八個參數,這些參數爲 Web 部件基礎結構提供協調與該 Web 部件的連接所需的信息。每個參數的用途在以下代碼的註釋中進行了描述:


替代 CanRunAt

Web 部件基礎結構使用 CanRunAt 方法來確定 Web 部件是期望在客戶端還是在服務器上實現其連接。這看上去可能是多餘的,因爲 RegisterInterface 方法的 RunAtOptions 參數能夠解決同一個問題。然而,Web 部件可以使用此方法來提供用來執行以下操作的邏輯:基於在運行時可用的數據,計算預期的客戶端或服務器設置。

Web 部件基礎結構總是在某種程度上基於參與連接的其他 Web 部件的設置,針對在客戶端還是在服務器上實現連接做出最終決策。

本文以及隨附的示例沒有演示如何創建客戶端連接,因爲這需要 Web 部件發出用來實現連接的腳本代碼。


替代 PartCommunicationConnect

在某個 Web 部件成功連接到另一個 Web 部件之後,Web 部件基礎結構會調用此方法。它向該 Web 部件傳遞參數,指定連接了它的哪些接口、哪個 Web 部件和接口位於連接的另一端以及連接是在客戶端上還是服務器上運行。在本示例中,此方法僅調用 EnsureChildControls 方法。此方法的一個可能用法是,提供僅在該 Web 部件連接到特定 Web 部件時才運行的代碼。如果您創建了一組可互相利用各自特殊知識的 Web 部件,則您的代碼就會在此處發現這些 Web 部件已建立連接。


替代 PartCommunicationInit

您必須聲明 RowProviderInit 事件,但是在技術上,您不必爲了滿足 IRowProvider 接口的要求而引發該事件。但是,如果您在不引發 RowProviderInit 事件的情況下連接到某些使用者 Web 部件,則這些部件將無法正常工作,因此必須聲明該事件。在替代 PartCommunicationInit 方法時需要引發該事件。該事件允許代碼將初始化數據發送到您的 Web 部件所連接的 Web 部件。

示例 CustomerRowProvider Web 部件顯示如何使用 RowProviderInit 事件的 RowProviderInitArgs 參數來發布其字段的名稱以及要爲每個字段顯示的名稱。用來處理該事件的使用者 Web 部件可以在響應中自定義自身,這可能是通過顯示數據的標籤來完成的。

有幾個 Web 部件通信接口都包括一個 Init 事件(CellProviderInitCellConsumerInit 等),該事件具有一個特定於該接口的 InitEventArgs 參數。RowProviderInitEventArgs 對象具有用來存儲字符串數組的 FieldListFieldDisplayList 屬性。

本示例中的 CustomerRowProvider 類有兩個專用字符串數組字段:_fieldList_fieldDisplayList。這些數組在 CreateChildControls 方法中進行填充,並在此處用於設置 RowProviderInitEventArgs 對象的 FieldListFieldDisplayList 屬性。隨後,代碼引發 RowProviderInit 事件,將此數據發送到任何已連接 Web 部件的事件處理程序。


替代 GetInitEventArgs

對於可以使用轉換器的接口,您只需替代此方法。Web 部件基礎結構在創建圖 4 所示的轉換器對話時調用此方法。此方法返回的數據用於自定義該對話框的用戶界面。

此方法有一個用來標識所查詢接口的參數,它返回一個從 InitEventArgs 派生的對象。此方法所返回對象的確切類型視接口而異。CustomerRowProvider Web 部件中的代碼可確定是否正在查詢此部件的 RowProvider 接口,如果正在查詢的話,此代碼將返回一個 RowProviderEventArgs 對象,該對象類似於在引發 RowProviderInit 事件時使用的對象。


替代 PartCommunicationMain

替代 PartCommunicationMain 方法可以引發任何其餘的事件。在通過引發事件向所連接的使用者發送數據的提供者 Web 部件中,這通常是必需的。

IRowProvider Web 部件使用此方法來引發 RowReady 事件。RowReadyEventArgs 對象的 Rows 屬性可存儲 ADO.NET DataRow 對象的數組。

CustomerRowProvider Web 部件用單個 DataRow 對象填充 Rows 數組,該對象與在它的下拉列表中選擇的客戶 ID 相匹配。此類有一個受保護的 CurrentRow 字段,該字段在下拉列表的 SelectedIndexChanged 事件處理程序中進行填充。

除了 Rows 屬性以外,RowReadyEventArgs 還有一個用來指出當前選擇狀態的字符串屬性。此屬性的可用字符串在嵌入以下代碼的註釋中進行了描述。


提供者接口支持要在 PartCommunicationMain 中引發的各個事件。例如,ICellProvider Web 部件引發 CellReady 事件,IListProvider Web 部件引發 ListReady 事件。您的代碼必須引發這些事件,即使當前的請求是回發請求並且您提供的數據未發生任何更改。某些接口提供特殊的事件來解決無法提供任何可用數據的情形 — 例如,NoFilterNoParametersInNoParametersOut。如果無法引發這些事件,可能會導致使用者 Web 部件處於等待處理事件的狀態,從而產生問題,。

創建事件處理程序

實現連接接口的最後一步是爲互補接口的事件創建任何必需的事件處理程序。然而,IRowConsumer 接口不包括任何事件,因此在實現 IRowProvider 時不需要任何處理程序。

實現 ICellConsumer

本示例中的 OrdersCellConsumer Web 部件舉例說明了如何實現 ICellConsumer 接口。

ICellConsumer 的實現步驟與前面描述的 IRowProvider 的實現步驟非常相似:聲明事件、替代方法和處理互補接口(在本例中爲 ICellProvider)的事件。

ICellConsumer 接口只需要聲明一個事件 — CellConsumerInit,該事件必須由 PartCommunicationInit 方法引發。

另外,ICellConsumer Web 部件必須:

替代 EnsureInterfaces 以調用 RegisterInterface

替代 CanRunAt 以指定客戶端或服務器端連接

替代 PartCommunicationConnect 以添加針對連接而做出響應的代碼

替代 PartCommunicationInit 以引發 CellConsumerInit 事件,該事件向提供者 Web 部件發送一個 CellConsumerInitEventArgs 對象,此對象包含所使用單元格的字段名和顯示名稱的屬性

替代 GetInitEventArgs 以支持轉換器

(可選)處理 ICellProviderCellProviderInit 事件,以便從它的連接夥伴那裏獲得 FieldNameFieldDisplayName

處理 ICellProviderCellReady 事件,以便從 CellReadyEventArgs 對象的 Cell 屬性獲取數據

ICellConsumer Web 部件不需要替代 PartCommunicationMain,這是因爲它們不引發任何其他事件。

 

安裝細節

在後臺,Web 部件受到豐富管理基礎結構的支持。本文前面描述的 Stsadm.exe 工具可爲它所安裝的每個 Web 部件程序集執行下列操作:

將 Web 部件程序集複製到 SharePoint 站點的 Bin 目錄中。在本示例中,此程序集名爲 Northwind.dll。

將該程序集中每個 Web 部件的 .dwp 文件複製到此站點的 Wpcatalog 目錄中。.dwp 文件是一個包含 Web 部件相關信息的 XML 文件,本文稍後將更詳細地介紹該文件。本示例中包含兩個 .dwp 文件:Northwind_CustomerRowProvider.dwp 和 Northwind_OrdersCellConsumer.dwp。所有在 Wpcatalog 目錄中包含 .dwp 文件的 Web 部件都自動包括在虛擬服務器庫中,虛擬服務器庫是可在該服務器上使用的 Web 部件的目錄。

將所有 Web 部件資源文件複製到它在此站點的 Wpresources 目錄中爲該程序集創建的子目錄中。本示例包含兩個資源文件:Customers.xml 和 Orders.xml,用於存儲由 Web 部件使用的數據。

向該站點的 Web.config 文件的 SafeControls 部分中添加項目。該站點允許用戶只加載那些在配置文件中列爲安全的 Web 部件。

將 .cab 文件複製到運行 Windows SharePoint Services 的服務器的配置數據庫中,以便您可以通過按名稱引用某個程序集,將該程序集安裝到其他 SharePoint 站點上或者服務器場中的其他服務器上,而無需訪問初始的 .cab 文件。

爲了允許 Stsadm.exe 工具執行這些任務,.cab 文件必須包含該程序集、一個 .dwp 文件以及所有必需的資源文件。另外,.cab 文件必須包含一個名爲 Manifest.xml 的 XML 文件,該文件用於指定每個程序集的 .dwp 和資源文件的名稱,以及要添加到 Web.config 文件中的 SafeControls 項。下面是本示例中包括的 Manifest.xml 文件的完整文本:


通過運行其他 Stsadm.exe 命令和命令行開關,可以從服務器中刪除 Web 部件包、枚舉所安裝的軟件包、指定應爲特定虛擬服務器安裝的軟件包,或者指定應將程序集安裝到全局程序集緩存 (GAC)(而非 Bin 文件夾)中。

要點 要將某個 Web 部件程序集安裝到 GAC,您必須賦予該程序集一個強名稱。Northwind 示例程序集沒有強名稱,因此它不能安裝到 GAC 中。要賦予該程序集一個強名稱,請編輯 AssemblyInfo.cs 文件中的 AssemblyKeyFile 屬性,使其包含密鑰對所在文件的路徑,然後重新編譯該項目。在編譯時使用密鑰對文件簽署程序集,可確保只有能夠訪問密鑰對文件中私鑰的開發人員才能對程序集進行更改。

創建和部署 .dwp 文件

Windows SharePoint Services 使用擴展名爲 .dwp 的 XML 文檔來維護 Web 部件基於文件的持久性。這些文件可捕獲 Web 部件屬性設置的快照,以及對用於創建 Web 部件的程序集和類的引用。

在以前版本的 Web 部件技術中,實際代碼中包含的 .dwp 文件用於實現 Web 部件的邏輯。在當前版本中,Web 部件邏輯在託管程序集中已編譯的 ASP.NET 類中實現,.dwp 文檔包含每個 Web 部件的程序集和類的名稱。

在默認情況下,由 Visual Studio .NET 模板創建的 .dwp 文件只指定 Title 屬性和 Description 屬性的值,當用戶向頁面中添加 Web 部件時,這些值用於標識這些部件。但是,您可以向該 .dwp 文件中添加元素以指定其他屬性值,替代在 Web 部件代碼中實現的默認屬性設置。

下面的示例顯示包括在示例 Northwind 項目中的 Northwind_OrdersCellConsumer.dwp 文件的 XML 文本:


此示例 .dwp 文件的內容具有 XML 的自編文檔特性,因此易於理解和編輯。請注意,Web 部件的類名在 TypeName 元素中指定,並使用包括命名空間的名稱。

要指定其他任何屬性值,請添加一個標記,並使該標記所基於的屬性名和文本包含所需的屬性值。例如,您可以向示例 .dwp 文件中添加下行:


在默認情況下,使用此版本 .dwp 文件安裝的 Web 部件將顯示客戶 ALFKI 的定單。

在使用任務窗格修改了 Web 部件的共享屬性和個人屬性之後,您可以通過從 Web 部件菜單中選擇“導出”,將 Web 部件的當前狀態捕獲到一個 .dwp 文件中。導入該 .dwp 文件會創建一個 Web 部件,其狀態與以前導出的 Web 部件的狀態相同。您可以使用 .dwp 文件來序列化和反序列化 Web 部件實例。這在使用某些 Web 部件(如用作靜態 HTML 容器的內置內容編輯器 Web 部件)時尤其有用。

如果您能夠找到某個 Web 部件的 .dwp 文件,而且該 Web 部件的程序集位於全局程序集緩存或者虛擬服務器的 Bin 目錄中,則可以向頁面中添加該 Web 部件,即使該 Web 部件尚未包括在庫中也是如此。另外,該 Web 部件必須在虛擬服務器的 Web.config 文件中標識爲安全,如本文的下一部分所述。

通過引用 .dwp 文件來添加 Web 部件

1.

在 Web 部件頁上,單擊“修改我的網頁”或“修改共享網頁”。

2.

指向“添加 Web 部件”,然後單擊“導入”。

3.

在任務窗格中,鍵入該 .dwp 文件的路徑,或者單擊“瀏覽”按鈕,然後瀏覽至該 .dwp 文件所在的位置。所選 Web 部件即會出現在任務窗格中。

4.

將該 Web 部件拖到頁面上的 Web 部件區域中,或者使用“添加到”菜單選擇一個 Web 部件區域,然後單擊“添加”。

警告 在向站點庫中添加 Web 部件時,會將 .dwp 文件複製到 Windows SharePoint Services 爲該站點維護的內容數據庫中。如果您對 .dwp 文件進行更改,則必須再次導入它,否則所作的更改將被忽略。

在您安裝某個 Web 部件時,還可以讓 Windows SharePoint Services 自動爲該 Web 部件的程序集創建默認的 .dwp 文件。要進行此操作,請執行以下步驟:

1.

在主頁上,單擊“網站設置”。

2.

在“網站設置”頁的“管理”區域中,單擊“轉到站點管理”。

3.

在“頂級站點管理”頁的“站點集合目錄”區域中,單擊“管理 Web 部件庫”。

Microsoft Windows SharePoint Services 2.0 Beta 2 以前使用目錄 這一術語,在本文中,此術語已更新爲庫 以反映當前的用法。

4.

在“Web 部件庫”頁上,單擊“新建 Web 部件”。

5.

在“Web 部件庫上:在“新建 Web 部件”頁上,選中要添加到站點庫中的任一 Web 部件複選框。所有這些 Web 部件在適用 Web.config 文件的 SafeControls 部分中都標識爲安全。

6.

(可選)鍵入每個選定 Web 部件的 .dwp 文件的名稱,系統會基於類名自動輸入默認的文件名。

7.

單擊“填充庫”。系統會自動創建一個最簡單的 .dwp 文件,並將其添加到一個名爲 Site_Name 的庫中。

添加到 Site_Name 庫中的 Web 部件即可供該站點及其下面的所有站點使用。

指定安全的 Web 部件

如果允許用戶、甚至是 Administrator 站點組中的成員不受限制地導入新 Web 部件,可能會使服務器受到安全威脅。因此,必須先將 Web 部件顯式指定爲安全,才能在虛擬服務器上使用它們。這是通過在虛擬服務器的 Web.config 文件的 SafeControls 部分中創建項目來完成的。Web.config 文件通常位於以下位置:


每個 SafeControls 項都標識一個包含一個或多個 Web 部件的程序集。您可以分別列出 Web 部件類,也可以指定程序集中的所有 Web 部件都是安全的。下面是一個 Web.config 文件的 SafeControls 部分的示例,它的前面有一些標記,顯示它如何適應該文件的 XML 層次結構:


每個 SafeControl 元素都有四個特性:

Assembly 程序集的名稱,其中包含一個或多個 Web 部件。對於具有強名稱的程序集,您必須包括名稱、版本、區域性和公鑰標記。對於其他程序集,儘管可以包括所有這四個部分,但只有名稱是必需的。

警告 如果您通過在項目的 Assemblyinfo.cs 文件中添加密鑰對文件的路徑來爲示例 Northwind 程序集賦予強名稱,則必須向該程序集的 SafeControl 項添加公鑰標記。要獲得具有強名稱的程序集的公鑰標記,一個簡單的方法是通過將 .dll 文件拖到 local_drive:/Windows/Assembly 目錄中,以將該程序集添加到 GAC 中。然後,您可以右鍵單擊該程序集並單擊“屬性”,以查看該程序集的屬性。公鑰標記即會顯示出來,該標記視圖非常方便,這是因爲您可以選擇它並將它複製到剪貼板上。如果您想將程序集從 GAC 中刪除,請右鍵單擊該程序集,然後單擊“刪除”。

Namespace Web 部件類的 .NET 命名空間。請注意,嵌套命名空間中的 Web 部件必須分別列出,即使針對 TypeName 輸入星號時也是如此。例如,前面顯示的 SafeControls XML 部分包括 Microsoft.SharePoint 程序集的兩個單獨的項目 — 一個用於 Microsoft.SharePoint 命名空間,另一個用於 Microsoft.SharePoint.WebPartPages 命名空間。

TypeName Web 部件的類名。您可以使用星號 (*) 來指出某個項目適用於所指定程序集和命名空間中的全部 Web 部件類。在開發程序集時,這尤其方便,因爲在添加新的 Web 部件類並重新編譯程序集時,無需進行任何更改。

Safe 通常,此特性的值爲 True。但是,Administrator 站點組的成員可以通過將此特性設置爲 False,來否認 Web 部件的安全並使其不可用。

SafeControls 列表可防止惡意 Web 部件供用戶使用。另外,Web 部件受制於那些應用於所有託管代碼的相同代碼訪問安全性控件。

代碼訪問安全性

在公共語言運行庫爲 Web 部件提供的各種有價值的服務中,有一項服務是代碼訪問安全性。根據本地計算機 Administrator 帳戶成員控制的策略,可以防止 Web 部件代碼執行某些類型的操作(如讀取或寫入文件)。

由於 Microsoft 盡力提供可信賴的計算技術,Windows SharePoint Services 的默認安全設置具有很強的限制性。您可能需要具備一定的前瞻能力,以確保 Web 部件程序集獲得它們所需的權限。

運行庫對每個 .NET 程序集的各個證據類型進行評估。例如,強名稱就是一種證據類型,就如程序集的位置一樣 — 無論將它安裝在 GAC 中還是 bin 文件夾中。運行庫還可以對指定安全策略的配置文件進行評估。基於證據和策略,每個程序集都被賦予一組權限。

在默認情況下,Microsoft Windows SharePoint Services 2.0 Beta 2 包括了一個非常寬容的安全策略。許多在 Beta 2 中能夠正常工作的 Web 部件,在以後的 Beta 版本或商用版本的 Microsoft Windows SharePoint Services 2.0 上運行時,可能會產生安全異常。例如,示例 Northwind Web 部件需要具備從 XML 文件讀取數據的文件訪問權限 — 在默認情況下,這些權限在 Beta 2 中可用,但在以後的版本中不可用。

在 Web.config 文件中指定信任級別

SharePoint 站點的 Web.config 文件包含一個 trust 元素,此元素指定賦予該服務器上運行的 Web 部件的默認安全級別。此元素出現在配置文件的 System.Web 部分中:


對於 level 特性來說,在默認情況下可用的值爲 Full、High、Medium、Low、Minimal、WSS_Medium 和 WSS_Minimal。在這些級別中,只有三個級別允許 Web 部件運行:Full、WSS_Medium 或 WSS_Minimal。其他信任級別適用於 ASP.NET,但是不包括 Web 部件所需的特定權限。

用來在 Web 部件中啓用功能的一種簡單方法是,升級 Web.config 文件中的信任級別,但是此方法具有潛在危險。例如,示例 Northwind Web 部件需要兩種類型的文件 I/O(輸入/輸出)權限 — 它們需要調用 Page.Server.MapPath 以發現 XML 數據文件的文件系統路徑,並且還需要讀取這些文件。這些權限對於 WSS_Minimal 信任級別不可用,但是,如果您將值更改爲 WSS_Medium 或 Full,它們將變得可用。

使用這種提升 Web 部件權限的方法是非常危險的,因爲它會全局應用到整個 SharePoint 虛擬服務器中。更好的做法是使用一種允許您區分不同 Web 部件並根據需要應用不同信任級別的方法。但是,對於調試和開發工作,改變 Web.config 文件中的設置可能會非常有用。

爲了確保您對 Web.config 信任級別設置進行的所有更改生效,請在保存所作的更改之後,從命令提示符下運行 Iisreset

創建和編輯策略文件

Web.config 文件中的每個信任級別都與用來指定一組權限的策略配置文件相對應。例如,WSS_Minimal 信任級別的權限在名爲 Wss_minimaltrust.config 的文件中指定。

您可以編輯這些文件以更改默認策略,也可以創建自己的策略文件並引用 Web.config 文件中的自定義策略。Web.config 文件中的 SecurityPolicy 部分列出可用的自定義信任級別以及它們所基於的文件。下面的代碼顯示一個 SharePoint 站點的 Web.config 文件中的默認列表:


您可以添加可引用自定義策略的信任級別元素。每個策略文件都包含權限類的列表、已命名權限集及每個集合的權限的列表、用以定義證據(程序集必須提供該證據,以便爲其分配一個特定的權限集)的代碼組列表。

您還可以編輯其中一個默認策略文件。例如,您可以修改 Wss_minimaltrust.config 文件,以便向 Northwind Web 部件授予必需的文件 I/O 權限,即使在服務器的信任級別設置爲 WSS_Minimal 時也是如此。

要執行這種修改,需要以下三個步驟:

指定任何必需的權限類。

定義權限集。

定義用來基於證據分配權限集的代碼組。

首先,將以下代碼行添加到服務器上 Wss_minimaltrust.config 文件的 SecurityClasses 部分:


接着,將下面的權限集添加到 NamedPermissionSets 部分。此權限集包括執行和連接 Web 部件所必需的權限,以及一個文件 I/O 權限,該 I/O 權限限制在讀取和發現虛擬服務器的 Wwwroot 目錄樹中的文件路徑。


您必須對策略文件進行的最後一次修改是添加一個代碼組,該代碼組可爲符合您指定的成員身份條件(證據)的程序集分配自定義權限集。在本例中,代碼組中的成員身份取決於是否具有指定的強名稱。這種方法能夠將提升的權限安全地限制到單個程序集。

XML 的代碼組塊嵌套在類別中。每個代碼組定義都包含兩個元素 — 一個 CodeGroup 元素和一個 IMembershipCondition 元素。

查找最外面的 CodeGroup 元素,該元素的 class 特性的值爲 FirstMatchCodeGroup。該元素的 PermissionSetName 特性設置爲 Nothing,這是因爲它是引用已命名權限集的其他代碼組的容器。將以下代碼行嵌套在外面的 FirstMatchCodeGroup 代碼組內部:


示例 Northwind 項目包含一個名爲 Wss_mimimaltrust.config 且包括這些更改的文件。

爲了使其生效,還需要執行最後一步。您需要用實際的公鑰值替換 IMembershipCondition 元素中的“your_public_key”標記。爲此,請使用 Sn.exe 工具生成一個密鑰對文件,按前面所述的那樣在 Assemblyinfo.cs 文件的 AssemblyKeyFile 特性中引用該密鑰對文件,然後重新編譯 Northwind 項目以生成具有強名稱的程序集。要獲得強名稱 blob,請從命令提示符下運行以下命令:


此外,還要記住的是,如果您爲 Web 部件程序集賦予了一個強名稱,還應當像前面所述的那樣,將公鑰標記值添加到 Web.config 文件中該 Web 部件的 SafeControl 項中。

安裝到 GAC 中以實現完全信任

如果您賦予 Web 部件程序集一個強名稱,則還可以選擇提升它的信任級別。您可以將程序集安裝在全局程序集緩存中,以便它自動以完全信任的級別執行。

如果您檢查 Windows SharePoint Services 的策略文件,其原因會變得很清楚。即使是 Wss_minimaltrust.config 文件也包括下面的代碼組:


當您使用 Stsadm.exe 工具爲具有強名稱的程序集安裝 Web 部件 .cab 文件時,可以使用 globalinstall 命令行開關將其安裝到 GAC 中,如下所示:


您還可以將具有強名稱的 Web 部件程序集手動安裝到 GAC 中,方法是將該 Web 部件的 .dll 文件拖到下面的特殊文件夾中:


特殊的 Wpresources 文件夾位置用於安裝到 GAC 中的所有 Web 部件:


使用基於 Wpresources 目錄的 URL 有一個好處,那就是 Web 部件基礎結構可自動在適當的位置查找文件,具體在哪個位置查找取決於 Web 部件是安裝到虛擬服務器的 bin 目錄還是安裝到 GAC 中。

但是,依賴 GAC 是添加 Web 部件權限的另一種簡單但具有潛在危險的示例方法,這是因爲安裝在 GAC 中的 Web 部件始終以完全信任的級別運行。更好的做法是隻賦予代碼其所需的權限。安裝在 GAC 中的 Web 部件還會自動供該計算機上的所有虛擬服務器使用,而這可能是您不希望的。

當您將 Web 部件安裝到 Bin 目錄中時,可以將 Web 部件限制到單個虛擬服務器,並限制可由 Web 部件使用的權限。

注 爲了便於限制權限,您還可以進一步採取另一個步驟,那就是向 Web 部件程序集添加可指定它們所需的確切權限的特性。這會向程序集中添加元數據,從而更易於發現所需的權限。下面的安全特性示例可防止在文件 I/O 權限不可用時加載程序集:

using System.Security.Permissions;

[Assembly:FileIOPermission(SecurityAction.RequestMinimum)]

調試 Web 部件

Visual Studio .NET 便於在執行頁面期間逐句通過 Web 部件類中的代碼。但是,要調試 Web 部件,您必須首先確保它安裝在運行 Windows SharePoint Services 的服務器上,否則您將無法運行它。下列步驟中詳述的操作已經在本文前面更詳細地介紹過:

1.

設置 Web 部件項目的“輸出路徑”屬性,使其指向虛擬服務器的 Bin 目錄。

2.

從 .cab 文件安裝 Web 部件,或者遵循以下三個步驟。

3.

向虛擬服務器上 Web.config 文件的 SafeControls 部分中添加一項。

4.

爲 Web 部件創建一個 .dwp 文件。

5.

將 Web 部件加載到 Site_Name 庫中。要進行此操作,請執行以下步驟:

在 Web 部件頁上,單擊“修改我的網頁”或“修改共享網頁”。

指向“添加 Web 部件”,然後單擊“導入”。

在任務窗格中,鍵入 .dwp 文件的路徑,或者單擊“瀏覽”按鈕並瀏覽至 .dwp 文件所在的位置。所選的 Web 部件隨後會出現在任務窗格中。

將 Web 部件拖到頁面上的 Web 部件區域中,或者從“添加到”列表中選擇一個 Web 部件區域,然後單擊“添加”。

您可能希望在開始調試之前將 Web 部件添加到頁面中,也可能希望調試在添加 Web 部件時運行的代碼,這兩種情況都有可能出現。

當您準備開始調試時,請返回到 Visual Studio .NET 並在 Web 部件的代碼中設置一個或多個斷點。用來設置中斷的兩個較好的候選方法是 CreateChildControls 方法和 RenderWebPart 方法。

如果您尚未調試過 ASP.NET 自定義控件,則後面的步驟可能是最棘手的:

1.

在“調試”菜單上,單擊“進程”。

2.

在“進程”對話框中,確保“顯示系統進程”和“顯示所有會話中的進程”複選框均被選中。

3.

選擇 W3wp.exe 進程。

4.

單擊“附加”。

5.

在“附加到進程”對話框中,選中“Common Language Runtime”作爲要調試的程序類型,然後單擊“確定”。

6.

單擊“關閉”。

7.

在瀏覽器中運行您的 Web 部件;執行過程會在斷點處中斷。

8.

使用標準的 Visual Studio 方法來調試代碼,然後在準備終止會話時從“調試”菜單中選擇“停止調試”。

警告 如果您在測試 Web 部件之後嘗試編輯和重新編譯代碼,則可能會收到一則錯誤消息,指出 Visual Studio .NET 無法替換輸出 .dll 文件。要解決此問題,請使用任務管理器來終止 W3wp.exe 進程,或者從命令行運行 iisreset。這將釋放對 .dll 文件的鎖定,以便您可以重新編譯。

 

小結

對於使用 Windows SharePoint Services(目前只能通過 Microsoft Windows Server 2003 使用)的公司,Web 部件提供了極具競爭力的技術。Windows SharePoint Services 協作環境和 ASP.NET 可擴展模型組合在一起,最終爲開發人員提供了一個將最初的數字儀表板承諾變爲現實的平臺。

對於用戶,Web 部件提供了全新的自由度和能力來彙集個性化頁面、工作區和門戶。對於管理員,Web 部件提供了安全和可伸縮性。對於設計師,Web 部件基礎結構爲 Web 應用程序的表示層提供了基於接口的可插入組件所帶來的好處。

發佈了53 篇原創文章 · 獲贊 0 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章