零代碼 Web 站點(轉載)

大多數重要的 Web 應用程序都需要某種數據存儲,不管它是 Microsoft SQL Server 數據庫、Microsoft Access 數據文件、XML 文件還是某些其他類型的數據源。根據應用程序的複雜程度,UI 顯示直接從數據存儲檢索的數據,或者從一組業務對象獲得的數據。在 ASP.NET 1.1 中,即使一個簡單的 Web 頁(用於顯示直接來自數據庫的產品列表)也需要大量代碼來連接數據庫,並將數據綁定到服務器控件。在 ASP.NET 2.0 中,許多常見的數據訪問情況可以只通過聲明 ASPX 標記來實現 — 不要求編程。

ASP.NET 2.0 中新的“零代碼”功能涵蓋最常見的數據訪問情況。最簡單的情況是使用一個服務器控件顯示數據源數據的單向數據綁定。這種情況的常見例子是在下拉列表中顯示州/省/市/自治區列表。一種更復雜的情況是使用多個控件的單向數據綁定,其中在一個控件中選擇的值會影響在另一個依賴控件中顯示的值 — 例如,在下拉列表中顯示國家/地區列表,然後當選中某個國家/地區時,在另一個下拉列表中顯示該國家特有的州/省/市/自治區列表。對於某些服務器控件,ASP.NET 2.0 甚至包括內置的排序和分頁功能。

ASP.NET 2.0 中令人印象最深刻的“零代碼”功能指:能夠輕鬆地提供添加、更新和刪除數據的用戶界面和數據訪問邏輯,而無需像在 ASP.NET 1.1 中一樣編寫這些基本操作所需的基礎結構代碼。

聲明性語言

零代碼 Web 站點這個短語可能有點用詞不當,因爲 ASP.NET 標記語言(即 ASPX 語言)正逐漸被認爲是一種聲明性編程語言。如果您具有嚴格的命令式編程背景,即使用過諸如 C、S、Java 和 Visual Basic 等編程語言,那麼將 ASPX 視爲一種編程語言也許聽起來有點令人困惑,因爲聲明性編程是一種很不一樣的編程模型。對於許多程序員而言,基於 XML 的語言“感覺”根本不像一種編程語言。命令性編程往往相當直接地意味着非常低級的計算機操作方式。在任何特定的時刻,程序都處於通過執行所提供的指令而達到的特定狀態。通過執行其他指令,程序會以一個新狀態結束。當用命令性語言編程時,您通過提供實現目標所需的特定操作(即,告訴計算機如何實現目標)來實現期望的目標。當用聲明性語言編程時,您指定目標,而編譯器或解釋器使用它預定義的算法來確定實現該目標的適當操作。

如果不習慣考慮聲明性編程,這些概念可能聽起來有點陌生,但您可能已經不知不覺地成爲了一名更有經驗的以聲明性方式編程的程序員。考慮以下聲明性代碼:

SELECT * FROM Products WHERE ProductID = 55

您可能會認爲這是 SQL 代碼。SQL 是一個非常流行的聲明性語言實例。SELECT 查詢表示一個最終結果:選擇 Products 表中 ProductID列值爲 55 的各行的所有列。將這種查詢表示爲一組可執行的操作,該任務由該查詢所發送到的任何數據庫的查詢處理引擎來完成。現在考慮一個 ASP.NET 標記塊:

<form runat="server"> 
<asp:TextBox id="txtCountry”Text="Canada”runat="server"/> 
<asp:Button id="btnSave”Text="Save”runat="server”/> 
</form>

該“代碼”沒有包含一組指令,而是定義一個最終結果:一個窗體包含一個用“Canada”預填充的文本框和一個標記爲“Save”的按鈕。ASP.NET 有一個預定算法,可以將這些聲明轉換成適合不同類型瀏覽器的輸出(例如,適合 Internet Explorer 的 HTML)。不必提供獲取正確輸出所需的任何特定操作,因爲 ASP.NET 替您負責這些工作。

正如本節中的應用程序所演示的,ASP.NET 標記只需很少的編程工作就可以提供很多功能。使用 ASPX 語言不只可以控制佈局或到 HTML 的簡單映射,ASPX 還允許定義行爲,包括豐富的用戶界面和數據庫通信。當使用 ASPX 時,您使用的遠不只是用於編碼用戶界面的數據格式 — 您正在使用一種最新和最流行的聲明性語言進行編程。

數據綁定

在發佈 .NET Framework 之前,數據綁定的名聲不佳,因爲對於需要複雜行爲的應用程序而言,使用 Visual Basic 6 非常麻煩。.NET Framework 1.0 版引入新的數據綁定功能,該功能模仿大多數開發人員自己編碼以獲取數據綁定行爲的做法。.NET Framework 的一個最了不起的功能是:可以使 Web 開發人員在 Web 窗體上使用高效而簡單的單向數據綁定。只要提供一個可綁定的服務器控件(例如具有數據源的 DropDownList),該服務器控件就可以負責循環數據,併爲每個數據項生成適當的 HTML。雖然這樣做非常簡單,但 ASP.NET 1.1 中的數據綁定仍需要代碼來創建數據源,將數據源分配給適當的數據控件,然後調用數據控件的 DataBind方法來實際使控件循環訪問數據源。在 ASP.NET 2.0 中,只需封裝數據源設置和 ASPX 中的綁定,而讓服務器控件負責其餘的工作。

演練

ASP.NET 2.0 中最簡單的數據綁定是數據源數據的只讀表格顯示。使用 Visual Studio 2005 IDE,首先創建一個新的 Web 窗體,並將數據源控件拖到該窗體上。此應用程序使用 SqlDataSource控件,不過還可以使用其他數據源控件,例如 Microsoft Access 數據文件或 XML 文檔。SqlDataSource控件負責連接到 Microsoft SQL Server 數據庫並檢索所請求的數據。

當將新的 SqlDataSource控件添加到窗體時,Data Source Configuration Wizard 可以指導您設置該控件。第一步是建立該控件與數據庫通信的連接設置。圖 6-1 顯示已經配置第一步中到 Northwind 數據庫的連接。


6-1 Data Source Configuration Wizard。

接着,指定希望數據源控件從數據源選擇的數據。此應用程序使用一個簡單的查詢來選擇 Northwind 數據庫中 Products 表的所有行:

SELECT * FROM [Products]

有了連接和 SELECT 查詢,SqlDataSource控件就具備從數據庫檢索數據所需的全部信息。嚮導所生成的 ASPX 標記的結果爲:

<asp:SqlDataSource ID="ProductsDS”Runat="server” 
SelectCommand="SELECT * FROM [Products]" 
ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"> 
</asp:SqlDataSource>

您將注意到,以聲明方式從 web.config 配置文件讀取連接字符串使用了新語法。web.config 中對應的項如下所示(爲提高可讀性,添加了換行符):

<connectionStrings> 
<add name="NorthwindConnection" 
connectionString="Server=(local); 
Integrated Security=True; 
Database=Northwind; 
Persist Security Info=True" 
providerName="System.Data.SqlClient”/> 
</connectionStrings>

既然 Web 窗體有了數據源控件,您就可以添加支持數據綁定的其他控件,並將它們綁定到數據源控件。對於簡單的表格顯示,新的 GridView控件不需要特殊的配置 — 只要爲其提供數據源控件的 ID,它就可以生成完整的數據表。可以使用 GridView的 Common Tasks 智能標記來分配數據源,或者只使用下面的 ASPX 標記來設置 GridView 的 DataSourceID屬性:

<asp:GridView ID="ProductsGrid”Runat="server”DataSourceID="ProductsDS"> 
</asp:GridView>

可視化 Web 設計器中的最終結果如圖 6-2 所示。SqlDataSource控件在設計視圖中是可見的,但當在 Internet Explorer 中查看時,只有由 GridView生成的數據表是可見的,如圖 6-3 所示。


6-2 使用零代碼綁定到SqlDataSource 的 GridView。


6-3 在 Internet Explorer 中查看的最終輸出。

雙向數據綁定

雖然使用零代碼進行單向數據綁定非常方便,但創建快速只讀顯示的總工作效率優勢不是那麼顯著。在 ASP.NET 1.1 中,更可怕的工作是爲 CRUD(創建、讀取、更新和刪除)操作進行雙向數據綁定,並提供一個可用的界面,包含諸如排序和分頁這樣的功能(例如,每頁顯示 10 條記錄,並有 Next 和 Previous 按鈕)。ASP.NET 2.0 簡化了雙向數據綁定工作,並同樣需要零代碼。奧祕在於數據源和 GridView控件的功能。

在此應用程序的第一頁,可以看到如何創建配置爲只選擇數據的 SqlDataSource 控件。但 SqlDataSource控件還可以用於更新、插入和刪除數據。對於不同類型的查詢,SqlDataSource控件只需適當的 SQL 命令和參數。可以自己輸入多行 ASPX 標記,也可以使用 Data Source Configuration Wizard 的高級功能來創建標記。

在爲 Data Source Configuration Wizard 設置數據選擇後,“Advanced Options”按鈕就可以使用了,它打開圖 6-4 所示的對話框窗口。選中第一個複選框將提示嚮導利用您提供的選擇信息來探測數據庫的數據結構。查詢完數據庫的結構後,嚮導將自動創建 SqlDataSource控件對數據庫執行 CRUD 操作所需的全部 ASPX 標記。


6-4 Data Source Configuration Wizard 的高級 SQL 生成選項。

