DetailsView控件

以至於讓ASP.NET開發人員不滿足於此,而是希望它能提供更多功能。DataGrid控件在ASP.NET 2.0中並沒有發生太大變化,只是添加了兩個分別名爲GridView和DetailsView的新控件,它們提供了通常要求DataGrid控件所具有的功能,並且還加入了一些屬於它們自己的新功能。

    GridView呈現HTML表的方式與DataGrid一樣,但與DataGrid不同的是,GridView可以完全依靠自己來分頁和排序。GridView還支持比DataGrid種類更爲豐富的列類型(在GridView用語中稱爲字段類型),並且它們具有更爲智能的默認呈現行爲,能夠自動呈現Boolean值(例如,通過複選框)。GridView也可以容易地與DetailsView搭配使用,以創建主-從視圖。GridView控件的主要缺陷是:像DataGrid一樣,它通過將信息傳回到服務器來完成它該做的大部分工作。

    圖6 中的頁面結合使用了GridView和DetailsView,以創建Pubs數據庫的Titles表的簡單主-從視圖。SqlDataSource控件爲其他控件提供數據,而綁定到DetailsView控件的SqlDataSource中的SelectParameter使DetailsView能夠顯示GridView中當前選擇的記錄。可以通過單擊GridView的Select按鈕(該按鈕因標記中的AutoGenerateSelectButton="true"屬性而存在)來選擇記錄。

<%@ Page Theme="BasicBlue" %>

<html>
    <body>
        <form runat="server">
            <asp:SqlDataSource ID="Titles1" RunAt="server"
                ConnectionString="server=localhost;database=pubs;Integrated Security=SSPI"
                SelectCommand="select title_id, title, price from titles"
            />
            <asp:SqlDataSource ID="Titles2" RunAt="server"
                ConnectionString="server=localhost;database=pubs;Integrated
                Security=SSPI"
                SelectCommand="select title_id, title, price from titles where
                title_id=@title_id"
            >
                <SelectParameters>
                    <asp:ControlParameter Name="title_id"
                        ControlID="MyGridView"
                        PropertyName="SelectedValue"
                    />
                </SelectParameters>
            </asp:SqlDataSource>
            <table><tr><td>
                <asp:GridView ID="MyGridView" DataSourceID="Titles1"
                    Width="100%" RunAt="server" AutoGenerateColumns="false"
                    SelectedIndex="0" AutoGenerateSelectButton="true"
                    DataKeyNames="title_id"
                >
                    <Columns>
                        <asp:BoundField HeaderText="Title ID"
                            DataField="title_id"
                        />
                        <asp:BoundField HeaderText="Book Title" DataField="title" />
                        <asp:BoundField HeaderText="Price" DataField="price"
                            DataFormatString="{0:c}" NullDisplayText="TBD"
                        />
                    </Columns>
                </asp:GridView>
            </td></tr>
            <tr><td>
                <asp:DetailsView DataSourceID="Titles2" RunAt="server"
                    AutoGenerateRows="false" Width="100%"
                >
                    <Fields>
                        <asp:BoundField HeaderText="Title ID"
                            DataField="title_id"
                        />
                        <asp:BoundField HeaderText="Book Title"
                            DataField="title"
                        />
                        <asp:BoundField HeaderText="Price" DataField="price"
                            DataFormatString="{0:c}" NullDisplayText="TBD"
                        />
                    </Fields>
                </asp:DetailsView>
            </td></tr></table>
        </form>
    </body>
</html>

圖6 MasterDetail.aspx

    請注意GridView和DetailsView控件中用於定義字段類型的和元素。這些元素實際上等效於DataGrid控件中的元素。圖7 列出了受支持的字段類型。特別重要的是ImageField和DropDownListField,它們都可以有效地削減目前開發人員爲在DataGrid中包含圖像和數據綁定下拉列表而編寫的大部分代碼。

字段類型 描述
AutoGeneratedField 默認字段類型
BoundField 綁定到數據源指定列
ButtonField 顯示一個按鈕、圖片按鈕或者鏈接按鈕
CheckBoxField 顯示一個複選框
CommandField 顯示一個用於選擇或者編輯的按鈕
DropDownListField 顯示一個下拉列表
HyperLinkField 顯示一個超級鏈接
ImageField 顯示一個圖片
TemplateField 內容由HTML模板來定義

