1. Profile介绍(存储用户配置)
ASP.NET 2.0 中的存储用户配置功能使您可以定义并存储要在整个应用程序中使用的基于用户的设置。而且,在用户未登录时,可以将这些设置存储在匿名配置文件中,然后在将来某个时间将其迁移到登录用户的配置文件中。
Profile 对象与Session对象十分相似,但是更好用一些。与Session相似的地方在于,Profile是相对于一个特定的用户的,也就是说,每个Web应用程序的用户都有他们自己的profile对象。与Session不同的是,Profile对象是持久对象。如果你向Session中添加一个项,在你离开网站时,该项就会消失。而Profile则完全不同,当你修改Profile的状态时,修改在多个访问之间均有效。
profile使用provider模式来存储信息,默认情况下,user profile的内容会保存在SQL Server Express数据库中,该数据库位于网站的App_Data目录。如果需要支持其他数据库,可以编写相关的ProfileProvider类。Profile对象是强类型的.
与Session不同,Profile是强类型的,Session对象仅仅是一个项集合而已,而profile对象则有强类型属性。
使用强类型是有它的道理的。例如,使用强类型,你就可以在Microsoft Visual Web Developer中使用智能感知技术,当你键入Profile和一个点的时候,智能感知会弹出你已经定义过的profile属性列表。
2. 配制ProFile
默认情况下,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一样使用aspnet_regsql来存储Profile信息的工具。具体的用法在这里就不说了,参照上一篇文章 ASP.NET的缓存.
双击aspnet_regsql,SQL Server安装向导会指导你完成必要的步骤,完成这些步骤后,向导会自动创建用于存储profile信息的存储过程和表结构。
3. 设置ProFile
既可以在machine.config中,也可以在web.config中定义一个user profile,由于你不能在应用程序的二级目录中创建一个包含文件profile节的web.config文件,这意味着你将无法在一个应用程序中定义两个以上的profile。如果需要支持匿名的话则还需要配置<system.web>元素下的<anonymousIdentification>元素。
<profile
enabled="true|false"
inherits="fully qualified type reference"
automaticSaveEnabled="true|false"
defaultProvider="provider name">
<properties>...</properties>
<providers>...</providers>
</profile>
属性 | 说明 |
enabled | 可选的 Boolean 属性。 指定是否启用 ASP.NET 用户配置文件。如果为 true,则启用 ASP.NET 用户配置文件。 默认值为 true。 |
defaultProvider | 可选的 String 属性。 指定默认配置文件提供程序的名称。 有关更多信息,请参见 Provider。 默认值为 AspNetSqlProfileProvider。 |
inherits | 可选的 String 属性。 包含从 ProfileBase 抽象类派生的自定义类型的类型引用。ASP.NET 动态地生成一个从该类型继承的 ProfileCommon 类,并将该类放在当前 HttpContext 的 Profile 属性中。 |
automaticSaveEnabled | 可选的 Boolean 属性。 指定用户配置文件是否在 ASP.NET 页执行结束时自动保存。如果为 true,则用户配置文件在 ASP.NET 页执行结束时自动保存。 只有在 ProfileModule 对象检测到某一用户配置文件已修改的情况下,该模块才保存该配置文件。也就是在 IsDirty 属性为 true 的情况下。有关更多信息,请参见 ASP.NET 配置文件属性。 默认值为 true。 |
子元素
元素 | 说明 |
properties | 必选的元素。定义用户配置文件属性和属性组的集合。 |
providers | 可选的元素。定义配置文件提供程序的集合。 |
<properties>
<add... />
<clear />
<remove... />
<group>...</group>
</properties>
元素 | 说明 |
add | 可选的元素。向用户配置文件添加属性。 |
clear | 可选的元素。从用户配置文件中清除以前定义的所有属性。 |
group | 可选的元素。定义用户配置文件属性的分组。 |
remove | 可选的元素。从用户配置文件中移除属性。 |
<add
name="property name"
type="fully qualified type reference"
provider="provider name"
serializeAs="String|Xml|Binary|ProviderSpecific"
allowAnonymous="true|false"
defaultValue="default property value"
readOnly="true|false"
customProviderData="data for a custom profile provider" />
/>
属性
属性 | 说明 |
name | 必选的 String 属性。 指定属性名。该值用作自动生成的配置文件类的属性的名称,并用作该属性在 Properties 集合中的索引值。该属性的名称不能包含句点 (.)。 有关自动生成用户配置文件属性的更多信息,请参见 ASP.NET 配置文件属性概述。 |
type | 可选的 String 属性。 指定属性类型。 默认值为 String。 |
provider | 可选的 String 属性。 指定用于存储和检索属性值的配置文件提供程序。provider 属性的值是 providers 元素中指定的某个配置文件提供程序的名称。如果未指定提供程序名称,则使用 profile 元素中指定的默认提供程序。有关配置文件提供程序的更多信息,请参见 ASP.NET 配置文件提供程序。 |
serializeAs | 可选的 SettingsSerializeAs 属性。 指定数据存储区中属性值的序列化格式。默认序列化格式视具体的提供程序而定。实际所使用的序列化由提供程序确定;对于 SQL 提供程序,则为 String 序列化。 |
allowAnonymous | 可选的 Boolean 属性。 指定在应用程序用户是匿名用户的情况下是否可以获取或设置属性。 如果设置为 true,则在应用程序用户是匿名用户的情况下可以获取或设置属性。 默认值为 false。 |
defaultValue | 可选的 String 属性。 如果数据存储区中没有 Profile 属性的值,则按如下所示指定默认值: · 如果使用 XML 序列化对属性 (Property) 类型进行了序列化处理,则此属性 (Attribute) 可以设置为表示属性 (Property) 类型的序列化实例的 XML 字符串。 · 如果使用二进制序列化对属性 (Property) 类型进行了序列化处理,则此属性 (Attribute) 可以设置为表示属性 (Property) 类型的序列化实例的 Base-64 编码字符串。 · 如果属性为引用类型,则可以使用 Stringnull 值指示 Profile 属性应为未初始化的配置文件返回 null。 |
readOnly | 可选的 Boolean 属性。 指定是否只能读取而不能设置属性。如果设置为 true,则可以读取但不可以设置属性。 默认值为 false。 |
customProviderData | 可选的 String 属性。 指定 customProviderData 属性 (Attribute) 可以设置为任意字符串值,以供属性 (Property) 的配置文件提供程序使用。如果设置了此属性 (Attribute),则该值放置在属性 (Property) 的 Attributes 集合中,通过名称 "CustomProviderData" 进行索引。 |
至于其他更具体的元素说明,请参照MSDN<profile 元素>
例如下面一个简单的例子
<system.web>
<anonymousIdentification enabled="true"/>
<profile>
<properties>
<add name ="Name" defaultValue ="游客" allowAnonymous="true"/>
<group name="Group">
<add name ="Collection" type="System.Collections.ArrayList"/>
<add name="Pirce" type="int" defaultValue="100"/>
</group>
</properties>
</profile>
</system.web>
有了anonymousIdentification这个元素,系统会自动为匿名用户生成唯一的ID。allowAnonymous该特性表明这个profile属性是否允许被匿名用户使用。
4.使用Profile
Profile是自动保存的,但是某些复杂类型可能无法自动保存,此时需要设置<profile>元素的automaticSaveEnabled设置为false,要保存的话则调用 Profile 上的 Save 方法即可。要动态取消Profile的自动保存功能的话则需要在 global.asax 中加一个Profile_ProfileAutoSaving事件.(如果找不到global.asax文件,点添加新项,选者全局应用程序类)
例如
void Profile_ProfileAutoSaving(Object sender, ProfileAutoSaveEventArgs e)
{
if ((e.Context.Items["CancelProfileAutoSave"] != null) && ((bool)e.Context.Items["CancelProfileAutoSave"] == true))
e.ContinueWithProfileAutoSave = false;
}
在需要取消Profile的自动保存功能的页的代码处如下写
protected void Page_Load(object sender, EventArgs e)
{
Context.Items["CancelProfileAutoSave"] = true;
}
通过ProfileManager执行相关任务,如搜索有关所有配置文件、经过身份验证用户的配置文件及匿名用户的配置文件的统计信息,确定在给定时间段内尚未修改的配置文件的数量,根据配置文件的上一次修改日期删除单个配置文件及多个配置文件等
将匿名配置文件迁移到经过身份验证的配置文件
在global.asax加一个Profile_MigrateAnonymous事件处理,示例如下,仅为说明
void Profile_MigrateAnonymous(Object sender, ProfileMigrateEventArgs pe)
{
// 获得匿名配置
ProfileCommon anonProfile = Profile.GetProfile(pe.AnonymousID);
// 从匿名配置中取值并赋值给经过身份验证的配置
if (anonProfile.Color != System.Drawing.Color.Empty)
{ Profile.Color = anonProfile.Color; }
// 从数据库中删除匿名配置
ProfileManager.DeleteProfile(pe.AnonymousID);
// 清除与某个会话关联的匿名 Cookie 或标识符
AnonymousIdentificationModule.ClearAnonymousIdentifier();
}
以上面的Web.Config为例子,程序里调用的方法如下
Profile.Name = User.Identity.Name;
Profile.Group.Collection.Clear();
Profile.Group.Collection.Add("哦累累");
Profile.Group.Collection.Add("哦拉拉");
Profile.Group.Pirce = 1;
一周之后调用该页面,并访问这些数据,依然会存在
Profile对象既可用于匿名用户也可以用于已认证用户。然而,当用户从匿名用户状态转换为已认证用户状态时,Profile对象能够以一种令人难以理解的方式完成任务。
当匿名用户使用Profile对象时,用户profile是与一个随机生成的号码相关联的,该号码是根据每个用户唯一生成的,它保存在浏览器的cookie中,无论何时该用户返回应用程序,该用户的Profile设置会被自动加载。
如果匿名用户通过认证的话,所有与该用户相关的profile就会丢失,同时系统会生成一个新的profile。这时该Profile信息将与用户名相关联,而非唯一识别号。
5.管理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。如下程序所示,你可以使用Windows计划任务(Windows Scheduled Tasks)来安排该程序的执行时间。
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");
}
}
你还可以使用ProfileManager类生成profile信息报表。例如,如果你打算生成一个用户调查的报表,你可以把用户调查保存在profile中,这样就可以轻易的使用ProfileManager生成你需要的报表。
下列的的web.config中有三个属性:SurveyCompleted、FavoriteLanguage 和 FavoriteEnvironment
<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>
下列页面演示了一个简单的用户调查,该页面包含两个Panel控件,第一个控件中有两个调查问题,当用户完成调查后,第一个控件会自动隐藏,而第二个会显示出来,第二个Panel有一段表示感谢的文字
<%@ 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>
下列页面中有一个显示ProfileInfo对象集合的GridView控件,该ProfileInfo对象集合是由 ProfileManager的GetAllProfiles方法获得的。当你点击GridView中的任意一行的Select链接时,你将会看到对这个问题的调查结果,该调查结果是由Profile类的GetProfile方法获得的。