在 Visual Studio .NET 2003 中,嚮導(例如 Data Adapter Wizard)可以幫助您創建進行 CRUD 操作的代碼,但結果是 Visual Basic(或者 C#)代碼,然後必須將其以編程方式綁定到數據控件。另外,將生成的代碼放置在代碼文件的“設計器生成的”區域,在這裏進行更改會有極大的危險,因爲如果再次調用嚮導這些更改將丟失。將生成的代碼移出“設計器生成的”區域意味着不能使用嚮導來更改適配器設置。相比之下,Visual Studio 2005 中的 Data Source Configuration Wizard 生成的 ASPX 標記用相應的參數聲明性地表示更新、插入和刪除命令。下面的 ASPX 清單顯示嚮導爲 Northwind Products 表生成的標記。

<asp:SqlDataSource ID="SqlDataSource1”Runat="server” 
SelectCommand="SELECT [Products].* FROM [Products]" 
ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>“ 
DeleteCommand="DELETE FROM [Products] 
WHERE [Products].[ProductID] = @ProductID" 
InsertCommand="INSERT INTO [Products] ([Products].[ProductName], 
[Products].[SupplierID], [Products].[CategoryID], 
[Products].[QuantityPerUnit], [Products].[UnitPrice], 
[Products].[UnitsInStock], [Products].[UnitsOnOrder], 
[Products].[ReorderLevel], [Products].[Discontinued]) 
VALUES (@ProductName, @SupplierID, @CategoryID, 
@QuantityPerUnit, @UnitPrice, @UnitsInStock, 
@UnitsOnOrder, @ReorderLevel, @Discontinued)" 
UpdateCommand="UPDATE [Products] SET 
[Products].[ProductName] = @ProductName, 
[Products].[SupplierID] = @SupplierID, 
[Products].[CategoryID] = @CategoryID, 
[Products].[QuantityPerUnit] = @QuantityPerUnit, 
[Products].[UnitPrice] = @UnitPrice, 
[Products].[UnitsInStock] = @UnitsInStock, 
[Products].[UnitsOnOrder] = @UnitsOnOrder, 
[Products].[ReorderLevel] = @ReorderLevel, 
[Products].[Discontinued] = @Discontinued 
WHERE [Products].[ProductID] = @ProductID"> 
<DeleteParameters> 
<asp:Parameter Type="Int32”Name="ProductID"></asp:Parameter> 
</DeleteParameters> 
<UpdateParameters> 
<asp:Parameter Type="String”Name="ProductName"></asp:Parameter> 
<asp:Parameter Type="Int32”Name="SupplierID"></asp:Parameter> 
<asp:Parameter Type="Int32”Name="CategoryID"></asp:Parameter> 
<asp:Parameter Type="String”Name="QuantityPerUnit”/> 
<asp:Parameter Type="Decimal”Name="UnitPrice"></asp:Parameter> 
<asp:Parameter Type="Int16”Name="UnitsInStock"></asp:Parameter> 
<asp:Parameter Type="Int16”Name="UnitsOnOrder"></asp:Parameter> 
<asp:Parameter Type="Int16”Name="ReorderLevel"></asp:Parameter> 
<asp:Parameter Type="Boolean”Name="Discontinued"></asp:Parameter> 
<asp:Parameter Type="Int32”Name="ProductID"></asp:Parameter> 
</UpdateParameters> 
<InsertParameters> 
<asp:Parameter Type="String”Name="ProductName"></asp:Parameter> 
<asp:Parameter Type="Int32”Name="SupplierID"></asp:Parameter> 
<asp:Parameter Type="Int32”Name="CategoryID"></asp:Parameter> 
<asp:Parameter Type="String”Name="QuantityPerUnit”/> 
<asp:Parameter Type="Decimal”Name="UnitPrice"></asp:Parameter> 
<asp:Parameter Type="Int16”Name="UnitsInStock"></asp:Parameter> 
<asp:Parameter Type="Int16”Name="UnitsOnOrder"></asp:Parameter> 
<asp:Parameter Type="Int16”Name="ReorderLevel"></asp:Parameter> 
<asp:Parameter Type="Boolean”Name="Discontinued"></asp:Parameter> 
</InsertParameters> 
</asp:SqlDataSource>

現在,其他數據控件(如 GridView)可用於更改數據庫中的數據(通過 SqlDataSource控件)。爲了使 GridView控件能夠更改數據,在“Properties”窗口中將 AutoGenerateDeleteButton和 AutoGenerateEditButton屬性設置爲 True,如圖 6-5 所示。


6-5 啓用數據更改的 GridView 屬性。

所得到的標記與單向數據綁定示例沒有太大的不同。添加的只是具有兩個屬性的 CommandField元素,它告訴 ASP.NET 生成編輯和刪除鏈接按鈕:

<asp:GridView ID="GridView1”Runat="server” 
DataSourceID="SqlDataSource1”DataKeyNames="ProductID"> 
<Columns> 
<asp:CommandField ShowDeleteButton="True” 
ShowEditButton="True"> 
</asp:CommandField> 
</Columns> 
</asp:GridView>

當在瀏覽器中查看該 GridView 時,可以看到每行數據的 Edit 與 Delete 鏈接。如果單擊 Edit 鏈接,該行就變成一組可編輯的控件(一般是文本框),如圖 6-6 所示。單擊“Update”將更改保存到基礎數據源(本例爲 Microsoft SQL Server)。這就是不用編寫一行代碼的雙向數據綁定!


6-6 在 Internet Explorer 中使用零代碼編輯產品。

修飾零代碼站點

這些零代碼功能的確令人注目,但目前在視覺上不是太有感染力或者不是太用戶友好。隨着家庭和商務用戶越來越習慣於利用 Web 來工作和娛樂,他們要求 Web 頁更具有視覺感染力 — 即使是編輯庫存數據。幸運的是,ASP.NET 2.0 對格式設置有大量的支持,換句話說,它可以改善零代碼 Web 站點的外觀。例如,GridView控件允許您控制顏色、字體和佈局信息來創建具有吸引力並且實用的數據表。

爲數據控件選擇一個專業的預打包外觀的最快方法是使用 Auto Format 功能,通過“Common Tasks”智能標記窗口可以訪問該功能,如圖 6-7 所示。還可以利用“Common Tasks”窗口來啓用 GridView控件的排序和分頁功能。如果您曾經嘗試使用 ASP.NET 1.1 中的分頁(例如 DataGrid),您就會意識到使用 GridView控件是多麼簡單 — 只需選中一個複選框即可。GridView和 SqlDataSource負責控制分頁的其餘細節。


6-7 GridView Common Tasks 智能標記對話框窗口。

Auto Format”對話框允許從許多預構建的格式中進行選擇,這些格式包括顏色、字體、行的樣式、可選行樣式、選定的行樣式、標題行樣式,等等。圖 6-8 所示的“Auto Format”對話框用於爲支持分頁(每頁最多 10 條記錄)但不支持排序的 GridView選擇一種格式。


6-8 “Auto Format”對話框窗口。

Visual Studio 2005 中的 Auto Format 功能爲選定的控件生成許多元素和屬性。利用 Sand & Sky 格式生成下面的標記:

<asp:GridView ID="GridView1”Runat="server” 
AutoGenerateColumns="False”DataKeyNames="ProductID" 
DataSourceID="SqlDataSource1”BorderWidth="1px” 
BackColor="LightGoldenrodYellow" 
GridLines="None”CellPadding="2” 
BorderColor="Tan”ForeColor="Black"> 
<FooterStyle BackColor="Tan"></FooterStyle> 
<PagerStyle ForeColor="DarkSlateBlue”HorizontalAlign="Center” 
BackColor="PaleGoldenrod"> 
</PagerStyle> 
<HeaderStyle Font-Bold="True”BackColor="Tan"></HeaderStyle> 
<AlternatingRowStyle BackColor="PaleGoldenrod"></AlternatingRowStyle> 
... 
</asp:GridView>

爲每個網格複製所有這些格式設置,從而使 Web 站點中數據網格的格式保持相同,這是一項非常費力的任務。幸運的是,通過創建一個新的主題(將在下一個應用程序中說明)可以將這種格式統一應用於 Web 站點。

當啓用分頁時,可以利用 GridView控件的 PageSize屬性來更改每頁顯示的數據行數。

小結

每一個 Web 應用程序都是獨特的,但總會有一些相似之處。一個相似之處是用於只讀顯示的基本數據訪問,或用於查看和修改數據的界面。ASP.NET 2.0 中新的零代碼功能使得編寫有用的 Web 應用程序構造塊而無需編寫任何代碼成爲可能!利用嚮導和其他設計時功能,Visual Studio 2005 可以生成定義重要 Web 應用程序的所有 ASPX 標記。數據訪問只是使用零代碼功能可以實現的常見任務之一。在下面的兩個應用程序中您將看到,無需編寫任何代碼還可以創建一個具有身份驗證功能的 Web 站點,包含新用戶註冊和用戶登錄。

應用程序:成員身份、配置文件和角色

此應用程序重點介紹 ASP.NET 2.0 中新的成員身份、配置文件和基於角色的安全功能,這使得確保 Web 應用程序的安全性更簡單。

新概念

大多數實際的 Web 應用程序都有一些受限區域,這些區域要求對用戶進行身份驗證,這樣才能根據是否授權用戶使用受保護的資源來授予或拒絕授予訪問權限。常見的例子是更新內容或查看站點統計信息的管理區域。ASP.NET 支持幾種身份驗證方案,包括集成的 Windows 身份驗證和 Passport 身份驗證。Windows 和 Passport 身份驗證僅對某些類型的應用程序是適合的,而對許多應用程序都不適用。Windows 身份驗證要求每個用戶都有一個用戶帳戶。Passport 身份驗證對於小型和中型站點而言成本過高。因此,許多站點選擇自定義身份驗證邏輯和自定義數據存儲來存儲證書和其他與用戶相關的數據,例如姓名、地址等。ASP.NET 1.1 站點可以利用 Forms 身份驗證完成諸如設置身份驗證 cookie 這樣的工作,它們可以使用一個通用的 API 來決定某個用戶是否登錄,以及該用戶屬於什麼授權角色。而創建管理用戶帳戶的基礎結構是 Web 開發人員的責任。

