ASP.NET 2.0個性化配置(profile)

爲每個用戶存儲配置信息
強類型 長期保存  支持匿名用戶
定義配置(profile)
<?xml version="1.0"?>

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
    
<appSettings/>
    
<connectionStrings>
        
<add name="Northwind" connectionString="Server=localhost;Integrated Security=True;Database=Northwind" providerName="System.Data.SqlClient"/>
    
</connectionStrings>
    
<system.web>

        
<anonymousIdentification enabled="true" />
        
<profile>   //定義配置(profile)
            
<properties>
                
<add name="Theme" allowAnonymous="true" />
                
<add name="LastVisit" type="System.DateTime" allowAnonymous="true" />
            
</properties>
        
</profile>
<!--
        <webParts>  //定義配置(webParts)
            <personalization defaultProvider="AspNetSqlPersonalizationProvider"/>
        </webParts>
-->
        
<!-- 
            Set compilation debug="true" to insert debugging symbols into the compiled page.
            Because this affects performance, set this value to true only during development.
        
-->
        
<compilation debug="true">
            
<expressionBuilders>
                
<add expressionPrefix="Version" type="VersionExpressionBuilder"/>
            
</expressionBuilders>
        
</compilation>
        
<!--
            The <authentication> section enables configuration of the security authentication
            mode used by ASP.NET to identify an incoming user. 
        
-->
        
<authentication mode="Windows"/>
        
<!--
            The <customErrors> section enables configuration of what to do if/when an unhandled
            error occurs during the execution of a request.  Specifically, it enables developers
            to configure html error pages to be displayed in place of a error stack trace.
        
-->
        
<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
            
<!-- 
            <error statusCode="403" redirect="NoAccess.htm"/>
            <error statusCode="404" redirect="FileNotFound.htm"/>
        
-->
        
</customErrors>
    
</system.web>
</configuration>

使用配置(profile)
//increment the current user's post cout
profile.posts = profile.posts+1;
// update the current user's last post date
profile.lastpost = datetime.now;

個性化數據將存入數據庫
介紹
Microsoft ASP.NET 2.0支持被稱爲Profile的新對象,它可以自動在多個Web應用程序的訪問之間存儲用戶信息。一個User Profile中可以存儲各種類型的信息,這些信息既可以是簡單的string和integer類型,也可以是複雜的自定義類型。例如,你可以存儲用戶的姓、購物籃、用戶屬性或網站使用情況統計。
本文中,你將學習如何在一個應用中定義user profile。我們也會向你演示如何配置使用不同provider的profile。最後,你將學習如何管理和生成user profile的報告。
User Profiles總攬
Profile 對象與Session對象十分相似,但是更好用一些。與Session相似的地方在於,Profile是相對於一個特定的用戶的,也就是說,每個Web應用程序的用戶都有他們自己的profile對象。與Session不同的是,Profile對象是持久對象。如果你向Session中添加一個項,在你離開網站時,該項就會消失。而Profile則完全不同,當你修改Profile的狀態時,修改在多個訪問之間均有效。
profile使用provider模式來存儲信息,默認情況下,user profile的內容會保存在SQL Server Express數據庫中,該數據庫位於網站的App_Data目錄。然而,在本文的後半部分,你將瞭解如何使用其他數據提供者(data provider)來存儲信息,如完整版的SQL Server中的一個數據庫或者一個Oracle數據庫。
與Session不同,Profile是強類型的,Session對象僅僅是一個項集合而已,而profile對象則有強類型屬性。
使用強類型是有它的道理的。例如,使用強類型,你就可以在Microsoft Visual Web Developer中使用智能感知技術,當你鍵入Profile和一個點的時候,智能感知會彈出你已經定義過的profile屬性列表。
定義user profile
你既可以在machine.config中,也可以在web.config中定義一個user profile,由於你不能在應用程序的二級目錄中創建一個包含文件profile節的web.config文件,這意味着你將無法在一個應用程序中定義兩個以上的profile。
在列表1的web.config中,列舉了一個簡單的profile定義的實例,該profile有三個屬性,FirstName, LastName和PageVisits。
列表1
<configuration>
 
<system.web>
   
<authentication mode="Forms" />
      
           
<anonymousIdentification enabled="true" />
        
   
<profile>
               
