轉:ASP.NET 2.0:使用使用者控制項和定製的Web組件個人化你的門戶網站

來源:互聯網
上載者:User

ASP.NET 2.0:
使用使用者控制項和定製的Web組件個人化你的門戶網站

原著:Ted Pattison,Fritz Onion
翻譯:汪泳

原代碼下載:WebParts.exe (619KB)
原文出處:ASP.NET 2.0 Personalize Your Portal with User Controls and Custom Web Parts

本文基於 ASP.NET 2.0 的預發行版本,文中提供的所有資訊將來都可能發生變化。

本文將討論以下內容:

  • 使用Web組件建立模組化的Web門戶應用;
  • 個人化特性和自訂特性;
  • 將自訂使用者控制項作為Web組件使用;
  • 建立一個個人化特性的提供者;

  現今門戶應用非常流行,好的門戶都有共同而顯著的特點。那就是都會給訪問者提供雅觀的資訊,並且這些資訊都是通過模組化的、一致的、易於瀏覽的使用者介面提供的。一些綜合性的門戶網站走得更遠,它們甚至允許網站成員提供內容、上傳文檔以及個人化門戶頁面。
  微軟為 Windows Server 2003 平台增加了一個可擴充的門戶應用程式框架,隨之發布了一個 Windows SharePoint 服務 ,這個架構提供了門戶應用程式框架必須的一些基本元素,其中包括網站成員的支援、內容和文件管理、使用 Web 組件以模組化的形式展示資料等等。
  Web 組件提供了支援自訂特性和個人化特性的基礎功能。在Windows SharePoint服務網站裡面,通過配置網站,門戶應用的使用者能夠添加、配置、刪除Web組件,這樣他們就能輕鬆地個人化或者定製頁面了。基於Windows SharePoint服務的網站還提供了一種簡便而且強大的方法擴充網站的功能,那就是:開發自訂Web組件。建立支援定 制特性和個人化特性的Web組件時,你只需要簡單地在你的Web組件類裡面增加一些屬性以及設定幾個特殊的標籤就可以了。那些繁瑣複雜的工作都由 Windows Sharepoint 服務的Web組件基礎結構來完成,比如:序列化、儲存和讀取與網站自訂特性和成員個人化特性相關的資料。
  ASP.NET 2.0 引入了一套Web組件控制項集,這套控制項集與 Windows SharePoint 服務提供的功能很相似,它們 被設計用來完成序列化、儲存和讀取網站自訂特性和成員個人化特性相關資料等功能。但是它們更獨特和更靈活,它們與 SQL Server 或 Active Directory 不是緊耦合的。對於那些希望使用基於表單驗證技術建立門戶,或者不想受限於某一特定資料庫解決方案的公司來講,這無疑是一個好訊息。

 
圖1:使用模組化Web組件設計的一個樣本門戶應用

  本文將向你展示一個用  ASP.NET 2.0 Web 組件開發的樣本門戶應用,其主要目的是讓你瞭解為門戶應用開發Web組件時 ,你將面臨的一些重要的設計問題。首先,我們將著重介紹新的 ASP.NET 2.0 Web組件控制項集涉及的一些基本概念和控制項類型。例子參見圖1。

Web組件基礎

  用來放置Web組件的頁面,我們可以稱之為Web組件頁面。2所示,一個Web組件頁面需要一個WebPartManager 控制項(只能有一個)和一個或多個的 WebPartZone 控制項。還可以包括一個 EditorZone 控制項或者 CatalogZone 控制項(不是必需的)。需要注意的是,在.aspx檔案中,WebPartManager 控制項的標籤必須出現在與Web組件 基礎結構相關的任何其它控制項標籤之前,比如:WebPartZone 控制項、EditorZone 控制項、CatalogZone 控制項。為了更好地控制Web組件頁面的布局和表現形式,你還可以在aspx檔案中使用HTML表格,將不同的 zone 控制項布局到不同的地方。


圖2:一個Web組件頁面的典型布局

  我們先來看一個簡單的Web組件頁面例子,該頁麵包含 WebPartManager 控制項和 WebPartZone 控制項:

<asp:WebPartManager ID=" WebPartManager1" runat="server" /><asp:WebPartZone ID="WebPartZone1" runat="server" HeaderText="Zone 1">  <ZoneTemplate>       <!-- time to add a Web Part -->     </ZoneTemplate>   </asp:WebPartZone>      

  在頁面裡放置了一個 WebPartZone 控制項之後,就可以使用Web組件定義來建立Web組件執行個體了。有二種不同的方法可以建立Web組件定義。第一種方法是建立一個從 WebPart 類繼承的類,第二種方法是建立一個使用者控制項。 本文稍後的部分,我們將詳細探討這兩種方法之間的不同。現在,我們先建立一個從WebPart類繼承的簡單的類(參見圖3)。
  每個Web組件執行個體都存在於一個頁面特定的 WebPartZone 控制項的某個索引位置上。一個 WebPartZone 控制項可以包含多個Web組件。4所示,在 WebPartZone1 控制項裡面有二個Web組件執行個體。