結果是將無數的 ASP.NET Web 應用程序投入生產,每個應用程序中實現的身份驗證模型幾乎完全相同。這種常用的身份驗證模型非常普遍,因此應當直接將它嵌入到 Web 應用程序平臺中。而這正是 ASP.NET 2.0 提供的新的成員身份和用戶配置文件功能。

成員身份

ASP.NET 2.0 中新的成員身份功能主要以三種方式簡化用戶管理:

1.自動創建數據存儲。(ASP.NET 2.0 爲 Access 和 Microsoft SQL Server 配備有內置的提供程序。)當嘗試使用成員身份功能時,ASP.NET 2.0 檢查是否配置了指定的數據存儲。如果沒有配置,ASP.NET 就創建。ASP.NET 2.0 中包含一個 Access 成員身份數據文件的模板和用於創建 Microsoft SQL Server 成員身份數據庫的腳本。

2.它們包含創建和驗證用戶以及顯示用戶特定信息和登錄狀態的服務器控件。新控件(如 Login、LoginStatus、CreateUserWizard 和 ChangePassword控件)提供預構建的用戶界面構造塊,包括用於最常見的與成員身份相關的任務的功能。在新 Web 控件應用程序中重點介紹這些控件。

3.它們提供一種以編程方式管理用戶的應用程序編程接口 (API)。Membership API 是通過 Membership 類訪問的,包含非常有用的方法,例如 CreateUser、DeleteUser 和 ValidateUser。

利用 ASP.NET 2.0 成員身份,不用編寫任何代碼就可以實際創建一個具有受保護頁、自動重定向到登錄頁、用戶創建(註冊)和用戶登錄的 Web 站點!在此應用程序的“演練”一節中您將看到,web.config 中的一些 XML 元素和一些服務器控件都是使用 ASP.NET 2.0 創建一個支持身份驗證的 Web 應用程序所需要的。

用戶配置文件

ASP.NET 2.0 中的成員身份功能允許您收集對於身份驗證非常重要的基本用戶信息,例如用戶名、密碼、電子郵件地址以及取回密碼所需的問題/回答機密對。但經常需要收集和存儲其他信息,例如姓名、Web 站點或 Weblog URL、職稱,還可能更多。ASP.NET 2.0 中新的用戶配置文件功能使您能夠定義應用程序必須存儲的有關用戶的其他信息。只需在 web.config 中指定需要的信息,然後在運行時填充特殊 Profile 對象中的相應字段。

ASP.NET 2.0 生成的 Profile 對象是特定於應用程序的,並且包含的強類型屬性映射到應用程序 web.config 文件中的項。在設計時,Visual Studio IDE 讀取這些項,並自動構建一個專有類(從 HttpProfileBase 繼承),這樣就可以在“Intellisense”菜單中使用特定於應用程序的屬性,並且可以通過編譯器進行驗證。此應用程序的“演練”一節說明如何在 web.config 中設置用戶配置文件,然後說明如何在運行時訪問特定於用戶的配置文件數據。

基於角色的安全性

可以通過在 Web 站點上對用戶進行身份驗證來識別用戶,但如果沒有其他的基於角色的授權,就不能根據用戶的身份限制其對 Web 資源的訪問。ASP.NET 始終內置支持通過用戶的安全用戶對象來確定用戶是否具有某種角色。使用 Windows 身份驗證時,角色來自於 Windows 安全組。但是使用 ASP.NET 1.1 中的 Forms 身份驗證時,必須構建自己的安全用戶對象,並在對每個 Web 請求進行身份驗證時填充它的角色集合。作爲開發人員,您還要負責編寫代碼來維護用戶角色的數據存儲,以及在運行時加載這些數據。

通過引入 ASP.NET 角色管理,ASP.NET 2.0 擴展基於角色的安全功能,包括新的 Roles 類和 web.config 的 <roleManager>配置節。ASP.NET 角色管理提供最常用的基於角色的安全功能,這些功能在以前必須自己構建。Roles 類提供的 API 可以用於創建和刪除角色,從角色中添加和刪除用戶,枚舉角色,枚舉具有某種角色的用戶,枚舉某個用戶所具有的角色等。ASP.NET 角色管理負責持久化角色成員身份數據,在運行時加載角色成員身份數據,以及爲用戶的安全用戶添加適當的角色。

演練

此應用程序演示如何使用 ASP.NET 2.0 中新的成員身份、配置文件和基於角色的安全功能。本演練包括有關配置這些新功能和以編程方式使用它們的詳細信息。

成員身份

在 Visual Studio 2005 中配置 ASP.NET 成員身份非常容易。當在 Visual Studio 2005 中創建新 Web 站點時,解決方案資源管理器的外觀如圖 6-9 所示。


6-9 訪問 Membership API 之前的解決方案資源管理器。

當在運行時訪問 Membership API 時,系統會自動創建在 ASP.NET 配置中指定的成員身份數據庫(如果它不存在)。ASP.NET 2.0 附帶成員身份的 Microsoft Access 數據文件模板,以及一組用於創建 Microsoft SQL Server 成員身份數據庫的 SQL 腳本。用於持久化成員身份數據的數據存儲類型用 ASP.NET 配置來控制。如果沒有在 web.config 中顯式聲明數據提供程序,則使用 machine.config 文件中的默認值。在此應用程序中,machine.config 中的默認值是 Microsoft Access 的提供程序,因此當訪問 Membership API 時,系統會在 Web 站點的 Data 子文件夾中自動創建一個 Access 數據文件。


6-10 顯示自動生成成員身份數據文件的解決方案資源管理器。

此應用程序中的第一個 Web 窗體訪問 Membership API 中三個最有用的方法:CreateUser、ValidateUser 和 GetAllUsers。該 Membership API 還包括進行身份驗證管理所需的其他類型的維護功能,例如通過電子郵件地址查找用戶、修改用戶、刪除用戶以及設置密碼。

該 API 中的方法易於使用並且清楚易懂。例如,CreateUser方法的最簡單版本採用兩個易於理解的參數:用戶名和密碼。CreateUser的重載版本還採用電子郵件地址作爲參數。您只需編寫如下一行代碼即可創建成員身份數據庫中的新用戶:

Membership.CreateUser(txtUserName.Text, txtPassword.Text)

CreateUser 方法調用可以創建數據庫中的用戶,但有時需要檢索數據庫中的數據,以便可以驗證用戶的憑據。只需調用 ValidateUser 方法即可自動完成所有這些工作:

If Membership.ValidateUser(txtUserName.Text, txtPassword.Text) Then 
FormsAuthentication.SetAuthCookie(txtUserName.Text, False) 
Response.Redirect(Request.Path) 
End If

Membership API 使得可以輕而易舉地完成常見類型的用戶管理任務,否則您必須編寫這些任務的所有數據訪問和業務邏輯。例如,要檢索成員身份數據庫中的所有用戶列表,只需枚舉 GetAllUsers方法返回的用戶集合:

Dim users As MembershipUserCollection = Membership.GetAllUsers()

此應用程序中 Default.aspx 的全部源包括用於用戶名和密碼的 TextBox控件,以及用於創建用戶或以用戶身份登錄的 Button 控件。該 Web 窗體還包含存放成員身份數據庫中所有用戶列表的 ListBox。用 Label 來顯示登錄狀態。下面的 ASPX 標記和 Visual Basic 代碼是處理成員身份的 Default.aspx 的子集(即,這些代碼沒有添加用戶配置文件和基於角色的安全功能):

<%@ page language="VB”%> 
<script runat="server"> 
Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) 
Dim users As MembershipUserCollection = Membership.GetAllUsers() 
Dim userArray As New ArrayList(users.Count) 
For Each mu As MembershipUser In users 
userArray.Add(mu.Username) 
Next 
UserList.DataSource = userArray 
UserList.DataBind() 
If User.Identity.IsAuthenticated Then 
lblLoginStatus.Text = “You are currently authenticated as “+ _ 
User.Identity.Name 
End If 
End Sub 
Sub btnCreate_Click(ByVal sender As Object, _ 
ByVal e As System.EventArgs) 
Membership.CreateUser(txtUserName.Text, txtPassword.Text) 
End Sub 
Sub btnLogin_Click(ByVal sender As Object, ByVal e As System.EventArgs) 
If Membership.ValidateUser(txtUserName.Text, txtPassword.Text) Then 
FormsAuthentication.SetAuthCookie(txtUserName.Text, False) 
Response.Redirect(Request.Path) 
End If 
End Sub 
</script> 
<html> 
<head runat="server"> 
<title>Untitled Page</title> 
</head> 
<body> 
<form id="form1”runat="server"> 
<div> 
Username: <asp:TextBox ID="txtUserName” 
Runat="server"></asp:TextBox> 
<br /> 
Password: <asp:TextBox ID="txtPassword” 
Runat="server"></asp:TextBox> 
<br /> 
<asp:Button ID="btnCreate”Runat="server”Text="Create User” 
OnClick="btnCreate_Click”/> 
<asp:Button ID="btnLogin”Runat="server”Text="Login” 
OnClick="btnLogin_Click”/> 
<asp:Label ID="lblLoginStatus”Runat="server"></asp:Label> 
</div> 
<p> 
Users in Membership database: 
<br /> 
<asp:ListBox ID="UserList”runat="server"></asp:ListBox> 
</p> 
</form> 
</body> 
</html>

圖 6-11 顯示在運行時只添加成員身份功能的 Default.aspx。在新的 Web 控件應用程序中您將看到,ASP.NET 2.0 通過提供新的安全控件(如 Login和 LoginStatus控件)使身份驗證的用戶界面更簡單。


6-11 Internet Explorer 中顯示成員身份數據庫內所有用戶的 Web 窗體。

ASP.NET 中默認的身份驗證模式是 Windows。爲了使用 Forms 身份驗證(此應用程序使用這種方式),必須將 web.config 中 <authentication> 元素的 Mode 屬性設置爲“Forms”。

用戶配置文件