<properties>
                  
<add 
        
name="FirstName"  
        defaultValue
="??"
        allowAnonymous
="true" />
      
<add 
        
name="LastName" 
        defaultValue
="??"
        allowAnonymous
="true" />
      
<add 
        
name="PageVisits"
        type
="Int32" 
        allowAnonymous
="true"/>
               
</properties>
           
</profile>
 
</system.web>
</configuration>

    由於該profile需要同時被匿名用戶和已認證用戶使用,因此我們在web.config文件中增加包含一個< anonymousIdentification>元素,有了這個元素,系統就會自動爲匿名用戶生成唯一的ID。仔細看的話我們會發現,每一個 profile屬性都有一個allowAnonymous特性,該特性表明這個profile屬性是否允許被匿名用戶使用。
    默認的profile屬性類型是System.String類型。列表1中,由於沒有爲FirstName和LastName這兩個profile屬性增加type特性,那麼系統默認它們是string類型,而PageVisits屬性則指定了type特性爲Int32,因此該profile屬性可用於表示一個整型值。
    最後,注意FirstName和LastName屬性都有defaultValue特性。你可以爲簡單的數據類型設置defaultValue特性,但你不能爲複雜類型設置defaultValue特性。
 
    當你定義好一個profile之後,系統會自動在下一次頁面被調用時,生成一個與該profile相對應的類。這個類會被保存在"Temporary ASP.NET Files Directory"目錄(該目錄也用於存放用於動態生成頁面的類)。你可以使用HttpContext的Profile屬性(Property)調用該類。
    當你定義好一個profile後,你可以使用如下方法爲profile屬性賦值。

[Visual Basic .NET]
Profile.FirstName 
= "Bill"