圖7 GridView and DetailsView字段類型

新增的管理功能

    ASP.NET 1.x的另一個明顯的缺陷(已經在ASP.NET 2.0中得到修復)是根本沒有用於管理Web站點的接口(無論是聲明性接口還是編程接口)。在過去,更改配置設置意味着啓動記事本並編輯Machine.config或Web.config,但現在不再需要這麼做了。ASP.NET 2.0具有一個完善的管理API,它簡化了讀取和寫入配置設置的任務。它還包括一個管理GUI,您可以通過在瀏覽器中請求Webadmin.axd來顯示該GUI,如圖8所示。


圖8 管理GUI

    儘管在撰寫本文時尚不完善,但Webadmin.axd被設計爲使您可以配置ASP.NET 2.0中包含的各種服務(如成員身份和角色管理服務)、查看Web站點統計信息以及應用安全設置。

成員身份服務

    ASP.NET 2.0中新增的最佳功能之一是新的成員身份服務,它提供了用於創建和管理用戶帳戶的易於使用的API。ASP.NET 1.x大規模引入了窗體身份驗證,但仍然要求您編寫相當數量的代碼來執行實際操作中的窗體身份驗證。成員身份服務填補了ASP.NET 1.x窗體身份驗證服務的不足,並且使實現窗體身份驗證變得比以前簡單得多。

    成員身份API通過兩個新的類公開:Membership和MembershipUser。前者包含了用於創建用戶、驗證用戶以及完成其他工作的靜態方法。MembershipUser代表單個用戶,它包含了用於檢索和更改密碼、獲取上次登錄日期以及完成類似工作的方法和屬性。例如,下面的語句採用用戶名和密碼作爲參數,並返回true或false來指示它們是否有效。它取代了對ASP.NET 1.x應用程序中、使用Active Directory?或後端數據庫來驗證憑據的簡易方法的調用,如下所示:

bool isValid = Membership.ValidateUser (username, password);

    下面的語句返回一個MembershipUser對象,該對象表示用戶名爲“jeffpro”的用戶:

MembershipUser user = Membership.GetUser ("jeffpro");

    以下語句檢索一個已註冊用戶的電子郵件地址(假設記錄了電子郵件地址):

string email = user.Email;

    成員身份服務所管理的用戶名、密碼和其他數據存儲在哪裏?像ASP.NET 2.0中的幾乎所有狀態管理服務一樣,成員身份是基於提供程序的。提供程序是使服務可以與物理數據源進行交互的模塊。ASP.NET 2.0將包含Microsoft Access數據庫、SQL Server數據庫和Active Directory的成員身份提供程序,並且還可能包含其他數據存儲的成員身份提供程序。

    默認情況下,成員身份服務使用Access提供程序,並將成員身份數據存儲在應用程序的Data子目錄中名爲AspNetDB.mdb的文件中。可以通過Web.config的部分選擇備用提供程序。可以讓Webadmin.axd修改Web.config,而不必自己進行修改。下面的內容節選自Web.config(在Webadmin.axd創建了一個名爲WhidbeyLogin的SQL Server?數據庫,並將成員身份服務配置爲使用該數據庫之後):

<membership defaultProvider="WhidbeyLogin">
    <providers>
        <add name="WhidbeyLogin"
            type="System.Web.Security.SqlMembershipProvider, ..."
            connectionStringName="webAdminConnection632112624221191376"
            applicationName="/Whidbey" requiresUniqueEmail="false"
            enablePasswordRetrieval="true" enablePasswordReset="false"
            requiresQuestionAndAnswer="false"
            passwordFormat="Encrypted"
        />
    </providers>
</membership>

    connectionStringName屬性引用了Web.config的新部分中的連接字符串。ASP.NET 2.0將包含加密這部分的Web.config以保護數據庫連接字符串的能力。

    Webadmin.axd的用途並不僅限於創建數據庫和選擇成員身份提供程序:它還可以用於創建用戶、管理憑據以及其他用途。在Webadmin.axd和成員身份API之間,還存在用於管理站點註冊用戶的聲明性手段和編程手段。這是從ASP.NET 1.x向前邁出的一大步,它在很大程度上將憑據管理的問題留給用戶自己去處理。