ASP.NET 2.0 中的用戶配置文件有時稱爲用戶個性化或配置文件個性化,在 Web 站點的 web.config 文件中進行配置。可以在該配置文件中以聲明性方式聲明希望爲每個用戶存儲的數據,然後在某個特殊的 Profile 對象中填充對應的屬性。下面的 web.config 文件子集配置 Web 站點來存儲每個用戶的 FirstName和 LastName字符串值:

<?xml version="1.0”?> 
<configuration> 
<system.web> 
<authentication mode="Forms”/> 
<profile inherits="System.Web.Profile.HttpProfileBase, System.Web, 
Version=2.0.3600.0, Culture=neutral, 
PublicKeyToken=b03f5f7f11d50a3a"> 
<properties> 
<add name="FirstName”type="System.String”/> 
<add name="LastName”type="System.String”/> 
</properties> 
</profile> 
</system.web> 
</configuration>

Visual Studio 2005 從 web.config 文件讀取這些配置信息,並動態地創建從 HttpProfileBase 繼承的專用類。該專用類包含 web.config 文件中定義的具有正確數據類型的所有屬性。圖 6-12 例舉一個在 Intellisense 中可用的自定義配置文件屬性。


6-12 在 Intellisense 中可用的強類型配置文件屬性。

在運行時,ASP.NET 2.0 負責管理配置文件數據的持久性。作爲程序員,您唯一的任務是讀寫這些數據。下面的代碼說明如何設置 FirstName和 LastName屬性,並將它們保存在配置文件數據存儲中:

Profile.FirstName = txtFirstName.Text 
Profile.LastName = txtLastName.Text 
Profile.Save()

要從 Profile 對象讀回數據,只需顛倒賦值語句即可:

txtFirstName.Text = Profile.FirstName 
txtLastName.Text = Profile.LastName

默認情況下,這些配置文件屬性只能爲經過身份驗證的用戶設置(因此也只爲他們存儲)。但在有些情況下,當用戶匿名瀏覽站點時,您需要捕獲信息;而當該用戶登錄站點時,您需要維護數據。ASP.NET 用戶配置文件本身支持這種情況。必須使用 web.config 中的 <anonymousIdentification>元素顯式啓用匿名配置處理。然後,希望支持匿名用戶的任何屬性都必須將 allowAnonymous屬性設置爲 true。下面來自 web.config 的 XML 顯示此應用程序的這些設置:

<anonymousIdentification enabled="true”/> 
<profile inherits="System.Web.Profile.HttpProfileBase, System.Web, 
Version=2.0.3600.0, Culture=neutral, 
PublicKeyToken=b03f5f7f11d50a3a”> 
<properties> 
<add name="FirstName”type="System.String”/> 
<add name="LastName”type="System.String”/> 
<add name="FirstVisit”type="System.String”allowAnonymous="true”/> 
</properties> 
</profile>

基於角色的安全性

ASP.NET 2.0 角色管理提供許多與創建和維護角色與角色成員身份有關的功能。要啓用 Web 站點的角色管理,可以將 <role-Manager> 元素添加到 web.config 文件。在配置角色管理時,可以選擇將用戶的角色加密並緩存在 cookie 中。雖然緩存有助於減少往返數據存儲以獲得用戶角色信息的次數,但它也帶來一個問題:cookie 中的角色與在服務器端數據存儲中最近更新的角色集不匹配。當大量更改角色成員身份時,這種差異可能特別容易產生問題。對於此應用程序,通過將 <roleManager>元素的 cacheRolesInCookie屬性設置爲 false 來禁用 cookie 緩存:

<roleManager enabled="true" 
cacheRolesInCookie="false”/>

現在每次處理經過身份驗證的請求時,都將重新從數據存儲中讀取角色,並將其加載到用戶的安全用戶對象中。

在爲用戶分配角色之前,您必須創建角色。使用 Roles 類的 Create-Role 方法可以做到這一點。逐個應用程序存儲角色,因此爲該應用程序創建的角色與其他應用程序的角色完全無關。

Roles.CreateRole(“Admin”) 
Roles.CreateRole(“Editor”) 
Roles.CreateRole(“Reviewer”)

一旦創建了角色,就可以進行所需的維護任務,例如獲得應用程序中所有角色的列表。GetAllRoles方法返回一個 String 對象數組,包含以前所創建角色的名稱:

Dim allRoles() As String = Roles.GetAllRoles

既然角色已實際存在,就可以將用戶分配給角色。爲了一次將一個用戶分配給一個角色,請使用 AddUserToRole方法:

Roles.AddUserToRole(UserList.SelectedValue, RolesList.SelectedValue)

如果想將多個用戶同時添加給某個角色,可以使用 AddUsersToRole方法。如果想將一個用戶添加給多個角色,可以使用 AddUserToRoles 方法。將多個用戶同時添加給多個角色,可以使用 AddUsersToRole 方法。

ASP.NET 2.0 角色管理還添加了一種新功能,該功能解決 ASP.NET 1.1 中微不足道但卻讓人感到不便的限制 — 不用編寫讀取基礎數據源的數據訪問代碼就能夠獲得某個用戶所有角色的列表。

Roles.GetRolesForUser(User.Identity.Name)

圖 6-13 顯示如何將這些功能集中在一個簡單的用戶界面中,可以使用該界面創建用戶,創建角色,將用戶分配給角色,然後以用戶的身份登錄,並查看應用程序中所有的角色,以及單個用戶所屬的全部角色。


6-13 正在使用的成員身份、配置文件和角色。

小結

用戶管理是一項幾乎普遍存在的 Web 開發任務,它有許多已經確立的構建模式,包括使用用戶名和密碼的身份驗證;存儲用戶配置文件信息(如姓名和地址);以及基於角色的授權。ASP.NET 1.1 提供一些對用戶管理的支持 — 例如通用身份驗證模型和內置區分經過身份驗證的用戶和匿名用戶的功能 — 並提供一些對基於角色的授權的支持。但是在 ASP.NET 1.1 中,爲常見用戶管理任務創建與維護邏輯和數據存儲的重擔落到了開發人員身上。包括對憑據、配置文件和角色進行數據訪問在內的相似代碼已經由無數的開發人員反覆編寫過。最後,ASP.NET 2.0 支持將常見用戶管理的瑣碎工作直接內置在 ASP.NET Web 平臺中。

應用程序:新的 Web 控件

此應用程序演示 ASP.NET 2.0 中一些新的 Web 控件,例如爲新的 ASP.NET 2.0 成員身份系統提供預構建用戶界面元素的新安全控件。

新概念

ASP.NET 2.0 中有許多新控件 — 多得實在無法在一個示例應用程序中逐一介紹。這些新控件包括新數據源控件、新數據綁定控件、新安全控件、新 Web 部件控件、新導航控件以及 ASP.NET 1.1 控件中新的移動識別功能。此應用程序重點介紹最適合一般 Web 開發的新控件 — 希望它們可以滿足 Web 開發人員的一些最直接的需要。

安全控件

任何利用身份驗證來驗證用戶身份或限制訪問受保護資源的 Web 站點都需要某種用戶界面來完成所有不同的身份驗證任務,例如登錄、註冊(創建新帳戶)、顯示登錄狀態、顯示個性化的註銷鏈接以及重新設置密碼。在 ASP.NET 1.1 中,所有這些用戶界面組件都需要自己創建。在 ASP.NET 2.0 中,有一組新的安全控件,使用它們甚至無需編寫一行代碼就可以爲站點添加基本的安全功能。

Visual Studio 2005 預覽版包含的安全控件如下:

¦Login:這是一種綁定到 ASP.NET 成員身份功能的複合控件。它包含用於輸入用戶名和密碼的 TextBox控件以及一個“Submit”按鈕。該控件還包含許多可自定義的功能,包括設置可能出現的各種文本段(如指令文本、登錄失敗文本和控件標題文本)的格式。還可以選擇讓控件顯示指向註冊與密碼恢復頁的超級鏈接。Login控件甚至包含對用戶名和密碼進行所要求的內置字段驗證。(可以禁用驗證。)可以編寫代碼來支持 Login控件 — 例如,在 Authenticate 事件處理程序中 — 但這完全沒有必要。即使通過絕對零代碼最簡單地使用 Login控件,也可以提供一個完整的工作身份驗證界面。

¦ CreateUserWizard:該控件提供一個嚮導樣式的界面,用於在成員身份系統中創建新用戶。CreateUserWizard遠不只是一個用於輸入用戶名和密碼的簡單窗體。它包括對其所有字段的字段驗證,包括可選的對電子郵件地址進行的常規表達式驗證。它提示用戶兩次輸入建議的密碼,並確認這兩個密碼是否匹配。如果基礎成員身份提供程序支持安全問題,那麼 CreateUserWizard控件還可以收集用戶的安全問題和回答。此應用程序的“演練”一節還說明如何爲嚮導添加自定義步驟,從而在註冊的過程中收集用戶的其他信息。

¦LoginName:該控件是顯示用戶名的佔位符。如果當前用戶是匿名的(即沒有經過身份驗證),則該控件不呈現任何輸出。LoginName公開一個 FormatString屬性,使用該屬性,您不僅可以顯示用戶名,而且可以顯示更多其他的信息。例如,可以將 FormatString設置爲 ”Welcome, {}",當 UserTwo 登錄時,這會產生 ”Welcome, UserTwo” 的輸出。

¦LoginView:該控件提供可以在其中爲匿名用戶和經過身份驗證的用戶創建不同內容的模板。LoginView控件也是角色識別的,因此實際上您可以爲具有不同角色的經過身份驗證的用戶創建不同的模板。

