<?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;
個(gè)性化數據將存入數據庫
介紹
Microsoft ASP.NET 2.0支持被稱(chēng)為Profile的新對象,它可以自動(dòng)在多個(gè)Web應用程序的訪(fǎng)問(wèn)之間存儲用戶(hù)信息。一個(gè)User Profile中可以存儲各種類(lèi)型的信息,這些信息既可以是簡(jiǎn)單的string和integer類(lèi)型,也可以是復雜的自定義類(lèi)型。例如,你可以存儲用戶(hù)的姓、購物籃、用戶(hù)屬性或網(wǎng)站使用情況統計。
本文中,你將學(xué)習如何在一個(gè)應用中定義user profile。我們也會(huì )向你演示如何配置使用不同provider的profile。最后,你將學(xué)習如何管理和生成user profile的報告。
User Profiles總攬
Profile 對象與Session對象十分相似,但是更好用一些。與Session相似的地方在于,Profile是相對于一個(gè)特定的用戶(hù)的,也就是說(shuō),每個(gè)Web應用程序的用戶(hù)都有他們自己的profile對象。與Session不同的是,Profile對象是持久對象。如果你向Session中添加一個(gè)項,在你離開(kāi)網(wǎng)站時(shí),該項就會(huì )消失。而Profile則完全不同,當你修改Profile的狀態(tài)時(shí),修改在多個(gè)訪(fǎng)問(wèn)之間均有效。
profile使用provider模式來(lái)存儲信息,默認情況下,user profile的內容會(huì )保存在SQL Server Express數據庫中,該數據庫位于網(wǎng)站的App_Data目錄。然而,在本文的后半部分,你將了解如何使用其他數據提供者(data provider)來(lái)存儲信息,如完整版的SQL Server中的一個(gè)數據庫或者一個(gè)Oracle數據庫。
與Session不同,Profile是強類(lèi)型的,Session對象僅僅是一個(gè)項集合而已,而profile對象則有強類(lèi)型屬性。
使用強類(lèi)型是有它的道理的。例如,使用強類(lèi)型,你就可以在Microsoft Visual Web Developer中使用智能感知技術(shù),當你鍵入Profile和一個(gè)點(diǎn)的時(shí)候,智能感知會(huì )彈出你已經(jīng)定義過(guò)的profile屬性列表。
定義user profile
你既可以在machine.config中,也可以在web.config中定義一個(gè)user profile,由于你不能在應用程序的二級目錄中創(chuàng )建一個(gè)包含文件profile節的web.config文件,這意味著(zhù)你將無(wú)法在一個(gè)應用程序中定義兩個(gè)以上的profile。
在列表1的web.config中,列舉了一個(gè)簡(jiǎn)單的profile定義的實(shí)例,該profile有三個(gè)屬性,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需要同時(shí)被匿名用戶(hù)和已認證用戶(hù)使用,因此我們在web.config文件中增加包含一個(gè)< anonymousIdentification>元素,有了這個(gè)元素,系統就會(huì )自動(dòng)為匿名用戶(hù)生成唯一的ID。仔細看的話(huà)我們會(huì )發(fā)現,每一個(gè) profile屬性都有一個(gè)allowAnonymous特性,該特性表明這個(gè)profile屬性是否允許被匿名用戶(hù)使用。
默認的profile屬性類(lèi)型是System.String類(lèi)型。列表1中,由于沒(méi)有為FirstName和LastName這兩個(gè)profile屬性增加type特性,那么系統默認它們是string類(lèi)型,而PageVisits屬性則指定了type特性為Int32,因此該profile屬性可用于表示一個(gè)整型值。
最后,注意FirstName和LastName屬性都有defaultValue特性。你可以為簡(jiǎn)單的數據類(lèi)型設置defaultValue特性,但你不能為復雜類(lèi)型設置defaultValue特性。
當你定義好一個(gè)profile之后,系統會(huì )自動(dòng)在下一次頁(yè)面被調用時(shí),生成一個(gè)與該profile相對應的類(lèi)。這個(gè)類(lèi)會(huì )被保存在"Temporary ASP.NET Files Directory"目錄(該目錄也用于存放用于動(dòng)態(tài)生成頁(yè)面的類(lèi))。你可以使用HttpContext的Profile屬性(Property)調用該類(lèi)。
當你定義好一個(gè)profile后,你可以使用如下方法為profile屬性賦值。
[Visual Basic .NET]
Profile.FirstName = "Bill"
[C#]
Profile.FirstName = "Bill";
任何在web.config中定義的profile屬性都會(huì )在Profile對象中呈現。
列表2演示了你該如何使用profile來(lái)持久化保存用戶(hù)信息。這個(gè)頁(yè)顯示了FirstName,LastName, PageVisits三個(gè)屬性的值,同時(shí)它包含了一個(gè)能夠用于修改這三個(gè)屬性的表單(form)。在Page_Load中更新PageVisits的值,這意味著(zhù)每一次刷新頁(yè)面,PageVisits的值都會(huì )改變。
圖1 使用簡(jiǎn)單的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>
如果你多次訪(fǎng)問(wèn)列表2中的頁(yè)面,你會(huì )注意到PageVisits在不斷增大。如果你關(guān)閉的瀏覽器,并在一周之后調用該頁(yè)面,PageVisits屬性仍然會(huì )保留原值。從這一點(diǎn)可以看出Profile為每個(gè)用戶(hù)自動(dòng)保存一個(gè)副本。
使用Profile組
盡管你僅可以為一個(gè)應用程序定義一個(gè)profile,但如果你需要讓幾個(gè)profile屬性一起工作,把它們放在組中,會(huì )讓你覺(jué)得它們更易管理。
例如,在列表3中,有一個(gè)帶有兩個(gè)組的profile,這兩個(gè)組分別是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>
當你用組來(lái)定義profile時(shí),你應該使用組名來(lái)設置或讀取profile屬性。例如,在列表3中,你可以使用以下一些句子來(lái)完成三個(gè)profile屬性的賦值。
[C#]
Profile.Address.City = "Modesto";
Profile.Address.Street = "111 King Arthur Ln";
Profile.Preferences.ReceiveNewsletter = false;
一個(gè)profile的定義只能包含一層組,換句話(huà)說(shuō),你不能把其他的組放在一個(gè)profile組的下面一層。
使用復雜的profile屬性
到目前為止,我們已經(jīng)介紹了聲明包含簡(jiǎn)單類(lèi)型(如string或整型)屬性的profile,其實(shí)你也可以在profile中聲明復雜屬性。
舉個(gè)例子,假設你現在需要在profile中存儲一個(gè)購物籃,如果這樣做的話(huà),你就可以在每次訪(fǎng)問(wèn)網(wǎng)站時(shí)獲得自己的購物籃。
列表4 聲明了一個(gè)包含profile,這個(gè)profile包含一個(gè)名為ShoppingCart的屬性,而該屬性的type特性是一個(gè)叫ShoppingCart的類(lèi)(我們接下來(lái)會(huì )創(chuàng )建該類(lèi)),該類(lèi)名是有效的。
我們還會(huì )注意到,該聲明中包含一個(gè)serializeAs特性,該特性可以幫助ShoppingCart使用二進(jìn)制序列化器(binary serializer)進(jìn)行持久化,而不是使用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 中有一個(gè)簡(jiǎn)單購物籃的實(shí)現代碼,該購物籃擁有添加和刪除項(item)的方法(method),同時(shí)它還擁有兩個(gè)屬性(property),一個(gè)是用于獲得該購物籃中的所有項的,一個(gè)是用于表示所有商品的總價(jià)的。
列表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目錄中,購物籃會(huì )自動(dòng)被編譯。
在列表5中有一點(diǎn)值得注意,那就是ShoppingCart和CartItem類(lèi)都加上了可序列化的特性,這一點(diǎn)對于他們能否被序列化十分重要,只有這樣才能保存在Profile對象中。
最后,列表6的頁(yè)面顯示了可以被添加到購物籃中的產(chǎn)品。購物籃是通過(guò)BindShoppingCart方法從Profile對象中載入,該方法把購物籃中的對象綁定到一個(gè)GridView對象上,這些對象可以通過(guò)ShoppingCart類(lèi)的CartItems屬性獲得。
圖2 在profile中存儲購物籃
AddCartItem方法用于在購物籃中添加一個(gè)產(chǎn)品,該方法中包含了檢測Profile是否存在ShoppingCart的代碼。對于Profile中存儲的對象,你必須自己實(shí)例化這些對象,他們不會(huì )自動(dòng)實(shí)例化。
RemoveCartItem方法用于從購物籃中移除一個(gè)產(chǎn)品,該方法只是簡(jiǎn)單地通過(guò)調用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>
繼承一個(gè)profile
你也可以通過(guò)從一個(gè)已經(jīng)存在的profile類(lèi)中繼承一個(gè)profile來(lái)完成對profile的定義,這種特性能夠幫助你在多個(gè)應用程序中使用相同的profile。
例如,列表7中列出了一個(gè)擁有多個(gè)用戶(hù)屬性的類(lèi),該類(lèi)是從ProfileBase類(lèi)繼承而來(lái)的(你可以在System.Web.Profile中找到)
在列表8中的Web.config包含一個(gè)從UserInfo類(lèi)繼承而來(lái)的profile,通過(guò)該聲明,新的profile可以獲得UserInfo類(lèi)的所有屬性。
列表 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對象既可用于匿名用戶(hù)也可以用于已認證用戶(hù)。然而,當用戶(hù)從匿名用戶(hù)狀態(tài)轉換為已認證用戶(hù)狀態(tài)時(shí),Profile對象能夠以一種令人難以理解的方式完成任務(wù)。
當匿名用戶(hù)使用Profile對象時(shí),用戶(hù)profile是與一個(gè)隨機生成的號碼相關(guān)聯(lián)的,該號碼是根據每個(gè)用戶(hù)唯一生成的,它保存在瀏覽器的cookie中,無(wú)論何時(shí)該用戶(hù)返回應用程序,該用戶(hù)的Profile設置會(huì )被自動(dòng)加載。
如果匿名用戶(hù)通過(guò)認證的話(huà),所有與該用戶(hù)相關(guān)的profile就會(huì )丟失,同時(shí)系統會(huì )生成一個(gè)新的profile。這時(shí)該Profile信息將與用戶(hù)名相關(guān)聯(lián),而非唯一識別號。
要想理解所有這些工作,最好的方法就是看看下面的例子。列表9中的web.config定義了一個(gè)profile,該profile只有一個(gè)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中有一個(gè)包含兩個(gè)按鈕的頁(yè)面,分別是login和logout按鈕,其中還有一個(gè)用于更新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>
當你打開(kāi)第一個(gè)頁(yè)面時(shí),UserName的值是一個(gè)隨機生成的唯一識別號(見(jiàn)圖3)。當你按下Login按鈕后,你就完成了身份認證,它是通過(guò)用戶(hù)票據(User Bill)完成的。
圖3 使用匿名和認證profile
列表10的頁(yè)面中包含一個(gè)用于更新FavoriteColor的表單,要注意的是,在你登錄登出的時(shí)候,會(huì )分別生成兩個(gè)不同的profile。例如當你先登錄,后登出的話(huà),那么系統會(huì )生成一個(gè)隨機的唯一識別號。
在很多情況下,你需要把匿名profile遷移到認證profile狀態(tài),如果你需要遷移profile屬性值的話(huà),你可以利用 ProfileModule類(lèi)的MigrateAnonymous事件完成該任務(wù),該事件只能在Global.asax文件中進(jìn)行處理。列表11中的 Global.asax演示了你如何才能實(shí)現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>
通過(guò)Profile類(lèi)的GetProfile()方法你可以獲得匿名profile,該方法接收一個(gè)唯一識別號,并且返回與唯一識別號對應的profile。ProfileMigrateEventArgs對象包含一個(gè)匿名識別號。
配置Profile Provider
默認情況下,profile被保存在sqlserver 2005 express數據庫,它位于A(yíng)pp_Data目錄中,這或許在你開(kāi)發(fā)一些普通的asp.net應用程序時(shí)是沒(méi)有問(wèn)題的,但很有可能,你需要把你的應用程序的profile保存在另一個(gè)數據庫中,比如一個(gè)完整版的SqlServer 2005的實(shí)例中,而該數據庫又位于你局域網(wǎng)的某個(gè)位置。
Profile使用Provider模式,通過(guò)修改web.config或machine.config的設置來(lái)告訴系統把信息存儲在哪里。
ASP.NET本身配了一個(gè)profile provider,叫SqlProfileProvider。如果你感到困惑,你可以通過(guò)繼承ProfileProvider基類(lèi)來(lái)創(chuàng )建一個(gè)自己的 provider。例如,你可以創(chuàng )建一個(gè)基于Oracle數據庫或MySql數據庫的Provider。在這里,我們將只討論最簡(jiǎn)單的方法,即通過(guò)SqlServer數據庫來(lái)保存profile信息。
要使用Microsoft SQL Server存儲profile信息,必須完成兩個(gè)步驟。首先,你必須安裝SQL Server數據庫,然后你必須重新設置配置文件。
ASP.NET 2.0框架提供了一個(gè)用于配置SQL Server來(lái)存儲Profile信息的工具,該工具叫做aspnet_regsql,它位于Windows\Microsoft.NET\ Framework\[.NET版本號]。執行該工具后,你會(huì )看到圖4中的ASP.NET SQL Server安裝向導。
圖4 使用ASP.NET SQL Server安裝程序
SQL Server安裝向導會(huì )指導你完成必要的步驟,完成這些步驟后,向導會(huì )自動(dòng)創(chuàng )建用于存儲profile信息的存儲過(guò)程和表結構。
在你完成SQL Server數據庫的配置后,你需要修改web.config或machine.config中的數據庫連接設置來(lái)指向服務(wù)器上的SQL Server數據庫,本例中該數據庫的實(shí)例名為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配置中,包含了一個(gè)defaultProvider特性,這個(gè)特性指向一個(gè)叫MyProfileProvider的 profile provider,而這個(gè)provider定義是在profile標記的<providers>節中完成的。 MyProfileProvider則使用一個(gè)叫MyConnectionString的連接字符串完成數據庫連接,并保存profile信息到數據庫中。MyConnectionString可以在位于web.config開(kāi)頭的<connectionStrings>節中找到。
管理profile并生成profile報告
Profile會(huì )對象自動(dòng)保存用戶(hù)profile信息,這既是好事業(yè)是壞事。說(shuō)它是好事,是因為你不需要寫(xiě)存儲信息的所有邏輯代碼,說(shuō)它是壞事,是因為這樣可能造成一大堆無(wú)用的信息被保存在數據庫中。
幸運的是,ASP.NET 2.0框架包含一個(gè)叫做ProfileManager的類(lèi),你可以使用它來(lái)管理profile信息。它包含了相當多的方法使你能夠有效地管理profile并且生成profile報表,下面列出了一些該類(lèi)的重要方法:
· DeleteInactiveProfiles. 刪除一個(gè)特定日期之前的所有profile
· DeleteProfile. 刪除特定用戶(hù)的profile
· DeleteProfiles. 刪除一個(gè)profile集合
· FindInactiveProfilesByUserName. 返回一個(gè)ProfileInfo對象的集合,該集合表示的profile是匹配一個(gè)某個(gè)名字,并且是從某個(gè)特定日期開(kāi)始一直未被使用
· FindProfilesByUserName. 返回一個(gè)ProfileInfo對象集合,該集合與某個(gè)用戶(hù)名相關(guān)聯(lián)
· GetAllInactiveProfiles. 返回一個(gè)ProfileInfo對象集合,該集合表示的profile是從某個(gè)特定日期開(kāi)始一直未被使用的profile
· GetAllProfiles. 返回一個(gè)ProfileInfo對象集合,該集合表示所有的profile
· GetNumberOfInactiveProfiles. 返回從某個(gè)特定日期開(kāi)始一直未被使用的profile的數量
· GetNumberOfProfiles. 返回profile總數
這些方法中,雖然所有的方法都返回一個(gè)ProfileInfo對象集合,但沒(méi)有一個(gè)返回一個(gè)真正的profile。ProfileInfo對象包含以下profile屬性
· IsAnonymous. 表示該profile是否為匿名profile
· LastActivityDate. 最后一次profile被訪(fǎng)問(wèn)的時(shí)間和日期
· LastUpdatedDate. 最后一次profile被升級的時(shí)間和日期
· Size. 表示profile的大小,這是在profile provider存儲profile信息時(shí)記錄的
· UserName. 與profile關(guān)聯(lián)的用戶(hù)名
ProfileManager有幾個(gè)方法提供了額外的參數用于支持分頁(yè)。例如,GetAllProfiles方法的一個(gè)重載版本就提供了專(zhuān)門(mén)用于設置頁(yè)面索引、頁(yè)面大小、總共的記錄數的參數,這些參數在需要分頁(yè)的頁(yè)面中十分有用。
ProfileManager既可以在asp.net頁(yè)面下使用,也可以在其它程序中使用。例如,你可能需要做一個(gè)控制臺程序用于每天清除長(cháng)時(shí)間未使用的 profile。列表14的控制臺程序會(huì )刪除七天未使用的profile,你可以使用Windows計劃任務(wù)(Windows Scheduled Tasks)來(lái)安排該程序的執行時(shí)間。
列表 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" );
}
}
你可以通過(guò)一下的命令行指令對列表14進(jìn)行編譯
[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類(lèi)生成profile信息報表。例如,如果你打算生成一個(gè)用戶(hù)調查的報表,你可以把用戶(hù)調查保存在profile中,這樣就可以輕易的使用ProfileManager生成你需要的報表。
列表15中的web.config中有三個(gè)屬性:SurveyCompleted、FavoriteLanguage 和 FavoriteEnvironment
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中的頁(yè)面演示了一個(gè)簡(jiǎn)單的用戶(hù)調查。該頁(yè)面包含兩個(gè)Panel控件,第一個(gè)控件中有兩個(gè)調查問(wèn)題,當用戶(hù)完成調查后,第一個(gè)控件會(huì )自動(dòng)隱藏,而第二個(gè)會(huì )顯示出來(lái),第二個(gè)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> </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> </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中顯示調查的結果,該頁(yè)面中有一個(gè)顯示ProfileInfo對象集合的GridView控件,該ProfileInfo對象集合是由 ProfileManager的GetAllProfiles方法獲得的。當你點(diǎn)擊GridView中的任意一行的Select鏈接時(shí),你將會(huì )看到對這個(gè)問(wèn)題的調查結果,該調查結果是由Profile類(lèi)的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> </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>
聯(lián)系客服