登錄控件

    成員身份服務本身就顯著減少了驗證登錄和管理用戶所需的代碼量,此外還有一系列稱爲登錄控件的新控件使窗體身份驗證變得更加容易。登錄控件可以與成員身份服務配合使用,也可以不與其配合使用,但它們與該服務之間的集成性非常好,以至於當登錄控件與成員身份服務一起使用時,一些基本任務(例如,驗證用戶名和密碼以及用電子郵件發送遺忘的密碼)通常不必編寫任何代碼就可以完成。“新增控件”提要欄包含了計劃隨ASP.NET 2.0一起提供的一系列登錄控件。


圖9 Login控件

    圖9中所示的Login控件是登錄控件系列的核心控件。除了提供具有高度可自定義性的UI以外,它還能夠調用Membership.ValidateUser來驗證用戶名和密碼。Login控件還可以調用FormsAuthentication.RedirectFromLoginPage,將用戶重定向到他們在被重定向到登錄頁時嘗試到達的頁面。然後,FormsAuthentication.RedirectFromLoginPage將發出身份驗證Cookie。在本文稍後的部分中,您將看到Login和其他登錄控件的工作方式。

角色管理器

    如果不支持基於角色的安全性,那麼成員身份服務和登錄控件將是不完善的。在ASP.NET 1.x中,要將窗體身份驗證與角色結合起來,需要編寫代碼以將角色信息映射到各個傳入的請求。ASP.NET 2.0中新的角色管理器(它可以與成員身份服務配合使用,也可以不與其配合使用)取消了對此類代碼的需求,並且簡化了基於角色授予用戶訪問各種資源權限的任務。

    角色管理是基於提供程序的,它通過Web.config啓用。角色管理器通過新的Roles類來公開API,該類公開了名爲CreateRole、DeleteRole和AddUserToRole等的方法。值得注意的是,您或許永遠不需要調用這些方法,因爲Webadmin.axd完全能夠創建角色、將用戶分配給角色以及完成其他任務。一旦啓用,基於角色的安全性就能夠使用所提供的角色信息以及Web.config文件中的URL身份驗證指令來工作—這與ASP.NET 1.x中您已經熟悉的URL身份驗證相同。

    既然您已經熟悉了成員身份服務、登錄控件以及ASP.NET角色管理器,那麼您或許希望看到同時使用這三者的示例。本文可下載的代碼示例包含一個兩頁的應用程序,它演示了Visual Studio 2005樣式的窗體身份驗證。要部署該應用程序並對其進行測試,請首先將PublicPage.aspx、LoginPage.aspx和Web.config複製到Web服務器的某個虛擬目錄中。在該虛擬目錄中創建一個名爲Secure的子目錄,然後將ProtectedPage.aspx和其他Web.config文件複製到該子目錄中。

    啓動Webadmin.axd,並且將站點配置爲使用窗體身份驗證,將成員身份和角色服務配置爲使用您選擇的提供程序。同時,還要創建名爲Bob和Alice的用戶以及名爲Manager和Developer的角色。將Bob指定爲Manager角色,將Alice指定爲Developer角色。(我不會列出所有步驟,因爲在您使用任一方法閱讀本文之前,它們很可能會改變。幸運的是,Webadmin.axd相當直觀,並且它具有嚮導,可以引導您完成設置過程。)

    接下來,在瀏覽器中激活PublicPage.aspx,並單擊“View Secret Message”按鈕以查看ProtectedPage.aspx。ASP.NET會將您重定向到LoginPage.aspx,該頁面使用Login控件來請求用戶名和密碼。使用Bob的用戶名和密碼登錄。ProtectedPage.aspx應該顯示在瀏覽器窗口中,因爲Bob是Manager,並且可以通過Secure目錄中的Web.config文件將訪問權授予經理。請注意LoginName控件顯示的用戶名以及LoginStatus控件顯示的“Log out”鏈接。最後,關閉瀏覽器,然後重新打開它並重新激活PublicPage.aspx。單擊“View Secret Message”並以Alice的身份登錄。這一次,您將無法到達ProtectedPage.aspx,因爲Alice不是經理。

    我使用了一個類似的應用程序來講述ASP.NET 1.x中的窗體身份驗證,但1.x版本要求編寫非常多的代碼。2.0版本因其簡潔而不同尋常,尤其是沒有任何用於驗證在登錄窗體中鍵入的憑據、或者將用戶名映射到角色的代碼。如果您仍然不相信,請嘗試用ASP.NET 1.x實現同一應用程序!此外,請確保檢驗Webadmin.axd對Web.config所作的更改。除了其他內容以外,您還應該看到一個啓用角色Manager並且可能會指定角色管理提供程序的元素。

    您可能很想知道角色Manager是否經過了到數據庫(在其中,角色被存儲到每個請求中)的往返行程。值得慶幸的是,答案是“否”。它將角色編碼到Cookie中,並且爲了保密而將它們加密。如果一個用戶對應了衆多的角色(這種情況不太可能發生),以至於無法將這些角色編碼到一個Cookie中,則該Cookie將包含一個最近使用角色的列表,並且僅在迫不得已時才查詢數據庫。