¦ PasswordRecovery:該控件提供用戶界面和相應的功能,以幫助用戶檢索或重新設置其密碼。該控件有三種視圖:Username、Question 和 Success。Username 視圖允許用戶輸入必須檢索或重新設置密碼的用戶名。Question 視圖提示用戶在註冊的過程中輸入問題的回答。Success 視圖在通過電子郵件提交密碼後顯示一條成功消息。可用於密碼檢索的選項由用來提供成員身份服務的 Membership 提供程序部分決定。ASP.NET 2.0 包含用於 Microsoft Access 和 Microsoft SQL Server 的提供程序。這兩種提供程序都支持密碼檢索和安全問題。其他的提供程序(如第三方提供程序或您自己創建的提供程序)可能不完全支持這些功能。另外,默認情況下,這兩個內置提供程序都存儲密碼哈希值。(明文和加密的文本是另外的選項。)無法用密碼哈希值來確定原始密碼,因此默認情況下,唯一可用的恢復方案就是重新設置密碼,並通過電子郵件將新密碼發送給用戶。

¦LoginStatus:該控件根據當前用戶的登錄狀態產生一個 Login 或 Logout 超級鏈接:匿名用戶看見一個 Login 鏈接,而經過身份驗證的用戶看見一個 Logout 鏈接。當然,超級鏈接的實際文本與鏈接的目標文本一樣都是可自定義的。Logout 鏈接可以配置爲在用戶註銷後執行以下三項操作中的一項:刷新當前頁,將用戶重定向到登錄頁,或將用戶重定向到其他頁。

¦ ChangePassword:該複合控件爲用戶提供用於更改其密碼的界面。默認情況下要求用戶輸入一次當前密碼和兩次新密碼。和其他的安全控件一樣,ChangePassword 可以完全自定義。

站點地圖控件

新的 SiteMapPath控件提供內置在 ASP.NET 2.0 中部分新的站點地圖解決方案。SiteMapPath 控件提供在許多 Web 站點上非常流行的“Breadcrumeb”導航界面。在 ASP.NET 1.1 中,您必須創建 Breadcrumeb 導航的所有邏輯或購買第三方解決方案。SiteMapPath控件只要求 Web 站點有一個名爲 web.sitemap 的 XML 文件,該文件定義站點中頁的層次結構。SiteMapPath控件確定當前頁在站點地圖層次結構中的位置,並自動創建 Breadcrumeb 導航。如果 SiteMapPath控件放置在沒有包含在站點地圖文件中的 Web 窗體上,SiteMapPath自然不呈現 Breadcrumeb 蹤跡。

ASP.NET 2.0 還包含一個新的 SiteMapDataSource控件,該控件讀取 web.sitemap 文件並充當其他控件(如 TreeView)的數據源。此應用程序的“演練”一節將說明如何創建 web.sitemap 文件,如何使用 SiteMapPath控件,以及如何使用 SiteMapDataSource控件創建站點地圖樹。

Substitution 控件(緩存後替換)

輸出緩存是一種保存 ASP.NET Web 窗體輸出並重用相同的輸出來滿足對同一頁面多個請求的方法。當可以使用輸出緩存時,它對於 Web 站點的性能非常有利。在 ASP.NET 1.1 中,無法更改單個用戶緩存頁的內容,由於一小部分頁內容必須針對每個用戶進行自定義(例如,個性化問候或用戶購物車中商品的數量),因此許多 Web 頁不能從輸出緩存中受益。

頁面片段緩存是一種緩存 Web 窗體上用戶控件輸出的方法。如果可以將 Web 窗體設計成一組用戶控件,那麼在控制必須個性化的頁元素的同時,可以獲得輸出緩存的性能優勢。但是頁面片段緩存使用起來非常麻煩,因爲必須將頁面分解成用戶控件以允許進行甚至是最簡單的每個請求自定義。ASP.NET 2.0 引入一種從輸出緩存中受益以及可以爲每個用戶進行自定義的新方法。這種新方法稱爲緩存後替換

緩存後替換通過將 Substitution 控件放置在 Web 窗體上,然後提供共享(靜態)回調方法名來實現,ASP.NET 可以調用該方法來獲得注入到緩存輸出中的內容。雖然緩存後替換顯然不能像純粹的輸出緩存那樣提高性能,但調用回調方法的額外成本直接受回調方法性能特徵的制約。

演練

本演練說明如何使用 ASP.NET 2.0 中新的安全 Web 控件,還演示如何使用新的站點地圖控件,以及如何使用新 Substitution 控件進行緩存後替換。

安全控件

ASP.NET 2.0 引入七種新的安全控件來滿足 Web 應用程序中最常見的身份驗證和用戶管理要求。在構建新的 Web 應用程序或將現有應用程序遷移到 ASP.NET 時,很少的時間投入(以發現這七種控件的功能)可以節省更多的時間。

Login 控件雖然它不是最複雜的安全控件,但可以認爲 Login控件是核心安全控件,因爲它提供實際收集證書並根據成員身份數據庫對其進行驗證的界面。Login控件包含相當數量的屬性,這些屬性允許您配置控件的顯示和行爲。圖 6-14 顯示一些可以在 Properties 窗口中編輯的 Login控件屬性。


6-14 Login 控件的 Properties 窗口。

成功驗證用戶的證書後,可以配置 Login控件以將用戶重定向到一個特定頁。也可以在嘗試登錄失敗後,配置 Login控件刷新當前頁,或將用戶重定向到站點的登錄頁。還可以更改該控件顯示的所有文本,包括標籤、指令、幫助文本、失敗消息和控件標題。

此應用程序使用 Login控件的大部分默認設置。其 login.aspx 頁上 Login控件的 ASPX 標記如下所示:

<asp:Login ID="Login1”Runat="server” 
CreateUserText="Register for a new account" 
CreateUserUrl="Register.aspx” 
PasswordRecoveryText="Forgot your password?” 
PasswordRecoveryUrl="PasswordRecovery.aspx”> 
</asp:Login>

CreateUserUrl 屬性告訴 Login控件提供一個指向用戶註冊頁的超級鏈接。CreateUserText 屬性指定該超級鏈接的顯示文本。同樣,PasswordRecoveryUrl屬性告訴 Login控件提供一個超級鏈接,指向用戶可以在其中重新設置其密碼的頁面。PasswordRecoveryText 屬性指定該超級鏈接的顯示文本。圖 6-15 顯示登錄嘗試失敗後 Internet Explorer 中的 Login控件。


6-15 登錄嘗試失敗後運行時的 Login 控件。

CreateUserWizard控件要登錄,首先必須創建一個帳戶。正如在前一個應用程序中所看到的,可以通過 Membership.CreateUser方法完成該任務,但是這需要您構建自己的用戶界面,並至少編寫一行代碼。使用 CreateUserWizard,只需向 Web 窗體添加一個控件並設置一些屬性。該控件負責其餘的細節。

實際上,CreateUserWizard是一個非常強大的控件,因爲它允許您爲嚮導添加自己的自定義步驟。在此應用程序中,已經爲嚮導添加了新步驟以詢問新用戶所喜歡的顏色,然後使用內置的 ASP.NET 用戶配置文件功能進行存儲。

CreateUserWizard允許配置關於其外觀和行爲的幾乎所有方面 — 從標籤和提示到驗證電子郵件地址所用的常規表達式。需要爲該控件設置的一個屬性是 ContinueDestinationPageUrl,它決定在成功創建一個新帳戶後,CreateUserWizard控件將用戶重定向到何處。下面的 ASPX 清單是定義此應用程序中 Register.aspx 頁的 CreateUserWizard控件的標記。請注意,<asp:WizardStep>元素用來定義嚮導中的自定義步驟。

<asp:CreateUserWizard ID="CreateUserWizard1”Runat="server" 
ContinueDestinationPageUrl="default.aspx" 
OnContinueClick="CreateUserWizard1_ContinueClick"> 
<WizardSteps> 
<asp:WizardStep Runat="server”ID="SignStep” 
Title="What is your favorite color?” 
StepType="Step"> 
What is your favorite color?<br /> 
<asp:TextBox Runat="server”ID="txtColor"></asp:TextBox> 
</asp:WizardStep> 
</WizardSteps> 
</asp:CreateUserWizard>

圖 6-16、6-17 和 6-18 顯示用戶創建新帳戶所要經歷的步驟。請注意,嚮導中的自定義步驟(圖 6-17)詢問用戶喜歡的顏色。


6-16 顯示 ConfirmPasswordCompareErrorMessage 的 CreateUserWizard 控件。


6-17 CreateUserWizard 自定義嚮導步驟。


6-18 CreateUserWizard 最後成功的步驟。

當用戶單擊最後成功步驟上的“Continue”按鈕時,CreateUserWizard控件引發可爲其編寫事件處理程序的 ContinueClick事件。此時,用戶將自動登錄(除非您將 LoginCreatedUser屬性更改爲 false)。在事件處理程序中,您可以在自定義嚮導步驟中訪問控件,並檢索用戶在創建帳戶過程中輸入的值。下面的代碼說明如何獲得對 txtColor控件的引用,並將用戶喜歡的顏色保存在用戶的配置文件中:

Sub CreateUserWizard1_ContinueClick(ByVal sender As Object, _ 
ByVal e As System.EventArgs) 
Dim txtColor As Control 
txtColor = CreateUserWizard1.FindControl(“txtColor”) 
If Not txtColor Is Nothing Then 
Profile.FavoriteColor = DirectCast(txtColor, TextBox).Text 
Profile.Save() 
End If 
End Sub

LoginName控件LoginName控件是這些新安全控件中最簡單的控件。如果當前用戶經過身份驗證,那麼 LoginName控件將顯示用戶名。如果當前用戶沒有經過身份驗證,那麼 LoginName控件將不顯示任何輸出。下面的 ASPX 標記說明如何在此應用程序中使用 LoginName 控件:

Thank you for using our site, 
<asp:LoginName ID="Loginname1”Font-Bold="true”Runat="server”/>

在本例中,用戶名用粗體,但用戶名前面的問候語不用粗體。如果問候語和用戶名的字體粗細相同,可以按照如下方式將問候語放置在 FormatString屬性中:

<asp:LoginName ID="Loginname1” 
FormatString=“Thank you for using our site, {0}" 
Runat="server”/>