圖4:在一個特定zone控制項中的Web組件

  你可以通過編程方式和聲明方式將Web組件添加到某個區(zone)中。稍後你還可以看到如何將Web組件添加到組件目錄中。當你建立了一個 CatalogPart 控制項以後,使用者就可以在運行時將一個新的Web組件添加到WebPartZone控制項中。
  以編程方式將Web組件添加到 WebPartZone 控制項裡面的方法取決於需要添加的Web組件的類型。如果是一個從 WebPart 繼承的類,需要以編程方式建立一個 該類的執行個體,然後調用 WebPartManager 類的 AddWebPart 方法。調用 AddWebPart 方法時,你需要傳入的參數包括:Web組件的執行個體、 目標 WebPartZone 控制項、以及Web組件在 WebPartZone 控制項中的索引位置。代碼如下:

// create Web Part instance from WebPart-derived classWebPart wp1 = new WingtipWebParts.HelloWorld();WebPartManager1.AddWebPart(wp1, WebPartZone1, 0);      

  此即通過編程方式將Web組件添加到 WebPartZone。聲明方式是在Web組件頁面的.aspx檔案中定義控制項標籤。當使用者訪問頁面時,如果你希望某個Web組件出現在特定的 WebPartZone 控制項中,你可以在 WebPartZone控制項中添加一個 ZoneTemplate。代碼如下:

<%@ Register Assembly="WingtipWebParts" Namespace="WingtipWebParts"TagPrefix="Wingtip" %><asp:WebPartManager ID=" WebPartManager1" runat="server" /><asp:WebPartZone ID="WebPartZone1" runat="server" HeaderText="Zone 1">  <ZoneTemplate>    <Wingtip:HelloWorld runat="server" id="HelloWorld" />  </ZoneTemplate></asp:WebPartZone>      

  別忘了給Web組件“打扮”一下,因為如果不這樣的話,你的Web組件看起來會很乏味的。內聯門戶網應用需要的一個通用特性就是能夠給網站“換膚”,根據訪問者的喜好改變Web組件的 外觀。過去,這意味著你要自己建立一套架構去支援改變控制項呈現方式的功能,而這需要做大量的工作。ASP.NET 2.0 引入了“主題”的概念,其中包括一系列的風格屬性和控制項屬性,這些屬性可以應用到單個控制項、整個頁面甚至整個應用的全域範圍。
  為了讓你的門戶應用看起來顯得優雅和專業,你需要定製所有 WebPartZone 控制項、EditorZone 控制項和 CatalogZone 控制項的 外觀。當你剛開始做這件事的時候,你會覺得這種工作非常乏味。因為你需要給Web組件、Editor組件以及Catelog組件的內容區、標題列和動態菜單等等地區換膚和修改顯示內容。幸運的是,新的ASP.NET 2.0 的主題特性可以將這些.aspx檔案中有關介面工作的成果提取到可以重用的.skin檔案和.css檔案中。這篇文章的樣本門戶應用程式就是使用換膚和主題功能來定製Web組件的 外觀的,你可以到MSDN雜誌的網站上下載。

顯示模式和頁面範圍

  WebPartManager 控制項的一個單一執行個體運行在每個Web組件頁面中,它負責管理Web組件執行個體以及Web組件如何與WebPartZone控制項互動。WebPartManager控制項還提供了一個可程式化介面,可以用來切換Web組件頁面的顯示模式,例如:你可以在以下 三種模式之間切換:瀏覽模式、設計模式和編輯模式。例如:要通過程式將當前頁面切換到設計模式,你只需要添加一個連結控制項,在這個控制項的事件處理常式中將DisplayMode屬性設定為DesignDisplayMode即可。代碼如下:

WebPartManager1.DisplayMode = WebPartManager.DesignDisplayMode;      

  理解Web組件頁面每種顯示模式之間的區別是很重要的。預設情況下,Web組件頁面處於瀏覽模式,此模式不允許使用者修改任何的Web組件。當切換到設計模式的時候,使用者就能夠在WebPartZone內部或者不同的 區之間移動Web組件了。圖5列出了所有的顯示模式。
  ASP.NET 2.0 Web組件控制項會在後台產生所有必需的DHTML和Javascript代碼,讓使用者在瀏覽器裡可以進行拖放操作。在不支援必 需的DHTML和Javascript特性的瀏覽器裡,除了拖放操作之外的所有其它編輯功能都可以使用。這意味著你不必擔心要強制所有的客戶使用Microsoft IE5.0或以上的瀏覽器。ASP.NET 2.0 Web組件控制項還支援管理個人化資料的儲存和擷取,能夠記住使用者上一次將Web組件放在了什麼地方。
  除了支援使用代碼切換顯示模式之外,WebPartManager控制項還提供了允許Web組件頁面在使用者範圍和共用範圍之間切換的方法。頁面範圍是指對Web組件的修改是自訂動作還是個人化操作。所有的使用者都能看到自訂動作的結果,而只有使用者自己才能看到個人化操作的結果。改變Web組件頁面的範圍可以通過調用WebPartManager 控制項的 ToggleScope 方法來實現,代碼如下:

WebPartManager1.Personalization.ToggleScope();

  預設範圍即使用者範圍,也就是說對Web組件的修改被記錄為個人化操作,只能被目前使用者看到。成功地調用ToggleScope方法會把Web組件頁面改變到共用範圍,這樣的話,對Web組件的修改就會被記錄為自訂動作。共用範圍的作用是為了允許管理員或者網站設計人員統一修改Web組件頁面中的Web控制項,讓所有使用者都能看到這種改變。如果有衝突,個人化修改總是優先於全域自訂動作。
  目前使用者並不總是能夠成功地進入共用範圍。預設情況下,任何使用者都沒有這樣的許可權。只有在Web.config檔案中使用者被賦予了這樣的許可權才行。下面是一個例子,它允許所有擁有admin或者site_designer角色的使用者可以進入共用範圍和修改全域自訂資料:

<webParts>  <personalization>    <authorization>      <allow roles="admin, site_designer" verbs="enterSharedScope" />    </authorization>  </personalization></webParts>      

屬性和個人化

  每一個Web組件對象都有一套標準的屬效能夠被自訂或者個人化。例如,每個Web組件都有一個Title屬性,在被加入WebPartZone之後,還能夠被自訂。EditorZone控制項和一些Editor組件允許使用者對Web組件屬性做修改。
  當使用者將Web組件頁面切換為編輯模式時,Web組件的菜單提供了一個編輯命令。在一個Web組件上調用編輯命令會顯示出一個EditorZone控制項,此控制項是放在相關的 區控制項中的。ASP.NET 2.0提供了一些內建的Editor組件,用來修改標準的Web組件外觀、行為和布局。
  通過添加一些能夠被個人化的自訂屬性,Web組件個人化配置資料能夠被輕鬆地擴充。你只需要在Web組件類的定義裡面添加這些屬性,並且打上諸如:Personalizable、WebBrowsable、WebDisplayName之類的特性標籤就可以了。當你完成這些之後,Web組件控制項會協助你儲存和擷取這些被個人化或者自訂的屬性值。
  當你建立某個個人化屬性時,通常會同時定義一個私人欄位,代碼如下:

private bool _HR = true; 
[Personalizable(PersonalizationScope.User), WebBrowsable, WebDisplayName("                     Show HR News"), WebDescription("                     Use this property to show/hide HR news")] 
public bool HR { get { return _HR; } set { _HR = value; } }

  如果你想允許你的使用者像這樣個人化某個屬性,你只需要在當前頁面的EditorZone控制項中添加一個PropertyGridEditorPart組件就可以了。圖6顯示了當你這樣做的時候,使用者會看到什麼:


圖6 Editor 組件允許使用者個人化 Web 組件

  如果你定義的某個Web組件屬性是字串或者數字類型的,PropertyGridEditorPart 組件會提供一個文字框讓使用者修改屬性值。如果這個屬性是布爾類型的,PropertyGridEditorPart組件會提供一個 複選框,6所示。
  圖7給出了從 Windows SharePoint 服務Web組件開發中學來的一個極好的編程技巧:你可以定義一個基於枚舉類型的個人化屬性。
  建立 WebBrowsable 以及基於枚舉類型的個人化的屬性,其真正價值在於 PropertyGridEditorPart 組件會產生一個包括所有可選屬性值的下拉式清單,正7中顯示的 Timeframe 屬性那樣。對使用者來說,這很方便,而且有助於保證使用者選擇一個有效屬性值。
  關於 Timeframe 屬性,還有一件事值得留意。它被加上了一個 Personalizable 特性,特性的值為PersonalizationScople.Shared。當屬性像這樣被定義為共用屬性的時候,它只能被自訂,而不可以個人化。既然共用屬性不能被個人化,噹噹前頁面在使用者範圍的時候,PropertyGridEditorPart 組件不會顯示這個屬性,而只會在共用範圍顯示這個屬性。