個性化

    另一個新增的服務是個性化,它提供了一種現成的解決方案,用於解決存儲站點用戶的個性化設置問題。目前,此類設置通常存儲在Cookie、後端數據庫或這兩者中。無論這些設置存儲在何處,ASP.NET 1.x都不能提供什麼幫助。這需要由您來設置和管理後端數據存儲,以及使用經過身份驗證的用戶名、Cookie或其他某種機制來關聯個性化數據。

    ASP.NET 2.0個性化服務使得存儲各個用戶的設置以及隨意檢索這些設置變得非常容易。該服務基於用戶配置文件—您可以使用新的元素在Web.config中予以定義。下面的代碼節選自Web.config:

<profile>
    <properties>
        <add name="Theme" />
        <add name="Birthday" Type="System.DateTime" />
        <add name="LoginCount" Type="System.Int32" defaultValue="0" />
    </properties>
</profile>

    它定義了一個包含三個屬性的配置文件:一個名爲Theme的字符串,一個名爲Birthday的DateTime值,以及一個名爲LoginCount的整數。後面這個屬性被賦予默認值0。

    在運行時,您可以使用頁面的Profile屬性(該屬性引用包含該配置文件中定義的屬性的動態編譯類的實例)來訪問當前用戶的這些屬性。例如,下列語句可從當前用戶的配置文件中讀取屬性值:

string theme = Profile.Theme;
DateTime birthday = Profile.Birthday;
int logins = Profile.LoginCount;

    還可以將值賦予配置文件屬性:

Profile.Theme = "SmokeAndGlass";
Profile.Birthday = new DateTime (1959, 9, 30);
Profile.LoginCount = Profile.LoginCount + 1;

    個性化服務的一個明顯優勢是強類型化。另一個優勢在於個性化數據是按需讀寫的。請將此與會話狀態(無論是否使用,都會將其加載並保存到每個請求中)進行對比。但是,個性化服務的最大優勢可能在於您不必顯式地將數據存儲在任何位置;系統會替您完成該工作,並且它會永久性地存儲數據,以便數據在您需要時隨時可用。配置文件不會像會話那樣超時。

    那麼,個性化數據存儲在哪裏呢?這要依具體情況而定。個性化服務基於提供程序,因此您可以將其配置爲使用任何可用的提供程序。ASP.NET 2.0將至少附帶兩個個性化提供程序:一個用於Access,另一個用於SQL Server。如果您不另行指定,則個性化服務將使用Access提供程序,默認情況下,該提供程序會將個性化數據存儲在本地Data/AspNetDB.mdb中。您可以通過修改Web.config(手動或使用Webadmin.axd)來改用SQL Server數據庫。如果您不希望將個性化數據存儲在Access數據庫或SQL Server數據庫中,則可以編寫自己的提供程序。

    默認情況下,ASP.NET使用經過身份驗證的用戶名作爲所存儲的個性化數據的鍵,但您也可以將其配置爲支持匿名用戶。首先,通過將以下語句添加到Web.config中來啓用匿名標識:

<anonymousIdentification enabled="true" />

    然後,將allowAnonymous="true"添加到您要爲匿名用戶存儲的配置文件屬性中:

<name="Theme" allowAnonymous="true" />

    現在,Theme屬性可以作爲個性化設置使用,而無論站點的調用方是否經過了身份驗證。

    默認情況下,匿名標識使用Cookie來標識回返用戶。由支持的屬性可以用各種方式來配置這些Cookie。例如,您可以指定Cookie名稱,並指明是否應該將該Cookie的內容加密。您還可以將個性化服務配置爲使用無Cookie的匿名標識,因此它將依靠URL Munging來標識回返用戶。甚至還存在一個自動檢測選項:如果請求瀏覽器支持Cookie,則使用Cookie;如果不支持,則使用URL Munging。

    要查看個性化的工作方式,請運行本文隨附的下載資料中的Personalize.aspx示例。它會讓站點的每個訪問者選擇一個主題,然後記錄該主題,並且每當該訪問者返回時都將應用該主題。請注意,該主題是在頁面的PreInit事件(它是一個新事件,它的激發時間甚至早於Init)中以編程方式應用於該頁面的。

    在您運行該示例之前,需要啓用匿名標識,並定義一個包含名爲Theme的字符串屬性的配置文件。以下代碼行顯示了執行上述兩項任務的Web.config文件:

<configuration>
    <system.web>
        <anonymousIdentification enabled="true" />
        <profile>
            <properties>
                <property name="Theme" allowAnonymous="true" />
            </properties>
        </profile>
    </system.web>
</configuration>

SQL緩存依賴性

    ASP.NET 1.x中令人遺憾地缺少的另一項功能是數據庫緩存依賴性。可以將ASP.NET應用程序緩存中放置的項目與其他緩存項目聯繫起來,或者與文件系統中的對象聯繫起來,但不能與數據庫實體聯繫起來。ASP.NET 2.0通過引入SQL緩存依賴性來糾正這一由於疏忽而造成的錯誤。

    SQL緩存依賴性由新的SQLCacheDependency類的實例表示。它們的用法非常簡單。下面的語句將一個名爲ds的數據集插入到應用程序緩存中,並且在該數據集和Northwind數據庫的Products表之間創建依賴性:

Cache.Insert ("ProductsDataSet", ds,
    new SqlCacheDependency ("Northwind", "Products");

    如果Products表的內容改變,則ASP.NET會自動刪除該數據集。

    SQL緩存依賴性還可以與ASP.NET輸出緩存配合使用。下面的指令指示ASP.NET緩存來自包含頁面的輸出,直至Products表的內容改變或者滿60秒爲止(滿足任一條件即可):

<%@ OutputCache Duration="60" VaryByParam="None"
    SqlDependency="Northwind:Products"
%>        

    SQL緩存依賴性適用於SQL Server 7.0、SQL Server 2000和即將問世的SQL Server 2005。對於SQL Server 2005,無需進行任何準備;但必須將SQL Server 7.0和SQL Server 2000數據庫配置爲支持SQL緩存依賴性。準備工作涉及到創建數據庫觸發器,以及創建一個特殊的表,以供ASP.NET在確定是否已經發生更改時參考。該表由一個後臺線程使用可配置的輪詢間隔(默認爲5秒鐘)來定期輪詢。在SQL Server 2005中,要檢測更改,既不需要特殊的表,也不需要輪詢。此外,SQL Server 2005緩存依賴性可以在行級應用,而SQL Server 7.0和SQL Server 2000緩存依賴性在表級工作。您可以使用Aspnet_regsqlcache.exe工具或Webadmin.axd來準備數據庫,以使其支持SQL緩存依賴性。

新的動態編譯模型

    ASP.NET 1.x中引入的衆多創新之一是:系統能夠在首次訪問您的代碼時對其進行編譯。但是,只有頁面能夠被自動編譯,並且輔助類(如數據訪問組件)必須單獨編譯。

    ASP.NET 2.0擴展了動態編譯模型,以便能夠自動編譯幾乎所有的組件。bin目錄仍然保留以便實現向後兼容性,但它現在添加了名爲Code和Resources的目錄。Code目錄中的C#和Visual Basic文件以及Resources目錄中的RESX和RESOURCE文件被ASP.NET自動編譯並緩存在系統子目錄中。此外,落入Code目錄中的Web服務描述語言(WSDL)文件被編譯爲Web服務代理,而XML架構定義語言(XSD)文件被編譯爲類型化數據集。通過Web.config,還可以擴展這些目錄以支持其他文件類型。

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