LoginView控件如果您曾經創建過一個必須爲不同類型的用戶呈現不同內容的 Web 頁,那麼您一定知道該代碼相當簡單,但是創建和維護起來卻非常乏味。即使在 ASP.NET 1.1 中,您也必須做許多工作以將內容放置在可以充當容器(例如,<div runat="server">)的服務器控件中,然後編寫邏輯,從而根據查看頁面的用戶類型顯示和隱藏服務器控件。

LoginView控件具有對用戶角色的內置支持,因此可以根據角色爲經過身份驗證的用戶創建不同的視圖。LoginView控件處理根據當前用戶的角色選擇適當視圖的任務。下面的代碼來自於此應用程序的 Default.aspx 頁。該示例中的 LoginView控件有 4 種視圖:一種用於匿名用戶,一種用於經過身份驗證的用戶,一種用於經過身份驗證且具有 Admin 角色的用戶,一種用於經過身份驗證且具有 NormalUser 角色的用戶。

<asp:LoginView ID="Loginview1”Runat="server"> 
<RoleGroups> 
<asp:RoleGroup Roles="Admin"> 
<ContentTemplate> 
Hello, Admin. 
</ContentTemplate> 
</asp:RoleGroup> 
<asp:RoleGroup Roles="NormalUser"> 
<ContentTemplate> 
Ah, a normal user 
</ContentTemplate> 
</asp:RoleGroup> 
</RoleGroups> 
<LoggedInTemplate> 
<div align="center"> 
Thank you for using our site, 
<asp:LoginName ID="Loginname1”Font-Bold="true” 
Runat="server”/> 
</div> 
</LoggedInTemplate> 
<AnonymousTemplate> 
Welcome to our Web site. You are not 
currently logged in. 
<a href="login.aspx">Click here</a> to sign up 
for a free account. 
</AnonymousTemplate> 
</asp:LoginView>

LoginView控件的一個重要功能是,創建的所有模板都不會將 Visual Studio 2005 中的可視化設計圖面弄亂,因此 Web 窗體的設計時錶示不會像在使用多個 <div runat="server"> 或 <asp:Panel>控件時那樣亂七八糟。圖 6-19 顯示設計時 Visual Studio 2005 中 Default.aspx 的 LoginView控件。


6-19 設計時的 LoginView ¿Ø¼þ¡£

此應用程序中的 Default.aspx 頁還包含下面的代碼。這些代碼包括兩個 Click事件處理程序,二者都調用 SetRole方法,但傳遞的角色名不同。SetRole方法創建 Admin 角色和 NormalUser 角色(如果它們不存在)。然後,SetRole方法將當前用戶從所有的角色中移除。最後,SetRole方法將當前用戶添加到在 roleName參數中指定的角色。之後在呈現 Default.aspx 時,頁面上的 LoginView根據用戶的當前角色成員身份顯示適當的視圖。

Sub bntMakeAdmin_Click(ByVal sender As Object, _ 
ByVal e As System.EventArgs) 
SetRole(“Admin”) 
End Sub 
Sub btnMakeNormalUser_Click(ByVal sender As Object, _ 
ByVal e As System.EventArgs) 
SetRole(“NormalUser”) 
End Sub 
Sub SetRole(ByVal roleName As String) 
If Roles.GetAllRoles().Length = 0 Then 
Roles.CreateRole(“Admin”) 
Roles.CreateRole(“NormalUser”) 
End If 
For Each r As String In Roles.GetRolesForUser(User.Identity.Name) 
Roles.RemoveUserFromRole(User.Identity.Name, r) 
Next 
Roles.AddUserToRole(User.Identity.Name, roleName) 
End Sub

PasswordRecovery控件乍一看,PasswordRecovery控件非常簡單。功能完整的、啓用電子郵件密碼恢復功能的解決方案所需的 ASPX 標記只有一行代碼:

<asp:PasswordRecovery ID="Passwordrecovery1”Runat="server”/>

使用這一行標記,ASP.NET 2.0 使 Web 站點能夠讓用戶輸入其用戶名、回答其安全問題,並通過電子郵件將一個新密碼發送給他們。和其他的安全控件一樣,PasswordRecovery控件高度可配置。圖 6-20 和 6-21 顯示用戶重新設置密碼時要經歷的步驟。


6-20 密碼恢復的第一步。


6-21 密碼恢復的第二步。

LoginStatus控件LoginStatus控件不像其他一些安全控件那樣複雜,但卻非常實用。Web 站點通常在某處有一個將用戶帶到登錄頁的登錄鏈接。用戶登錄後,該鏈接變成註銷鏈接。在許多 Web 開發環境中,必須編寫檢查用戶登錄狀態並呈現適當 HTML(例如,通過啓用 ASP.NET 1.1 中適當的 HyperLink或 LinkButton控件)的邏輯。在 ASP.NET 2.0 中,所需的只是一個 LoginStatus控件:

<asp:LoginStatus ID="Loginstatus1”Runat="server”/>

可以以幾種方式配置 LoginStatus控件。例如,可以聲明用戶註銷後控件應當做什麼:刷新頁、重定向到另一個頁面,或者重定向到登錄頁。圖 6-22 顯示匿名用戶看到的 Login 鏈接。圖 6-23 顯示經過身份驗證的用戶看到的 Logout 鏈接。


6-22 呈現給匿名用戶的 LoginStatus 控件。


Figure 6-23 呈現給經過身份驗證的用戶的 LoginStatus 控件。

ChangePassword控件ChangePassword控件爲用戶提供更改其密碼的界面。和其他安全控件一樣,可以通過一行 ASPX 標記來使用 ChangePassword,也可以完全自定義 ChangePassword。下面的標記來自於此應用程序的 Default.aspx 頁。它只更改控件提供給用戶的導航類型,而不是該控件將使用的超級鏈接的按鈕。

<asp:ChangePassword ID="ChangePassword1”Runat="server” 
CancelButtonType="Link” 
ChangePasswordButtonType="Link" 
ContinueButtonType="Link">

6-24 使用導航鏈接而不是導航按鈕的 ChangePassword 控件。

站點地圖

站點地圖是許多 Web 站點不可缺少的部分。它們可以充當進入到站點任何部分的啓動點,並有助於改進搜索引擎排名。站點地圖一般保存爲 HTML 文檔,但是將站點地圖保存爲 HTML 有許多缺點。一個最大的問題是,站點地圖包含可定期更改的分層數據。將這些數據保存在 HTML 中需要在每次添加、移動或刪除頁面時考慮格式設置和位置問題。在 ASP.NET 2.0 中,可以將站點地圖保存在一個名爲 web.sitemap 的特殊文件中。此應用程序的 web.sitemap 文件如下所示:

<siteMap> 
<siteMapNode title="Home”description="Home”url="default.aspx”> 
<siteMapNode title="Login” 
description="Home” 
url="login.aspx”/> 
<siteMapNode title="Register” 
description="Home” 
url="register.aspx”/> 
<siteMapNode title="Forgot Password” 
description="Home” 
url="PasswordRecovery.aspx”/> 
<siteMapNode title="Articles” 
description="Articles” 
url="Articles/default.aspx”> 
<siteMapNode title="Article One” 
description="“ 
url="Articles/Article1.aspx”/> 
</siteMapNode> 
</siteMapNode> 
</siteMap>

可以在站點地圖中將站點的每一頁作爲一個 <siteMapNode>元素輸入。因爲每頁都是一個 <siteMapNode>元素,而每個 <siteMapNode>元素都可以包含其他 <siteMapNode> 元素,因此可以輕鬆地更改 Web 站點的結構,而無需擔心將站點地圖保存爲 HTML 時,Web 站點管理員必須費力解決的縮進和其他格式問題。

由於站點地圖存儲爲 XML,因此可以以多種方式來輕鬆地使用它。ASP.NET 2.0 中引入的一種新數據源控件是 SiteMapDataSource。SiteMapDataSource自動讀取 web.sitemap 並公開這些數據,以供其他控件使用。下面的標記來自於 SiteMap.aspx。它將一個 TreeView控件綁定到 SiteMapDataSource。結果如圖 6-25 所示。

<asp:SiteMapDataSource ID="SiteMapDataSource1”Runat="server”/> 
<asp:TreeView ID="TreeView1”Runat="server” 
DataSourceID="SiteMapDataSource1"> 
</asp:TreeView>

6-25 綁定到 SiteMapDataSource 的 TreeView 控件。

許多 Web 站點的另一個重要部分是 Breadcrumb 導航蹤跡,它顯示您在該 Web 站點頁層次結構中的位置。Breadcrumb 導航中顯示的分層信息一般與站點地圖中的分層數據相同,因此擁有一個根據站點地圖創建 Breadcrumb 導航的控件非常有意義。ASP.NET 2.0 中的 SiteMapPath控件讀取站點地圖,並根據當前頁在站點層次結構中的合適位置呈現適當的 Breadcrumb 導航。下面的 ASPX 標記來自於 Articles/Article1.aspx:

<asp:SiteMapPath ID="SiteMapPath1”Runat="server"> 
</asp:SiteMapPath>

當在 Internet Explorer 中查看時,SiteMapPath產生如圖 6-26 所示的導航路徑。


6-26 呈現在 Article1.aspx 中的 SiteMapPath 控件。

緩存後替換

Substitution控件允許將數據注入到緩存頁,實際上它只不過是一個在運行時替換數據的佔位符。Substitution 控件唯一令人感興趣的屬性是 MethodName。MethodName屬性指定在運行時調用的方法,以獲得要在緩存輸出中替換佔位符的數據。該方法的名稱無關緊要,但必須可以共享(靜態),並且必須接受 HttpContext對象作爲參數。