Web組件目錄

  我們已經見過了如何在 WebPartZones 控制項中事先放入Web組件。你還可以用另外一種方法完成這個功能,那就是允許使用者在運行時添加新的Web組件。通過使用 CatalogZone 控制項和 CatalogParts 類型的組件,比如 :PageCatalogPart 和 DeclarativeCatalogPart 來達到這個目的。(參見圖8)
  當你用這個方法添加某個 CatalogZone 和 CatalogPart 之後,使用者就可以在運行時動態添加Web組件了,介面就像9中所示的那樣。


圖9:CatalogZones允許使用者動態添加Web組件

  首先,你需要理解 PageCatalogPart 的用途。在設計顯示模式或者編輯顯示模式下,使用者能調用Web組件的“關閉”命令。當使用者關閉 某個Web組件時,Web組件和相對應的個人化或者自訂配置被保留下來,以便使用者可以在以後再次添加該Web組件。因此,PageCatalogPart 控制項顯示所有已經被關閉的Web組件的列表,使用者可以再次加到頁面上去。
  “關閉”命令與“刪除”命令是不同的。“刪除”命令在出現在編輯顯示模式。當使用者刪除一個Web組件時,有關這個組件的所有相關資訊,包括自訂和個人化資料,全部會被刪除掉。
  DeclarativeCatalogPart 組件能夠以聲明的方式添加Web組件。圖8中的代碼說明了怎樣定義這個目錄,其中使用了一個自訂名字的組件 WeatherWebPart。採用這種方法,你就能夠給使用者提供各種各樣的Web組件了。
  作為本文的補充,同時為了給你提供更多的有關建立Web組件頁面的詳細資料,我們建議大家去閱讀 Stephen Walther 所寫的“Introducing the ASP.NET 2.0 Web Parts Framework”一文 。文中提供了更詳細的資訊,以及使用 EditorZones 和 CatalogZones 建立Web控制項頁面的完整例子。Stephen 還講了一些更進階的話題,包括 Verbs、Connections 和 Web 組件的匯入匯出等內容。

ASP.NET 2.0 門戶應用開發

  除了Web組件自身體繫結構之外,在ASP.NET 2.0裡面還有一些新的特性使得內部門戶網站的開發更加有吸引力。正如文章前面所說,主題和換膚的引入使得風格屬性可以方便直接地獨立於門戶頁面,不用修改每個頁面,就可以做 統一的風格改變。當然,更令人興奮的是主版頁面(Master Pages)的引入。使用主版頁面,就可以將總體的 WebPartManager 控制項和所有 WebPartZones 控制項放在一個單獨的模版頁面,其它頁面都可以繼承這些基礎外觀和功能。在樣本門戶應用中,我們用到的一個有趣的技術就是在 主版頁面每個 WebPartZone 控制項的ZoneTemplate 模版中都添加一個 ContentPlaceholder 控制項。這樣的話,使用這個 主版頁面的內容頁面可以使用這個內容控制項來添加其自己的Web組件,並且映射到相應的 ContentPlaceholder 控制項中。
  為一個門戶網站設計主複本頁時,你必須考慮的一件事是如果給使用者提供自訂特性。正如你已經看到的,根據頁面中包含的不同類型的區控制項,有幾種不同的修改頁面的自訂模式 供讓使用者選擇。
  其中一種給使用者顯示自訂選項的方法是將 WebPartManager 控制項和一系列按鈕(典型的是LinkButton)封裝為一個使用者控制項,然後將這個控制項放在 主版頁面中,就可以為網站中所有頁面提供自訂選項。如果你的網站有多於一個的主控頁面,用來給不同的頁面提供不同的布局,封裝為一個使用者控制項(我們可以叫它WebPartManagerPanel)也是很有用的。之前圖1中給出的那個門戶應用的菜單條就給出了一個樣本的使用者控制項,可以顯示出當前 WebPartManager 的顯示模式和範圍,還提供了一些 LinkButton 將頁面改變 為 WebPartManager 控制項支援的其中一種編輯模式。(這就是我們樣本門戶應用使用的使用者控制項)。
  在你的 WebPartManagerPanel 控制項中可以提供的另外一個有用的特性是可以根據目前使用者和當前頁面顯示或者隱藏相應的顯示模式功能表項目。通過查看 WebPartManager 的 SupportedDisplayModes 這個collection屬性中包含哪些支援的顯示模式,就可以顯示或隱藏相應的顯示模式功能表項目。例如,要找出當前頁面是否支援CatalogDisplayMode,你應該寫如下的代碼:

if (WebPartManager1.SupportedDisplayModes.Contains(    WebPartManager.CatalogDisplayMode)) {  //enable catalog display mode LinkButton here...}      

  還應該注意,如果目前使用者沒有相應的許可權,調用 ToggleScope 將會失敗。所以通過代碼判斷一下是否顯示或隱藏讓使用者進入共用範圍的介面元素是個好主意,查詢 WebPartManager 控制項的 Personalization 屬性的 CanEnterSharedScope 屬性可以做到這件事。代碼如下:

if (WebPartManager1.Personalization.CanEnterSharedScope)  {  // display UI element that allows user to enter shared scope}      

  本文附帶的樣本應用中的 WebPartManagerPanel 使用者控制項包含了一個完整的實現,它可以根據目前使用者和當前頁面的能力動態地調整 窗格的顯示。

將使用者控制項作為Web組件

  在使用 Windows SharePoint 服務建立Web組件的時候,最令人沮喪的一件事情就是你必須用代碼去建立控制項的整個介面,設計器一點幫不了忙。因為 許多Web組件都是一系列互相互動的伺服器端控制群組成的,在建立Web組件時,不能使用 Visual Studio 的設計器是一件很不幸的事情。一個顯而易見的解決方案就是允許開發人員建立使用者控制項,並且可以作為Web組件使用。(一個叫 SmartPart 的第三方工具提供了在 Windows SharePoint服務中可以將使用者控制項作為Web組件使用)。
  ASP.NET 2.0 Web組件解決了這個問題,它可以允許任何控制項直接作為Web組件使用,不用修改或者封裝這些控制項。這不僅可以將使用者控制項 結合到Web組件集合中,而且還可以輕易地將現有 asp.net 頁面中使用的那些自訂控制項整合起來。
  這種方法內部的工作原理是,如果一個標準控制項(不是Web組件)被加入到 WebPartZone 控制項中,系統會隱含地調用 WebPartManager.CreateWebPart 方法,這個方法會建立一個 GenericWebPart 類的執行個體,並且用 添加的那個控制項去初始化這個執行個體。GenericWebPart 從基類 WebPart 中繼承,提供了核心Web組件屬性實現。當構建 GenericWebPart 控制項的時候,它會將初始化的那個控制項作為子控制項加入。在頁面呈現過程中,就像大多數複合控制項那樣,GenericWebPart自身不會在 響應緩衝中輸出任何內容,只是作為輸出子控制項內容的一個代理。最終結果是你可以在頁面中的 WebPartZone 控制項裡面加入任何控制項,不用擔心它不會運行。例如,下面的頁面定義了一個 WebPartZone 控制項,裡麵包括一個使用者控制項和一個標準日曆控制項,在建立的時候,這兩個控制項都會被隱含地封裝成為一個 GenericWebPart 類的控制項。代碼如下:

<%@ Register Src="webparts/CustomerList.ascx"     TagName="CustomerList" TagPrefix="Wingtip" %><asp:WebPartManager ID=" WebPartManager1" runat="server" /><asp:WebPartZone ID="WebPartZone1" runat="server" HeaderText="Zone 1">  <ZoneTemplate>    <Wingtip:CustomerList runat="server" id="CustomerList" />    <asp:Calendar runat="server" id="CustomerCalendar" />  </ZoneTemplate></asp:WebPartZone>      

  和標準的Web組件一樣,動態建立被 GenericWebPart 封裝的控制項也是可以的。如果是使用者控制項,首先,你必須調用 Page.LoadControl 來動態地載入和建立使用者控制項執行個體。其次,還必須顯式地給這個控制項設定一個唯一的ID。再者,你還必須調用 WebPartManager 對象的 CreateWebPart 方法去建立一個 GenericWebPart 類的執行個體來作為使用者控制項執行個體的封裝。最後,將獲得的 GenericWebPart 執行個體的引用作為參數傳給 AddWebPart 方法,並且指定要加入的WebPartZone。代碼如下:

// create Web Part instance from User Control fileControl uc = this.LoadControl(@"webparts\CompanyNews.ascx");uc.ID = "wp2";GenericWebPart wp2 = WebPartManager1.CreateWebPart(uc);WebPartManager1.AddWebPart(wp2, WebPartZone1, 1);      

  這種技術的唯一缺點就是你無法控制Web組件的一些專用特性,因為你的控制項不是從 WebPart 類繼承的,而只有 GenericWebPart 是從 WebPart 類繼承的。一旦你運行擁有由 GenericWebPart 封裝的控制項的頁面,你馬上就會很明顯地發現一個現象,不想大多數Web組件,這些Web組件預設是無標題的,而且也沒有相關的表徵圖和描述資訊。圖10給出了一個 由 GenericeWebPart 控制項封裝的帶有預設標題(無標題)和表徵圖的樣本使用者控制項。


圖10 GenericWebPart

  其中一種解決方案是,在你的使用者控制項中,增加一個Init事件處理常式。如果你的控制項由 GenericWebPart封裝(通過查詢 Parent 屬性的類型可以判斷),你就應該在程式中設定 GenericWebPart 類的一些屬性,代碼如下:

void Page_Init(object src, EventArgs e) {  GenericWebPart gwp = Parent as GenericWebPart;  if (gwp != null)  {    gwp.Title = "My custom user control";    gwp.TitleIconImageUrl = @"~\img\ALLUSR.GIF";    gwp.CatalogIconImageUrl = @"~\img\ALLUSR.GIF";  }}      

  當你再次運行此頁面時,一旦使用者控制項被 GenericWebPart 封裝,對 GenericeWebPart 父控制項的屬性的修改會反映在包含你的控制項的Web組件上。圖11給出了新的設定過屬性的使用者控制項,請注意標題和表徵圖。


圖11 標題和表徵圖

  另外一個更有吸引力的解決方案是直接在你的使用者控制項類裡實現 IWebPart 介面。既然使用者控制項從來不直接查詢Web組件的屬性,因為那些資訊是由 GenericWebPart 類處理的,這樣做初看起來好像沒什麼協助。幸運的是,GenericWebPart 類的設計者意識到這種需求,如果控制項實現了 IWebPart 介面, 那麼在 GenericeWebPart 類中實現屬性就會自動委託所封裝的控制項。
  所以定製某個使用者控制項的Web組件特性僅僅是實現 IWebPart 介面,並填充介面中定義的七個屬性就可以了。圖12中的代碼給出了使用者控制項的 後台代碼類的一個例子,實現了和之前我們動態修改 GenericWebPart 屬性一樣的結果。
  你可能還會考慮給你的使用者控制項建立一個另外的基類,這個基類從 UserControl 繼承,並且實現了IWebPart介面,然後就可以被你的門戶應用中所有的使用者控制項所繼承。我們在這篇文章的樣本應用中就是這麼做的。採用這種方法,你的使用者控制項就能在 它們的建構函式中初始化其所需的屬性,其它的就由基類去控制了。圖13給出了一個實現 IWebPart 介面的使用者控制項基類以及一個與之相對應的後台類的代碼, 該使用者控制項使用這個基類設定標題和表徵圖屬性。
  現在你擁有了建立使用者控制項的這麼多的靈活性,你可能會問:當你擁有設計器支援的使用者控制項,同時還可以定製Web組件特性,那為什麼還要建立自己自訂 的控制項呢?實際上,有幾個原因需要你這樣做。其中一個原因是你不能給使用者控制項添加定義的動作(verbs)。如果需要那樣做,你必須直接從 WebPart 繼承,然後重寫Verbs屬性。當然,你也可以考慮在你的控制項中實現 IWebEditable 介面。
  另外一個原因是使用者控制項局限於應用程式的目錄,除非你將.ascx檔案從一個項目複製到另外一個項目的目錄下,否則你不可能在多個Web應用程式中共用使用者控制項。另一方面,自訂Web組件類繼承自 WebPart 類,能夠被編譯到一個可重用的dll裡面, 並且部署到全域組件快取(GAC)。還有一點,通過自訂Web組件類,你還可以給你的控制項寫一個自訂的設計器,以改變在 Visual Studio 中預設的外觀,而且你還可以在這個Web組件類被放在工具箱的時候,建立一個表徵圖。圖14提供了一個特性對比表,讓你決定是選擇自訂Web組件還是使用者控制項。

Web組件和個人化特性提供者程式

  提供者程式是ASP.NET 2.0的一個新特性,這也是你能在這個版本中看到如此之多內建的功能完整的控制項只需要很少的甚至不需要任何代碼就能運行 的一個主要原因。提供者程式背後的基本思路是為某個特定的特性定義一套公用的與資料相關的任務,將那些任務聚集到一個抽象類別聲明中,該抽象類別從公用的 ProviderBase 類繼承。在本文探討的個人化特性中,必須明確提供的資料相關任務包括:

  • 為某個特定頁面和使用者儲存Web組件的屬性和布局;
  • 為某個特定頁面和使用者裝載Web組件的屬性和布局;
  • 儲存常規Web組件屬性和特定的頁面配置( 用於常規定製);
  • 載入常規Web組件屬性和特定的頁面配置(用於常規定製);
  • 將某個特定頁面和使用者的Web組件屬性和布局重設為其預設值 ;
  • 將某個特定頁面的Web組件屬性和布局重設為其預設值(用於常規定製);

  還有其它的一些屬於個人化體繫結構的附屬特性也需要持久化儲存的能力,但是基本上可以歸結為以上六種需求。如果我們假設有一個類可以完成這六個動作,而且能夠成功 地儲存和恢複資料,那麼當網站啟動並執行時候,每個頁面上的 WebPartManager 控制項就能夠使用那個類儲存和恢複所有的個人化和自訂資料。定義這些方法的抽象類別的名字叫 PersonalizationProvider 類, 預設情況下使用的一個具體的衍生類別是 SqlPersonalizationProvider 類。圖15顯示了代表我們定義的 六個功能的那三個方法。請注意,不論輸入的 userName 參數是否為空白,每個方法都能夠完成使用者個人化或者共用自訂資料的功能。
  所有的個人化資料都儲存為普通的位元據(byte[]),預設的 SqlPersonalizationProvider 類會將這些資料寫入資料庫中的一個image類型的欄位。既然 ASP.NET 2.0 知道有一個類可以提供這些方法,它就能夠在基礎的控制項集裡面建立比以前更加多的邏輯。在我們的 案例中,每個使用Web組件的頁面上的 WebPartManager類負責正確地調用當前的 PersonalizationProvider 類來序列化和恢複每個頁面的個人化設定。圖16展示了 EditorZone 控制項與預設的 SqlPersonalizationProvider 類是如何互動的。


圖16 互動

  你使用 ASP.NET 2.0 越多,對該提供者架構的例子瞭解就會越多。比如其中有成員提供者、角色管理提供者、網站地圖提供者、網站監控提供者等等很多的提供者,所有的提供者程式都定義了一個相似的核心方法集與控制項互動。

修改個人化資料存放區

  和大多數ASP.NET 2.0中的提供者程式一樣,預設的個人化提供者程式是面向 SQL Server 後台儲存而實現的。如果不修改設定檔,預設的 SqlPersonalizationProvider 採用 SQL Server 2005 Express Edition 連接字串,支援基於本地檔案的資料庫。這個連接字串就像下面這樣:

data source=.\SQLEXPRESS; Integrated Security=SSPI; AttachDBFilename=|DataDirectory|aspnetdb.mdf; User Instance=true

  使用 SQL Server 2005 Express Edition 基於檔案的資料庫的一個優勢就是它可以被動態建立,不需要使用者任何附加的設定。這意味著你可以建立一個全新的網站,不用設定資料庫就能啟用個人化特性,也能夠運行!當你最初與網站互動時,系統會在網站的 App_Data 目錄中產生一個新的 aspnetdb.mdf 檔案,並且用支援所有預設提供者程式所需的表和預存程序來初始化該資料庫。
  對於不需要擴充規模或者支援很多並發使用者的小網站來說,這簡直太好了。但是對於企業系統來說,需要將資料存放區到某個被全面管理的、專用的資料庫伺服器上。幸運的是,修改 SqlPersonalizationProvider 使用的資料庫是非常簡單直接的。SqlPersonalizationProvider 的配置將連接字串初始化為 LocalSqlServer,這意味著它會在設定檔的<connectionStrings>節中尋找名字為 LocalSqlServer 的配置項,使用相關的連接字串去開啟到資料庫的串連。預設情況下,這個字串就是你在前文所看到的,意味著它會寫入一個本地的 SQL Server 2005 Express Edition .mdf 檔案。要修改它,你必須首先清除掉 LocalSqlServer 連接字串集合,在你的 Web.config 檔案中重新設定一個新的連接字串值。(或者你也可以修改機器範圍的 Machine.config檔案,去影響這台機器上的所有網站)以下是一個 Web.config 檔案的例子,它將提供者資料庫的值修改為指向一個本地的 SQL Server 2000 的執行個體:

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/   V.2.0">  <connectionStrings>    <clear />    <add name="LocalSqlServer" connectionString=        "server=.;integrated security=sspi;database=aspnetdb"/>  </connectionStrings>  ...</configuration>

  在修改生效之前,本地 SQL 伺服器上必須有一個名為 aspnetdb 的資料庫,裡面有SqlPersonalizationProvider 所需的表和預存程序。隨 ASP.NET 2.0 發行了一個名為 aspnet_regsql.exe 的工具,用它可以建立這個資料庫。當以預設設定運行該程式時,它將建立一個名為 aspnetdb 的本機資料庫,其中有所有提供者程式所必需的表和預存程序,或者你可以選擇將這些表和預存程序安裝到一個已有的資料庫中。所有的表和預存程序的名字都會以“aspnet”開頭,所以不太可能會與任何現有的表重複。
  和所有 ASP.NET 2.0 的提供者程式一樣,這種間接的模式提供了一種非常靈活的架構,使得不用修改任何頁面或者Web組件,就可以將後端的資料存放區完全替換掉。

建立自己的個人化提供者程式

  為個人化提供者程式修改連接字串的能力賦予了你一定程度的靈活性,但是在 SqlPersonalizationProvider 內部還是使用命名空間 System.Data.Sql.Client 的功能來存取資料。這意味著你必須使用 SqlServer 資料庫。如果你需要將個人化資料儲存到另外一種資料庫中,或者可能是另外一種完全不同的資料存放區中,你將不得不更進一步,建立你自己定製的個人化資料提供者。幸運的是,大多數困難的工作已經為你做好了,而且也便於使用。作為個人化資料存放區到另外一種資料存放區的例子,本文的樣本門戶網站有一個自訂提供者程式的完整實現,名為 FileBasedPersonalizationProvider 類,它將所有的個人化和自訂資料儲存到應用程式 App_Data 目錄下的一個本地二進位檔案中。這個二進位檔案的名稱為每個使用者和路徑唯一產生,每個路徑下還有一個唯一的通用的使用者設定檔。
  建立一個自訂的個人化資料提供者,你必須首先建立一個從 PersonalizationProvider 基類繼承的新的類,然後重寫所有從基類繼承的抽象方法。圖17中給出的類定義示範了如何做到這一點。
  為了使你的提供者程式能夠運作,其實只有兩個重要的方法必須要實現:LoadPersonalizationBlobs 和 SavePersonalizationBlob。這兩個方法完成了個人化資料的二進位序列化功能,當載入頁面時,個人化架構會調用它們。當Web組件頁面處於編輯、目錄或者設計模式時,如果資料被修改了,個人化架構還會調用它們將資料寫回。(典型情況下是基於一個特定的使用者)。
  在下載的範例程式碼中,SavePersonalizationBlob 的實現代碼將 dataBlob 參數寫入一個基於傳入的使用者名稱稱和路徑唯一命名的檔案。相似地,LoadPersonalizationBlobs 的實現代碼會尋找這個檔案(使用相同的命名方法),並返回一個使用者個人化的或者共用的blob資料。如果傳入的userName參數為空白,這兩個方法預設都會儲存或者裝載共用資料,如果不為空白,就會儲存或者裝載使用者個人化資料。圖18給出了樣本 FileBasedPersonalizationProvider 中這兩個方法的實現代碼,以及一對用來根據使用者名稱和路徑資訊產生唯一檔案名的 helper 方法。
  一旦提供者程式完全實現了,通過個人化配置節中的提供者節,你就可以將這個程式註冊為一個提供者程式。要想實際使用它,你必須在 Web.config 檔案中定義它為預設的個人化提供者。下面是一個將我們自訂的基於檔案的提供者程式作為預設提供者的例子:

<webParts>  <personalization defaultProvider="FileBasedPersonalizationProvider">    <providers>      <add name="FileBasedPersonalizationProvider"           type="Wingtip.Providers.FileBasedPersonalizationProvider" />    </providers>  </personalization></webParts>

  如果我們重新運行我們的網站,所有的個人化資料現在都會被儲存到一個本地的二進位檔案。顯然這不是最好的解決方案,但是範例程式碼提供了一些思路,讓你瞭解如何?你自己的個人化提供者,不論你想基於什麼樣的後端儲存都可以。圖19給出了我們新的提供者是如何插入到整個的Web組件體繫結構中去的。


圖19 使用 FileBasedPersonalizationProvider

更進一步

  到現在為止,你已經看到了如果使用 ASP.NET 2.0 和其新的Web組件控制項來建立具有豐富特性的支援自訂和個人化的門戶應用程式,而 ASP.NET 2.0 使得這一工作變得相當簡單。也許這個架構的最重要的特性是可外掛程式的能力。提供者架構使得將符合你的網站特性的個人化資料寫入後端資料存放區變得相對簡單,而且也不會被綁定到一個特定的序列化實現和資料存放區上。所以,現在就前進,大膽地使用ASP.NET 2.0 Web組件去建立可以自訂的網站吧!
  如果你喜歡這篇文章,在ASP.NET 2.0門戶應用中建立Web組件還有大量的東西需要學習。記得從MSDN雜誌網站下載本文的範例程式碼。在 ASP.NET 2.0 QuickStart tutorials 中也有一些例子可以拿來研究。我們還推薦你去看看 Fredrik Normén的網誌,裡面有一些有關 ASP.NET 2.0 Web 組件的有趣的例子。
 

作者簡介
  Ted Pattison
是一名作家和培訓師,通過 Pluralsight 提供一些易於上手的培訓課程,還通過 Ted Pattison Group 提供諮詢服務,還是幾本書的作者。
  Fritz Onion
是 Pluralsight 的合伙人。Pluralsight 是一家從事教育和內容建立的公司,他在該公司裡專註於 ASP.NET Web 開發,Fritz 還是 Essential ASP.NET (Addison Wesley 2003) 的作者。在www.pluralsight.com/fritz 上面可以看到他的網誌。

本文由 VCKBASE MTT 翻譯

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.