[C#]
Profile.FirstName 
= "Bill";
任何在web.config中定義的profile屬性都會在Profile對象中呈現。
列表2演示了你該如何使用profile來持久化保存用戶信息。這個頁顯示了FirstName,LastName, PageVisits三個屬性的值,同時它包含了一個能夠用於修改這三個屬性的表單(form)。在Page_Load中更新PageVisits的值,這意味着每一次刷新頁面,PageVisits的值都會改變。
圖1 使用簡單的profile

列表 2. Simple.aspx (C#)<%@ Page Language="C#" %>
<script runat="server">

    
void Page_Load() {
        Profile.PageVisits 
++;
    }
    
    
void UpdateProfile(Object s, EventArgs e) {
        Profile.FirstName 
= txtFirstName.Text;
        Profile.LastName 
= txtLastName.Text;
    }
    
</script>

<html>
<head>
    
<title>Simple</title>
</head>
<body>
    
<form id="form1" runat="server">
    
<b>Name:</b> <%= Profile.FirstName %> <%= Profile.LastName %>
    
<br />
    
<b>Page Visits:</b> <%= Profile.PageVisits %>
    
    
<hr />
    
    
<b>First Name:</b>
    
<asp:TextBox ID="txtFirstName" Runat="Server" />
    
<br />
    
<b>Last Name:</b>
    
<asp:TextBox ID="txtLastName" Runat="Server" />
    
<br />
    
<asp:Button ID="Button1" 
        Text
="Update Profile" 
        OnClick
="UpdateProfile" 
        Runat
="server" />

    
</form>
</body>
</html>
 

如果你多次訪問列表2中的頁面,你會注意到PageVisits在不斷增大。如果你關閉的瀏覽器,並在一週之後調用該頁面,PageVisits屬性仍然會保留原值。從這一點可以看出Profile爲每個用戶自動保存一個副本。
使用Profile組
儘管你僅可以爲一個應用程序定義一個profile,但如果你需要讓幾個profile屬性一起工作,把它們放在組中,會讓你覺得它們更易管理。
例如,在列表3中,有一個帶有兩個組的profile,這兩個組分別是Address和Preferences
列表3. Web.Config
<configuration>
<system.web>
      
   
<anonymousIdentification enabled="true" />
        
   
<profile>
               
<properties>
   
<group name="Address">
                  
<add 
         
name="Street"  
         allowAnonymous
="true" />
                 
<add 
         
name="City"  
         allowAnonymous
="true" />
   
</group>
   
<group name="Preferences">
      
<add 
         
name="ReceiveNewsletter" 
         type
="Boolean"
         defaultValue
="false"
         allowAnonymous
="true" />
   
</group>
              
</properties>
        
</profile>
</system.web>
</configuration>

當你用組來定義profile時,你應該使用組名來設置或讀取profile屬性。例如,在列表3中,你可以使用以下一些句子來完成三個profile屬性的賦值。

[C#]

Profile.Address.City 
= "Modesto";
Profile.Address.Street 
= "111 King Arthur Ln";
Profile.Preferences.ReceiveNewsletter 
= false;
一個profile的定義只能包含一層組,換句話說,你不能把其他的組放在一個profile組的下面一層。
使用複雜的profile屬性
到目前爲止,我們已經介紹了聲明包含簡單類型(如string或整型)屬性的profile,其實你也可以在profile中聲明覆雜屬性。
舉個例子,假設你現在需要在profile中存儲一個購物籃,如果這樣做的話,你就可以在每次訪問網站時獲得自己的購物籃。
列表4 聲明瞭一個包含profile,這個profile包含一個名爲ShoppingCart的屬性,而該屬性的type特性是一個叫ShoppingCart的類(我們接下來會創建該類),該類名是有效的。
我們還會注意到,該聲明中包含一個serializeAs特性,該特性可以幫助ShoppingCart使用二進制序列化器(binary serializer)進行持久化,而不是使用xml序列化器。
列表4 Web.config

<
configuration>
<system.web>

  
<anonymousIdentification enabled="true" />
  
  
<profile>
    
<properties>
    
<add 
       
name="ShoppingCart"
       type
="ShoppingCart"
       serializeAs
="Binary"
       allowAnonymous
="true" />
    
</properties>
  
</profile>
</system.web>
</configuration>

列表5 中有一個簡單購物籃的實現代碼,該購物籃擁有添加和刪除項(item)的方法(method),同時它還擁有兩個屬性(property),一個是用於獲得該購物籃中的所有項的,一個是用於表示所有商品的總價的。
列表5 ShoppingCart (c#)

using
 System;
using System.Collections;

[Serializable]
public class ShoppingCart
{
    
public Hashtable _CartItems = new Hashtable();

    
// Return all the items from the Shopping Cart
    public ICollection CartItems
    {
        
get { return _CartItems.Values; }
    }

    
// The sum total of the prices
    public decimal Total
    {
        
get 
        {
            
decimal sum = 0;
            
foreach (CartItem item in _CartItems.Values)
                sum 
+= item.Price * item.Quantity;
            
return sum;
        }
    }

    
// Add a new item to the shopping cart
    public void AddItem(int ID, string Name, decimal Price)
    {
        CartItem item 
= (CartItem)_CartItems[ID];
        
if (item == null)
            _CartItems.Add(ID, 
new CartItem(ID, Name, Price));
        
else
        {
            item.Quantity
++;
            _CartItems[ID] 
= item;
        }
    }

    
// Remove an item from the shopping cart
    public void RemoveItem(int ID)
    {
        CartItem item 
= (CartItem)_CartItems[ID];
        
if (item == null)
            
return;
        item.Quantity
--;
        
if (item.Quantity == 0)
            _CartItems.Remove(ID);
        
else
            _CartItems[ID] 
= item;
    }

}

[Serializable]
public class CartItem
{
    
private int _ID;
    
private string _Name;
    
private decimal _Price;
    
private int _Quantity = 1;

    
public int ID
    {
        
get { return _ID; }
    }

    
public string Name
    {
        
get { return _Name; }
    }

    
public decimal Price
    {
        
get { return _Price; }
    }

    
public int Quantity
    {
        
get { return _Quantity; }
        
set { _Quantity = value; }
    }

    
public CartItem(int ID, string Name, decimal Price)
    {
        _ID 
= ID;
        _Name 
= Name;
        _Price 
= Price;
    }
}

如果你把列表5中的代碼添加到應用程序的App_Code目錄中,購物籃會自動被編譯。
在列表5中有一點值得注意,那就是ShoppingCart和CartItem類都加上了可序列化的特性,這一點對於他們能否被序列化十分重要,只有這樣才能保存在Profile對象中。
最後,列表6的頁面顯示了可以被添加到購物籃中的產品。購物籃是通過BindShoppingCart方法從Profile對象中載入,該方法把購物籃中的對象綁定到一個GridView對象上,這些對象可以通過ShoppingCart類的CartItems屬性獲得。


圖2 在profile中存儲購物籃
AddCartItem方法用於在購物籃中添加一個產品,該方法中包含了檢測Profile是否存在ShoppingCart的代碼。對於Profile中存儲的對象,你必須自己實例化這些對象,他們不會自動實例化。
RemoveCartItem方法用於從購物籃中移除一個產品,該方法只是簡單地通過調用Profile中的ShoppingCart對象的RemoveItem方法。
列表 6. Products.aspx (C#)

<%
@ Page Language="C#" %>
<%@ Import Namespace="System.Globalization" %>
<script runat="server">

    
void Page_Load() {
        
if (!IsPostBack)
            BindShoppingCart();
    }
        
    
void BindShoppingCart() 
    {
        
if (Profile.ShoppingCart != null
        {
            CartGrid.DataSource 
= Profile.ShoppingCart.CartItems;
            CartGrid.DataBind();
            lblTotal.Text 
= Profile.ShoppingCart.Total.ToString("c");
        }
    }
   
    
void AddCartItem(Object s, EventArgs e) 
    {
        GridViewRow row 
= ProductGrid.SelectedRow;

        
int ID = (int)ProductGrid.SelectedDataKey.Value;
        String Name 
= row.Cells[1].Text;
        
decimal Price = Decimal.Parse(row.Cells[2].Text, 
          NumberStyles.Currency);
        
        
if (Profile.ShoppingCart == null)
            Profile.ShoppingCart 
= new ShoppingCart();
       
        Profile.ShoppingCart.AddItem(ID, Name, Price);
        BindShoppingCart();
    }
    
    
void RemoveCartItem(Object s, EventArgs e) 
    {
        
int ID = (int)CartGrid.SelectedDataKey.Value;
        Profile.ShoppingCart.RemoveItem(ID);
        BindShoppingCart();
    }
</script>

<html>
<head>
    
<title>Products</title>
</head>
<body>
    
<form id="form1" runat="server">

    
<table width="100%">
    
<tr>
        
<td valign="top">
    
<h2>Products</h2>    
    
<asp:GridView
        ID
="ProductGrid"
        DataSourceID
="ProductSource"
        DataKeyNames
="ProductID"
        AutoGenerateColumns
="false"
        OnSelectedIndexChanged
="AddCartItem"
        ShowHeader
="false"
        CellPadding
="5"
        Runat
="Server">
        
<Columns>
            
<asp:ButtonField 
                CommandName
="select"
                Text
="Buy" />
            
<asp:BoundField
                DataField
="ProductName" />
            
<asp:BoundField
                DataField
="UnitPrice" 
                DataFormatString
="{0:c}" />
        
</Columns>
    
</asp:GridView>



        
    
<asp:SqlDataSource
        ID
="ProductSource"
        ConnectionString
=
"Server=localhost;Database=Northwind;Trusted_Connection=true;"
        SelectCommand
=
          
"SELECT ProductID,ProductName,UnitPrice FROM Products"
        Runat
="Server" />
        
</td>
        
<td valign="top">
        
<h2>Shopping Cart</h2>
        
<asp:GridView
            ID
="CartGrid"
            AutoGenerateColumns
="false"
            DataKeyNames
="ID"
            OnSelectedIndexChanged
="RemoveCartItem"
            CellPadding
="5" 
            Width
="300"
            Runat
="Server">
            
<Columns>
            
<asp:ButtonField
                CommandName
="select"
                Text
="Remove" />
            
<asp:BoundField
                DataField
="Name" 
                HeaderText
="Name" />
            
<asp:BoundField
                DataField
="Price" 
                HeaderText
="Price" 
                DataFormatString
="{0:c}" />
            
<asp:BoundField
                DataField
="Quantity" 
                HeaderText
="Quantity" />
            
</Columns>
        
</asp:GridView>
        
<b>Total:</b> 
        
<asp:Label ID="lblTotal" Runat="Server" />
        
</td>
     
</tr>
     
</table>
    
</form>
</body>
</html>

繼承一個profile
你也可以通過從一個已經存在的profile類中繼承一個profile來完成對profile的定義,這種特性能夠幫助你在多個應用程序中使用相同的profile。
例如,列表7中列出了一個擁有多個用戶屬性的類,該類是從ProfileBase類繼承而來的(你可以在System.Web.Profile中找到)
在列表8中的Web.config包含一個從UserInfo類繼承而來的profile,通過該聲明,新的profile可以獲得UserInfo類的所有屬性。

列表 7. UserInfo (C#)
using System;
using System.Web.Profile;

public class UserInfo : ProfileBase
{
private string _FirstName;
private string _LastName;

public string FirstName
{
get { return _FirstName; }
set { _FirstName = value; }
}
public string LastName
{
get { return _LastName; }
set { _LastName = value; }
}
}

using
 System;
using System.Web.Profile;

public class UserInfo : ProfileBase
{
    
private string _FirstName;
    
private string _LastName;

    
public string FirstName 
    {
        
get { return _FirstName; }
        
set { _FirstName = value; }
    }
    
public string LastName
    {
        
get { return _LastName; }
        
set { _LastName = value; }
    }
}

列表 8. Web.Config

<
configuration>
    
<system.web>
           
<anonymousIdentification enabled="true" />
   
<profile inherits="UserInfo" />
    
</system.web>
</configuration>


遷移匿名Profile設置
Profile對象既可用於匿名用戶也可以用於已認證用戶。然而,當用戶從匿名用戶狀態轉換爲已認證用戶狀態時,Profile對象能夠以一種令人難以理解的方式完成任務。
當匿名用戶使用Profile對象時,用戶profile是與一個隨機生成的號碼相關聯的,該號碼是根據每個用戶唯一生成的,它保存在瀏覽器的cookie中,無論何時該用戶返回應用程序,該用戶的Profile設置會被自動加載。
如果匿名用戶通過認證的話,所有與該用戶相關的profile就會丟失,同時系統會生成一個新的profile。這時該Profile信息將與用戶名相關聯,而非唯一識別號。
要想理解所有這些工作,最好的方法就是看看下面的例子。列表9中的web.config定義了一個profile,該profile只有一個FavoriteColor屬性。

列表 9 Web.config

<
configuration>
<system.web>

   
<authentication mode="Forms" />
      
           
<anonymousIdentification enabled="true" />
        
   
<profile>
   
<properties>
                  
<add 
         
name="FavoriteColor"
         allowAnonymous
="true" 
         defaultValue
="Red" />
               
</properties>
           
</profile>
</system.web>
</configuration>

列表10中有一個包含兩個按鈕的頁面,分別是login和logout按鈕,其中還有一個用於更新FavoriteColor屬性的表單。

列表10. Anonymous.aspx (C#)

<%
@ Page Language="C#" %>

<script runat="server">

    
void Login(Object s, EventArgs e)
    {
        FormsAuthentication.SetAuthCookie(
"Bill"false);
        Response.Redirect(Request.Path);
    }

    
void Logout(Object s, EventArgs e)
    {
        FormsAuthentication.SignOut();
        Response.Redirect(Request.Path);
    }

    
void UpdateProfile(Object s, EventArgs e)
    {
        Profile.FavoriteColor 
= txtFavoriteColor.Text;
    }
    
    
void Page_PreRender()
    {
        lblUsername.Text 
= Profile.UserName;
        lblFavoriteColor.Text 
= Profile.FavoriteColor;
    }
        
</script>

<html>
<head>
    
<title>Anonymous</title>
</head>
<body>
    
<form id="form1" runat="server">

    
<asp:Button
        Text
="Login"
        OnClick
="Login"
        Runat
="Server" />
    
<asp:Button ID="Button1"
        Text
="Logout"
        OnClick
="Logout"
        Runat
="Server" />
    
<hr />
    
<asp:TextBox    
        id
="txtFavoriteColor"
        Runat
="Server" />
    
<asp:Button
        Text
="Update Profile"
        OnClick
="UpdateProfile"
        Runat
="Server" />
    
<hr />
    
<b>Username:</b>
    
<asp:Label  
        id
="lblUsername"
        Runat
="Server" />
    
<br />
    
<b>Favorite Color:</b>
    
<asp:Label
        id
="lblFavoriteColor"
        Runat
="Server" />    
        
    
</form>
</body>
</html>

當你打開第一個頁面時,UserName的值是一個隨機生成的唯一識別號(見圖3)。當你按下Login按鈕後,你就完成了身份認證,它是通過用戶票據(User Bill)完成的。


圖3 使用匿名和認證profile

列表10的頁面中包含一個用於更新FavoriteColor的表單,要注意的是,在你登錄登出的時候,會分別生成兩個不同的profile。例如當你先登錄,後登出的話,那麼系統會生成一個隨機的唯一識別號。

在很多情況下,你需要把匿名profile遷移到認證profile狀態,如果你需要遷移profile屬性值的話,你可以利用 ProfileModule類的MigrateAnonymous事件完成該任務,該事件只能在Global.asax文件中進行處理。列表11中的 Global.asax演示了你如何才能實現FavoriteColor屬性的遷移。


列表 11. Global.asax (C#)

<%@ Application Language="C#" %>
<script runat="server">

    
void Profile_MigrateAnonymous(Object s, 
      ProfileMigrateEventArgs e)
    {
        ProfileCommon anonProfile 
= 
          Profile.GetProfile(e.AnonymousId);
        Profile.FavoriteColor 
= anonProfile.FavoriteColor;
    }   
</script>

通過Profile類的GetProfile()方法你可以獲得匿名profile,該方法接收一個唯一識別號,並且返回與唯一識別號對應的profile。ProfileMigrateEventArgs對象包含一個匿名識別號。

配置Profile Provider
默認情況下,profile被保存在sqlserver 2005 express數據庫,它位於App_Data目錄中,這或許在你開發一些普通的asp.net應用程序時是沒有問題的,但很有可能,你需要把你的應用程序的profile保存在另一個數據庫中,比如一個完整版的SqlServer 2005的實例中,而該數據庫又位於你局域網的某個位置。

Profile使用Provider模式,通過修改web.config或machine.config的設置來告訴系統把信息存儲在哪裏。
ASP.NET本身配了一個profile provider,叫SqlProfileProvider。如果你感到困惑,你可以通過繼承ProfileProvider基類來創建一個自己的 provider。例如,你可以創建一個基於Oracle數據庫或MySql數據庫的Provider。在這裏,我們將只討論最簡單的方法,即通過SqlServer數據庫來保存profile信息。

要使用Microsoft SQL Server存儲profile信息,必須完成兩個步驟。首先,你必須安裝SQL Server數據庫,然後你必須重新設置配置文件。

ASP.NET 2.0框架提供了一個用於配置SQL Server來存儲Profile信息的工具,該工具叫做aspnet_regsql,它位於Windows/Microsoft.NET/ Framework/[.NET版本號]。執行該工具後,你會看到圖4中的ASP.NET SQL Server安裝嚮導。

圖4 使用ASP.NET SQL Server安裝程序

SQL Server安裝嚮導會指導你完成必要的步驟,完成這些步驟後,嚮導會自動創建用於存儲profile信息的存儲過程和表結構。

在你完成SQL Server數據庫的配置後,你需要修改web.config或machine.config中的數據庫連接設置來指向服務器上的SQL Server數據庫,本例中該數據庫的實例名爲MyServer,列表12列出了該配置文件。

列表 12. Web.Config

<configuration>
<connectionStrings>
<add
name="myConnectionString"
connectionString
=
"Server=MyServer;Trusted_Connection=true;database=MyDatabase"
 />
</connectionStrings>
<system.web>
<anonymousIdentification enabled="true" />
<profile defaultProvider="MyProfileProvider">
<providers>
<add
name="MyProfileProvider"
type
="System.Web.Profile.SqlProfileProvider"
connectionStringName
="myConnectionString" />
</providers>
<properties>
<add
name="FirstName"
allowAnonymous
="true" />
<add
name="LastName"
allowAnonymous
="true" />
</properties>
</profile>
</system.web>
</configuration>

在列表12中的profile配置中,包含了一個defaultProvider特性,這個特性指向一個叫MyProfileProvider的 profile provider,而這個provider定義是在profile標記的<providers>節中完成的。 MyProfileProvider則使用一個叫MyConnectionString的連接字符串完成數據庫連接,並保存profile信息到數據庫中。MyConnectionString可以在位於web.config開頭的<connectionStrings>節中找到。

管理profile並生成profile報告
Profile會對象自動保存用戶profile信息,這既是好事業是壞事。說它是好事,是因爲你不需要寫存儲信息的所有邏輯代碼,說它是壞事,是因爲這樣可能造成一大堆無用的信息被保存在數據庫中。

幸運的是,ASP.NET 2.0框架包含一個叫做ProfileManager的類,你可以使用它來管理profile信息。它包含了相當多的方法使你能夠有效地管理profile並且生成profile報表,下面列出了一些該類的重要方法:
  • DeleteInactiveProfiles. 刪除一個特定日期之前的所有profile
  • DeleteProfile. 刪除特定用戶的profile
  • DeleteProfiles. 刪除一個profile集合
  • FindInactiveProfilesByUserName. 返回一個ProfileInfo對象的集合,該集合表示的profile是匹配一個某個名字,並且是從某個特定日期開始一直未被使用
  • FindProfilesByUserName. 返回一個ProfileInfo對象集合,該集合與某個用戶名相關聯
  • GetAllInactiveProfiles. 返回一個ProfileInfo對象集合,該集合表示的profile是從某個特定日期開始一直未被使用的profile
  • GetAllProfiles. 返回一個ProfileInfo對象集合,該集合表示所有的profile
  • GetNumberOfInactiveProfiles. 返回從某個特定日期開始一直未被使用的profile的數量
  • GetNumberOfProfiles. 返回profile總數
這些方法中,雖然所有的方法都返回一個ProfileInfo對象集合,但沒有一個返回一個真正的profile。ProfileInfo對象包含以下profile屬性
  • IsAnonymous. 表示該profile是否爲匿名profile
  • LastActivityDate. 最後一次profile被訪問的時間和日期
  • LastUpdatedDate. 最後一次profile被升級的時間和日期
  • Size. 表示profile的大小,這是在profile provider存儲profile信息時記錄的
  • UserName. 與profile關聯的用戶名
ProfileManager有幾個方法提供了額外的參數用於支持分頁。例如,GetAllProfiles方法的一個重載版本就提供了專門用於設置頁面索引、頁面大小、總共的記錄數的參數,這些參數在需要分頁的頁面中十分有用。

ProfileManager既可以在asp.net頁面下使用,也可以在其它程序中使用。例如,你可能需要做一個控制檯程序用於每天清除長時間未使用的 profile。列表14的控制檯程序會刪除七天未使用的profile,你可以使用Windows計劃任務(Windows Scheduled Tasks)來安排該程序的執行時間。


列表 14. DeleteInactiveProfiles (C#)

using System;
using System.Web.Profile;

public class DeleteInactiveProfiles
{    
    
public static void Main()
    {
      
int deleted = 0;
      deleted 
= 
        ProfileManager.DeleteInactiveProfiles(
        ProfileAuthenticationOption.All, 
        DateTime.Now.AddDays(
-7));
      Console.WriteLine(
"Deleted " + 
        deleted.ToString() 
+ " profiles" );
    }      
}

你可以通過一下的命令行指令對列表14進行編譯

[Visual Basic .NET]
C:/WINDOWS/Microsoft.NET/Framework/v2.0.40607/vbc 
  /r:System.Web.dll DeleteInactiveProfiles.vb

[C#]
C:/WINDOWS/Microsoft.NET/Framework/v2.0.40607/csc 
  DeleteInactiveProfiles.cs

你還可以使用ProfileManager類生成profile信息報表。例如,如果你打算生成一個用戶調查的報表,你可以把用戶調查保存在profile中,這樣就可以輕易的使用ProfileManager生成你需要的報表。

列表15中的web.config中有三個屬性:SurveyCompleted、FavoriteLanguageFavoriteEnvironment

Listing 15. Web.Config

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
    
   
<system.web>

      
              
<anonymousIdentification enabled="true" />

      
<profile>
      
<properties>
                      
<add 
            
name="SurveyCompleted"
            type
="Boolean"
            allowAnonymous
="true" />
                      
<add 
            
name="FavoriteLanguage"
            allowAnonymous
="true" />
                     
<add 
            
name="FavoriteEnvironment"
            allowAnonymous
="true" />
      
</properties>
              
</profile>
 
</system.web>
</configuration>

列表16中的頁面演示了一個簡單的用戶調查。該頁面包含兩個Panel控件,第一個控件中有兩個調查問題,當用戶完成調查後,第一個控件會自動隱藏,而第二個會顯示出來,第二個Panel有一段表示感謝的文字。


列表 16. Survey.aspx (C#)

<%@ Page Language="C#" %>
<script runat="server">

    
void SaveSurvey(Object s, EventArgs e)
    {    
        Profile.FavoriteLanguage 
= rdlLanguage.SelectedItem.Text;
        Profile.FavoriteEnvironment 
= rdlEnvironment.SelectedItem.Text;
        Profile.SurveyCompleted 
= true;
    }
    
    
void Page_PreRender()
    {    
        
if (Profile.SurveyCompleted) 
        {
            pnlSurvey.Visible 
= false;
            pnlSurveyCompleted.Visible 
= true;
        }
        
else
        {
            pnlSurvey.Visible 
= true;
            pnlSurveyCompleted.Visible 
= false;
        }
    }
    
</script>

<html>
<head>
    
<title>Survey</title>
</head>
<body>
    
<form id="form1" runat="server">
    
    
<asp:Panel ID="pnlSurvey" Runat="Server">
    What is your favorite programming language?
    
<br />
    
<asp:RadioButtonList 
        
id="rdlLanguage"
        runat
="Server">
        
<asp:ListItem Text="VB.NET" Selected="True" />    
        
<asp:ListItem Text="C#" />
        
<asp:ListItem Text="J#" />    
    
</asp:RadioButtonList>
    
<p>&nbsp;</p>
    What is your favorite development environment?
    
<br />
    
<asp:RadioButtonList 
        
id="rdlEnvironment"
        runat
="Server">
        
<asp:ListItem Text="VS.NET" Selected="True" />    
        
<asp:ListItem Text="Web Matrix" />
        
<asp:ListItem Text="Notepad" />    
    
</asp:RadioButtonList>
    
<p>&nbsp;</p>    
    
<asp:Button ID="Button1"
        Text
="Submit Survey"
        Onclick
="SaveSurvey"
        Runat
="Server" />
    
</asp:Panel>
    
<asp:Panel ID="pnlSurveyCompleted" Runat="Server">
    Thank you for completing the survey!
    
</asp:Panel>
    
</form>
</body>
</html>

列表17中顯示調查的結果,該頁面中有一個顯示ProfileInfo對象集合的GridView控件,該ProfileInfo對象集合是由 ProfileManager的GetAllProfiles方法獲得的。當你點擊GridView中的任意一行的Select鏈接時,你將會看到對這個問題的調查結果,該調查結果是由Profile類的GetProfile方法獲得的。


圖5 顯示調查結果


列表 17. SurveyResults.aspx (C#)

<%@ Page Language="C#" %>
<script runat="server">

    
void Page_Load()
    {    
        ResultsGrid.DataSource 
= 
ProfileManager.GetAllProfiles(ProfileAuthenticationOption.All);
        ResultsGrid.DataBind();
    }
    
    
void DisplayProfileDetails(Object s, EventArgs e)
    {
        ProfileCommon SelectedProfile 
= 
            Profile.GetProfile(ResultsGrid.SelectedValue.ToString());
        lblLanguage.Text 
= SelectedProfile.FavoriteLanguage;
        lblEnvironment.Text 
= SelectedProfile.FavoriteEnvironment;
    }
    
</script>

<html>
<head>
    
<title>Survey Results</title>
</head>
<body>
    
<form id="form1" runat="server">
    
<h2>Survey Results</h2>
    
<asp:GridView 
        
id="ResultsGrid"
        DataKeyNames
="UserName"
        AutoGenerateSelectButton
="true"
        OnSelectedIndexChanged
="DisplayProfileDetails"
        SelectedRowStyle-BackColor
="LightYellow"
        Runat
="Server" />
    
<p>&nbsp;</p>
    
<h2>Survey Details</h2>
    
<b>Favorite Language:</b>
    
<asp:Label  
        
id="lblLanguage"
        Runat
="Server" />
    
<br />
    
<b>Favorite Environment:</b>
    
<asp:Label  
        
id="lblEnvironment"
        Runat
="Server" />
    
</form>
</body>
</html>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章