接下來的 ASPX 標記來自於 PostCacheSubstitution/default.aspx。該頁包含一些靜態文本和一個名爲 cacheTime 的 Label 控件。當激發 Page_Load事件處理程序時,系統將當前的時間輸入到 cacheTime的 Text 屬性中。該頁使用 @OutputCache指令將頁面輸出緩存 60 秒。這意味着,系統生成該頁面的內容(包括 cacheTime Label 控件中的文本)一次,然後爲這 60 秒內的後續請求從緩存中檢索該頁的內容。Page_Load事件處理程序將根據對該頁的第一次請求來執行,但直到輸出緩存中的內容過期之後(60 秒之後)的首次請求時,它纔會再次執行。

Substitution 控件對於輸出緩存模型是個例外。每次請求都要調用在 MethodName 屬性中指定的回調方法。ASP.NET 將當前的 HttpContext傳遞給回調方法,因此它可以完全訪問在請求實現期間正常可用的各類對象,例如 RequestServerUser。在本例中,回調方法的名稱爲 SubstituteSubstitute 返回一個字符串,它在輸出發送給用戶的瀏覽器之前替換其中的 Substitution 控件:

<%@ page language="VB"%> 
<%@ OutputCache Duration="60”VaryByParam="none”%> 
<script runat="server"> 
Public Shared Function _ 
Substitute(ByVal context As HttpContext) As String 
Return “The time this page was requested was: “+ _ 
Now.ToString(“hh:mm:ss”) 
End Function 
Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) 
cacheTime.Text = Now.ToString(“hh:mm:ss”) 
End Sub 
</script> 
<html> 
<head runat="server"> 
<title>Untitled Page</title> 
</head> 
<body> 
<form id="form1”runat="server"> 
<div> 
This is cached output</div> 
<div> 
The time when the page was cached was: 
<asp:Label ID="cacheTime”Runat="server"></asp:Label> 
</div> 
<div>&nbsp;</div> 
<div> 
<asp:Substitution ID="Substitution1”Runat="server” 
MethodName="Substitute”/> 
</div> 
<div>&nbsp;</div> 
<div>This is cached output</div> 
</form> 
</body> 
</html>

圖 6-27 顯示首次請求後 10 秒鐘刷新瀏覽器後該 Web 頁的輸出。請注意,Label 中的時間與 Substitute 方法返回的時間不同。大多數頁面內容來自於輸出緩存,但是表示“請求該頁的時間爲:11:17:08”的這一部分內容來自於 Substitution 控件的回調方法。


6-27 使用 Substitution 控件的緩存後替換。

小結

此應用程序只是簡要介紹 ASP.NET 2.0 中可用新控件的一些比較淺顯的內容。作爲 Web 開發人員,您將認識到:這些新控件可能爲您節省時間,並且有機會用於所有 Web 站點的常用實現(如用戶管理、與安全相關的 UI 以及站點地圖)。

應用程序:母版頁和主題

此應用程序介紹母版頁與主題,ASP.NET 2.0 中的這兩種新功能提供內置的外觀與模板功能,而 ASP.NET 1.1 顯然沒有這些功能。

新概念

幾乎每個由多個頁面組成的實際 Web 站點都要求所有的頁面具有一致的外觀。如果沒有某種基於模板的解決方案,每頁都保持相同的圖形設計和佈局將非常麻煩。使用各種 Web 技術的 Web 開發人員已經嘗試了許多不同的方法來創建基於模板 的 Web 應用程序,這些應用程序的創建和更新都非常容易。遺憾的是,這是 ASP.NET 1.1 比較弱的一個方面。

許多 ASP.NET 1.1 開發人員採取一種非常麻煩的方法,他們使用的頁眉和頁腳用戶控件必須放置在每個頁面上。雖然在許多情況下這種方法還不錯,但它的設計時體驗並不理想,這使與圖形設計器的交互非常困難,而且可能在嘗試創建“Skinable”站點時受到極大的限制,很不靈活。實際上,使用頁眉和頁腳控件只是爲了模擬基於模板的 Web 站點。單頁的內容不注入模板 — 單頁只是包含在每個頁面上都產生一致外觀的常用元素和用戶控件。

“Skinnable”站點是一種對於相同的內容具有多個表示選項(通過更改字體、顏色、圖像、佈局,等等)的 Web 站點。

不滿足於“頁眉和頁腳”方法的 ASP.NET 開發人員已經選擇了替換方法,例如基於模板的自定義解決方案。實現自定義解決方案的幾種常用方法可以非常容易地在 Web 上找到。大多數方法使得圖形設計人員可以更加容易地創建可以在運行時選擇的模板。雖然比頁眉和頁腳控件更加靈活,但自定義解決方案的設計時體驗仍不理想,並增加管理的複雜性。

理想的解決方案是讓圖形設計人員使用指定的一個或多個內容區域創建模板。然後當構建單個 Web 頁時,只需指向該模板,並指示哪項內容進入模板的哪個內容區域。在構建這些單頁時,設計環境應提供可視化反饋,這樣就可以知道內容注入模板後頁面的最終效果。

母版頁

ASP.NET 2.0 中的母版頁爲 Web 開發人員渴望的真正基於模板的開發提供設計時和運行時支持。下面是使用母版頁的基本步驟:

1. 創建母版模板。這可以通過 HTML 圖形設計器輕鬆實現。特定於頁的內容的佔位符只需使用 <asp:ContentPlaceholder>服務器控件來指定。

2. 使模板成爲一個母版頁。將一個模板轉變成一個 ASP.NET 2.0 母版頁與將 @Master指令添加到 ASPX 標記一樣簡單。

3. 創建單個內容頁。可以像平常一樣創建單個 Web 窗體,唯一的不同之處在於,必須將內容放置在 <asp:Content>標記內,該標記引用模板中的內容佔位符。在使用 Visual Studio 2005 時,可以在創建內容頁時指定母版頁,並讓可視化設計器爲您創建 <asp:Content> 標記。

4. 引用母版頁。任何 ASP.NET 2.0 Web 窗體都可以通過在 @Page指令中引用一個母版頁而成爲一個內容頁。既可以直接編輯 ASPX 標記,也可以使用該 Web 窗體的 Properties 窗口。

Visual Studio 2005 中的可視化 Web 設計器提供對創建和編輯母版頁和內容頁的完全支持。一般首先創建母版頁,然後在將新的 Web 窗體添加到應用程序時引用該母版頁。此應用程序的“演練”一節將說明如何完成該任務。

主題

母版頁使得控制 Web 站點的佈局和定義常用的可視化元素(例如,左上角的公司徽標或每頁左側的導航欄)變得非常簡單。但是 Web 站點還有其他的可視化元素需要控制,例如文本框使用的字體和顏色,或者數據網格的格式設置。一般使用級聯樣式表 (CSS) 來集中控制 Web 用戶界面的許多方面。Web 站點中的每一頁都可以引用相同的級聯樣式表,這使您能夠通過更改一個文件而影響整個 Web 站點。但對於 ASP.NET 開發人員而言,級聯樣式表並不是完整的解決方案。例如,諸如 GridView這樣的複雜控件有許多可視化元素,使用 CSS 不能輕鬆地控制它們。如果您想讓每個 GridView都使用相同的字體和顏色,就必須顯式設置每個 GridView 的格式。

ASP.NET 2.0 中的主題提供一種控制服務器控件表示的新方法,而沒有放棄在級聯樣式表中的現有投入。ASP.NET 2.0 中的一個主題是包含樣式表和 .skin 文件的文件夾。這些 .skin 文件定義 Web 應用程序中服務器控件期望的格式屬性。將該主題應用於 Web 窗體時,在 .skin 文件中定義的屬性就應用於適當的服務器控件。例如,ASP.NET 2.0 附帶的 SmokeAndGlass 主題在 .skin 文件中包含 Label、TextBox、Button 和 LinkButton的如下屬性:

<asp:Label runat="server”ForeColor="#585880” 
Font-Size="0.9em”Font-Names="Verdana”/> 
<asp:TextBox runat="server”BackColor="#FFFFFF”BorderStyle="Solid” 
Font-Size="0.9em”Font-Names="Verdana”ForeColor="#585880" 
BorderColor="#585880”BorderWidth="1pt” 
CssClass="theme_textbox”/> 
<asp:Button runat="server”BorderColor="#585880”Font-Bold="true” 
BorderWidth="1pt”ForeColor="#585880”BackColor="#F8F7F4”/> 
<asp:LinkButton runat="server”Font-Size=“.9em”Font-Names="Verdana"/>

當將一個 Label 放置在 Web 窗體上時,它的 ForeColor值爲 #585880,並使用 Verdana 字體。Button 或 TextBox將具有相同的 ForeColor。應當注意,.skin 文件中的這些項不具有 ID屬性,因爲它們不表示服務器控件的實際實例。當在 Web 窗體上創建一個 Label 控件的實例時,它將具有其自己的 ID屬性,但被賦予其他的外觀屬性值,而不考慮在 Web 窗體中爲該控件指定的任何屬性值。重寫主題控件的可視化外觀的唯一方法是使用 EnableTheming屬性禁用該控件的“Theming”:

<asp:Label EnableTheming="False”ID="lblText”runat="server”Text="A”/>

使用 ASP.NET 2.0 主題,您可以繼續使用現有的級聯樣式表類和內聯樣式屬性。使用 <link> 標記,任何主題頁都可以自動引用主題文件夾中的樣式表文件 (.css)。然而,需要預先提醒的是,.skin 文件中的設置通常優先於 CSS 設置,因爲大多數服務器控件將屬性(如 BackColor)呈現爲內聯樣式,它將重寫 CSS 類的設置或以前的內聯樣式。

演練

本演練說明如何使用母版頁和主題來輕鬆提供 Web 站點的一致用戶界面。

創建母版頁

創建母版頁與創建任何其他的 ASP.NET Web 窗體一樣容易。只有兩點不同:使用 @Master指令而非 @Page,ContentPlaceHolder控件用來指示內容頁將注入特定頁內容的位置。爲了使用 Visual Studio 2005 創建一個新的母版頁,可以右鍵單擊解決方案資源管理器中的根節點,並選擇“Add New Item”。在“Add New Item”對話框中,選擇“Master Page”。圖 6-28 顯示選中“Master Page”的“Add New Item”對話框。請注意,母版頁的文件擴展名爲 .master,而不是通常的 .aspx 擴展名。


6-28 “Add New Item”對話框。

可視化 Web 設計器中的設計時體驗與使用任何 Web 窗體完全類似。唯一的不同之處是使用 ContentPlaceHolder控件。圖 6-29 顯示設計視圖中的一個母版頁,表中有一個 ContentPlaceHolder控件。


6-29 Visual Studio 2005 中設計視圖中的母版頁。

6-29 中母版頁後的 ASPX 標記非常簡單。大多數標記是常規的 HTML,用於定義正文中帶有表的 HTML 文檔。特定於母版頁的行爲粗體:

<%@ Master Language="VB"%> 
<html> 
<head runat="server"> 
<title>Untitled Page</title> 
</head> 
<body> 
<form id="form1”runat="server"> 
<div align="center"> 
<table width="500" border="0"> 
<tr style="background-color: DarkBlue” 
valign="middle"> 
<!-- Header title row--> 
<td> 
<h2 align="right” 
style="color: white; font-size: 14pt"> 
Master Pages 
</h2> 
</td> 
</tr> 
<tr> 
<td style="background-color: Beige;"> 
<asp:ContentPlaceHolder 
ID="ContentPlaceHolder1”Runat="server"> 
</asp:ContentPlaceHolder> 
</td> 
</tr> 
</table> 
</div> 
</form> 
</body> 
</html>

@Master指令將該 Web 窗體標識爲一個母版頁。這個特定的母版頁只有一個標識爲 ContentPlaceHolder1 的內容區域。實際上,ContentPlaceHolder控件的名稱非常重要。通過使用 ContentPlaceHolder 的 ID,可以將內容頁中的內容控件與母版頁中的佔位符關聯起來。

使用母版頁

對於 Visual Studio 2005,使用母版頁創建內容頁幾乎不費吹灰之力。當向 Web 站點添加一個新 Web 窗體時,選中“Add New Item”對話框中的“Select Master Page”複選框,如圖 6-30 所示。


6-30 添加內容頁的“Add New Item”對話框。

Visual Studio 2005 接下來將提示您從 Web 站點選擇一個現有的母版頁,如圖 6-31 所示。


6-31 爲新的 Web 窗體選擇一個母版頁。

當在可視化 Web 設計器中打開新的內容頁時,系統會顯示母版頁的佈局,但是爲灰色,這提供頁面的最終效果和頁特定內容顯示位置的快速可視化參考。Visual Studio 2005 爲母版頁中的每個 ContentPlaceHolder控件創建一個 Content 控件。圖 6-32 顯示前面使用母版頁爲此應用程序創建的內容頁。


6-32 設計視圖中的內容頁。

爲內容頁生成的 ASPX 標記非常簡單,因爲提供所生成 HTML 文檔結構的許多標記都是在母版頁中定義的。內容頁中只需要兩條關鍵信息:使用的母版頁文件和 Content 控件與 ContentPlaceHolder控件之間的映射。下面的 ASPX 標記顯示圖 6-32 所示的頁面的源代碼:

<%@ page language="VB”masterpagefile="~/MasterPage.master”%> 
<asp:Content ID="Content1” 
ContentPlaceHolderID="ContentPlaceHolder1” 
Runat="server"> 
This is content in the content file that replaces 
the content in the placeholder in the master page. 
</asp:Content>

在前面的標記中,在 @Page指令中使用 MasterPageFile屬性來指定母版頁。在 Content 控件中,使用 ContentPlaceHolderID屬性將內容頁中的 Content1 映射到母版頁中的 ContentPlaceHolder1

通過設置 Web 窗體的 MasterPageFile屬性,可以在運行時選擇一個新的母版頁。只有當新母版頁包含的 ContentPlaceHolder控件對應於內容頁中 Content 控件引用的所有佔位符時,纔可以使用新母版頁。必須在初始化該頁之前更改 MasterPageFile。例如,可以在 Page_PreInit事件處理程序中使用下面的代碼來選擇替換的母版頁,每加載頁 5 次選擇一個(平均):

Sub Page_PreInit(ByVal sender As Object, ByVal e As System.EventArgs) 
Dim rnd As New System.Random 
If rnd.Next(1, 5) = 1 Then 
Me.MasterPageFile = “~/MasterPage2.master" 
End If 
End Sub

但是,如果 MasterPage2.master 沒有像最初的母版頁文件那樣定義相同的 ContentPlaceHolder控件,這些代碼將失敗。

您可能會發現,與在運行時動態選擇母版頁相比,以編程方式操作母版頁更爲實用。ASP.NET 2.0 中的母版頁不是靜態模板。母版頁是服務器上對象實例化的類,它們公開一組完整的事件。實際上,MasterPage類是從 System.Web.UI.UserControl繼承的,並公開與 UserControl 相同的事件,包括 InitLoad 和 PreRender事件。而且,可以向母版頁添加自己的自定義屬性和方法,內容頁可以使用它們與母版頁進行交互。考慮下面添加到此應用程序母版頁中的 Property

Public Property SubTitle() As String 
Get 
Return lblSubTitle.Text 
End Get 
Set(ByVal value As String) 
lblSubTitle.Text = value 
End Set 
End Property

SubTitle屬性是 Label 控件 Text 屬性的包裝,該屬性被添加到母版頁。根據內容頁,下面的代碼可用於設置母版頁的 SubTitle屬性:

Dim m As MasterPage_master 
m = DirectCast(Master, MasterPage_master) 
m.SubTitle = “Now Showing: Content page at “+ Now.ToString()

內容頁的 Master 屬性是一種由 System.Web.UI.Page類公開的屬性。Master 屬性返回一個 MasterPage 對象,必須將該對象轉換爲派生的母版頁類的實際類型。保存爲 FileName.master 的母版頁文件的類名爲 FileName_master,因此本例中的派生類型爲 MasterPage_master。一旦正確地進行了類型轉換,就可以以一種類型安全的方式訪問母版頁的自定義屬性和方法。

如果對直接訪問母版頁中的控件感興趣,可以使用 FindControl方法來獲得對目標控件的引用(如果它存在)。下面的代碼使用 Master.FindControl 直接訪問副標題 Label

Dim lblSubTitle As Control 
lblSubTitle = Master.FindControl(“lblSubTitle”) 
If Not lblSubTitle Is Nothing Then 
If TypeOf lblSubTitle Is Label Then 
DirectCast(lblSubTitle, Label).Text = “Hello world" 
End If 
End If

Visual Studio 2005 的文檔聲明以下內容,可以從內容頁的 Master 屬性直接訪問母版頁的自定義公共屬性。例如,Master.UserLoginName = ¡°ethan¡±,其中 UserLoginName是母版頁的自定義屬性。在本書所使用的 Visual Studio 2005 預覽版中,Master 屬性始終返回一個 System.Web.UI.MasterPage對象,因此訪問 Master.UserLoginName將引起編譯錯誤。必須將 Master 轉換爲母版頁的類型,然後按照前一個示例的說明訪問自定義屬性。一種實現這種類型轉換的簡單方法是:DirectCast(Master, MasterPage_master).UserLoginName。

使用主題

可以使用 @Page指令的 theme 屬性來控制主題,也可以在 web.config 中使用 <pages>元素爲整個 Web 站點指定主題。用 @Page指令選擇主題非常簡單:

<%@ page language="VB”Theme="BasicBlue”%>

除了需要將設置放在 web.config 文件中而不是 @Page 指令中之外,爲整個站點指定主題真的非常簡單:

<?xml version="1.0”encoding="UTF-8”?> 
<configuration> 
<system.web> 
<pages theme="BlackAndWhite”/> <compilation debug="false”/> 
<globalization requestEncoding="utf-8”responseEncoding="utf-8”/> 
</system.web> 
</configuration>

在此應用程序中,BlackAndWhite 主題是一個自定義主題,該主題將黑色用於一些常用控件的背景色,而將白色用於前景色。圖 6-33 顯示在瀏覽器中查看時的最終效果:


6-33 Internet Explorer 中使用 BlackAndWhite 主題的內容頁。

創建自定義主題

使用 ASP.NET 2.0 中的預構建主題來徹底檢驗這種新技術是可行的,但這對於實際開發而言並不很實用,因爲每個站點都要求其自己的視覺效果與公司的品牌策略保持一致,或者實現圖形設計師的意圖。幸運的是,創建 ASP.NET 主題非常容易。首先,在 Web 站點文件夾中創建一個 Themes 文件夾。然後,在 Themes 文件夾中創建一個與主題具有相同名稱(如 BlackAndWhite)的文件夾。接下來,創建 .css 和 .skin 文件,您可以在其中定義服務器控件和其他 HTML 的幾乎任何可視化特徵。圖 6-34 顯示某個 Web 站點項目的 .skin 文件,以及可以在解決方案資源管理器中看到的 BlackAndWhite 主題文件夾。


6-34 在 Visual Studio 2005 中編輯 .skin 文件。

小結

在 ASP.NET 2.0 之前,由於對健壯的 Web 站點模板和外觀的支持有限,Microsoft Web 開發人員處於不利的狀況。許多開發人員依靠“頁眉和頁腳用戶控件”方法來保持 Web 站點外觀的一致性,但讓他們感到失望的是,設計時體驗並不理想,並且難以將 Web 圖形設計器完成的工作集成到用戶控件中,從而創建具有良好外觀的 Web 站點。ASP.NET 2.0 中引入母版頁和主題使得創建基於模板的 Web 站點簡單而又靈活。Visual Studio 2005 中的設計時體驗非常特別。將母版頁與主題相結合,使得創建具有一致外觀的專業 Web 頁非常容易,並且無需犧牲開發人員的工作效率或站點的長期可維護性。

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章