现在的位置: 首页 > 综合 > 正文

维护应用程序状态(三):使用用户配置文件

2012年07月18日 ⁄ 综合 ⁄ 共 12770字 ⁄ 字号 评论关闭

1.3  使用用户配置文件

ASP.NET 2.0 Framework提供了一种可选的不同于cookie和Session状态的方式存储用户信息:Profile对象。Profile对象提供强类型、可持久化的Session状态表单。

可以在应用程序的根Web配置文件定义一组Profile属性来创建Profile。ASP.NET Framework在后台动态编译一个包含这些属性的类。

例如,代码清单1-19所示的Web配置文件定义了一个Profile包含了三个属性:firstName、lastName和numverOfVisits。

代码清单1-19  Web.config

代码

<?xml version="1.0"?>

<configuration>

  <system.web>

    <profile>

      <properties>

        <add name="firstName" />

        <add name="lastName" />

        <add name="numberOfVisits" type="Int32" defaultValue="0" />

      </properties>

    </profile>

  </system.web>

</configuration>

 

 

当定义Profile属性时,可以使用下面的属性:

q name——用于指定属性名称;

q type——用户指定属性类型。类型可以是任意类型,包括定义在App_Code文件夹中的自定义组件(默认值是字符串类型);

q defaultValue——用于指定属性默认值;

q readOnly——用于创建只读属性(默认值为false);

q serializeAs——用于指定一个属性如何持久化为静态持久化数据。可能的值有Binary、ProviderSpecific、String和Xml(默认值为ProviderSpecific);

q allowAnonymous——用于允许匿名用户读写属性(默认值为false);

q provider——用于关联属性到特定的Profile提供程序;

q customProviderData——用于传递自定义数据到Profile提供程序。

在Web配置文件中定义Profile后,可以使用Profile对象修改Profile属性。例如,代码清单1-20所示的页面使用一个表单修改firstName和lastName属性的值。并且,页面在每次被请求时自动更新numberOfVisits属性(见图1-7)。

代码清单1-20  ShowProfile.aspx

代码

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

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

    void Page_PreRender()

    {

        lblFirstname.Text = Profile.firstName;

        lblLastName.Text = Profile.lastName;

        Profile.numberOfVisits++;

        lblNumberOfVisits.Text = Profile.numberOfVisits.ToString();

    }

    protected void btnUpdate_Click(object sender, EventArgs e)

    {

        Profile.firstName = txtNewFirstName.Text;

        Profile.lastName = txtNewLastName.Text;

    }

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >

<head id="Head1" runat="server">

    <title>Show Profile</title>

</head>

<body>

    <form id="form1" runat="server">

    <div>

    

    First Name:

    <asp:Label

        id="lblFirstname"

        Runat="server" />

    <br /><br />

    Last Name:

    <asp:Label

        id="lblLastName"

        Runat="server" />

    <br /><br />

    Number of Visits:

    <asp:Label

        id="lblNumberOfVisits"

        Runat="server" />

        

    <hr />

    

    <asp:Label

        id="lblNewFirstName"

        Text="New First Name:"

        AssociatedControlID="txtNewFirstName"

        Runat="server" />

    <asp:TextBox

        id="txtNewFirstName"

        Runat="server" />

    <br /><br />

    <asp:Label

        id="lblNewLastName"

        Text="New Last Name:"

        AssociatedControlID="txtNewLastName"

        Runat="server" />

    <asp:TextBox

        id="txtNewLastName"

        Runat="server" />

    <br /><br />    

    <asp:Button

        id="btnUpdate"

        Text="Update Profile"

        OnClick="btnUpdate_Click" 

        Runat="server" />

    

    </div>

    </form>

</body>

</html>

 

1-7  显示Profile信息

注意,Profile属性被公开为强类型属性。例如,numberOfVisits属性被公开为一个整型属性,因为我们将其定义为一个整型属性。

理解Profile属性是持久化的非常重要。如果为一个用户设置Profile属性,那么就算该用户过500年也不会再返回网站,属性也会保留其值。不像Session状态,当为Profile属性赋值时,用户离开网站,值也不会消失。

Profile对象使用提供程序模型。默认的Profile提供程序是SqlProfileProvider。默认情况下,该提供程序保存Profile数据到名为ASPNETDB.mdf的Microsoft SQL Server 2005 Express数据库,保存在应用程序的App_Code文件夹。如果数据库不存在,第一次使用Profile对象时它会被自动创建。

默认情况下,不能为匿名用户保存Profile信息。ASP.NET Framework使用用户的身份认证标识关联Profile信息。对任何标准的ASP.NET Framework支持的身份验证方式,都可以使用Profile对象,包括表单身份认证和Windows身份认证(默认情况下,Windows身份验证被启用)。

注解   本节的后续部分,你将了解到如何为匿名用户保存Profile信息。

 

1.3.1  创建用户配置文件组

如果需要定义许多Profile属性,则需要将属性组织成组,使得属性更易管理。例如,代码清单1-21所示的Web配置文件定义了两个名叫Preference和ContactInfo的组。

代码清单1-21  Web.config

代码

<?xml version="1.0"?>

<configuration>

  <system.web>

    <profile>

      <properties>

        <group name="Preferences">

          <add name="BackColor" defaultValue="lightblue"/>

          <add name="Font" defaultValue="Arial"/>

        </group>

        <group name="ContactInfo">

          <add name="Email" defaultValue="Your Email"/>

          <add name="Phone" defaultValue="Your Phone"/>

        </group>

      </properties>

    </profile>

  </system.web>

</configuration>

 

代码清单1-22所示的页面演示如何读写不同组的属性。

代码清单1-22  ShowProfileGroups.aspx

代码

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

<%@ Import Namespace="System.Drawing" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

    void Page_Load()

    {

        // Display Contact Info

        lblEmail.Text = Profile.ContactInfo.Email;

        lblPhone.Text = Profile.ContactInfo.Phone;

        

        // Apply Preferences

        Style pageStyle = new Style();

        pageStyle.BackColor = ColorTranslator.FromHtml(Profile.Preferences.BackColor);

        pageStyle.Font.Name = Profile.Preferences.Font;

        Header.StyleSheet.CreateStyleRule(pageStyle, null, "html");

    }

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >

<head id="Head1" runat="server">

    <title>Untitled Page</title>

</head>

<body>

    <form id="form1" runat="server">

    <div>

    

    Email:

    <asp:Label

        id="lblEmail"

        Runat="server" />

    <br /><br />

    Phone:

    <asp:Label

        id="lblPhone"

        Runat="server" />

    

    </div>

    </form>

</body>

</html>

 

 

1.3.2  支持匿名用户

默认情况下,匿名用户不能修改Profile属性。问题在于ASP.NET Framework没有办法关联Profile数据和特定的用户,除非用户是经过身份鉴别的。

如果希望允许匿名用户修改Profile属性,必须启用ASP.NET Framework的名叫匿名认证(Anonymous Identification)的功能。当匿名认证功能开启时,一个标识(一个GUID)被分配给匿名用户,并保存在持久化的浏览器cookie中。

注解   可以启用不依赖cookie的匿名标识符。不依赖cookie的匿名标识符与不依赖cookie的会话类似:匿名标识符被添加到页面的URL而不是cookie。可以在配置文件中设置anonymousIdenti- fication元素的cookieless属性值为UseURI或AutoDetect,来启用不依赖cookie的匿名标识符。

并且,必须用allowAnonymous标识所有希望匿名用户可以修改的Profile属性。例如,代码清单1-23所示的Web配置文件启用了匿名身份认证,并定义了一个可以被匿名用户修改的Profile属性。

代码清单1-23  Web.config

代码

<?xml version="1.0"?>

<configuration>

  <system.web>

    <authentication mode="Forms" />

    <anonymousIdentification enabled="true" />

    <profile>

      <properties>

        <add

          name="numberOfVisits"

          type="Int32"

          defaultValue="0"

          allowAnonymous="true" />

      </properties>

    </profile>

  </system.web>

</configuration>

 

代码清单1-23中定义的numberOfVisits属性包含了allowAnonymous属性。注意,Web配置文件同样启用了表单鉴别。当启用表单鉴别,并且没有登录时,用户就是匿名用户。

代码清单1-24所示的页面演示了当匿名身份认证启用时,如何修改Profile属性。

代码清单1-24  ShowAnonymousIdentification.aspx

代码

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

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

    void Page_PreRender()

    {

        lblUserName.Text = Profile.UserName;

        lblIsAnonymous.Text = Profile.IsAnonymous.ToString();

        Profile.numberOfVisits++;

        lblNumberOfVisits.Text = Profile.numberOfVisits.ToString();

    }

    protected void btnLogin_Click(object sender, EventArgs e)

    {

        FormsAuthentication.SetAuthCookie("Bob", false);

        Response.Redirect(Request.Path);

    }

    protected void btnLogout_Click(object sender, EventArgs e)

    {

        FormsAuthentication.SignOut();

        Response.Redirect(Request.Path);

    }

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >

<head id="Head1" runat="server">

    <title>Show Anonymous Identification</title>

</head>

<body>

    <form id="form1" runat="server">

    <div>

    

    User Name:

    <asp:Label

        id="lblUserName"

        Runat="server" />

    <br />

    Is Anonymous:

    <asp:Label

        id="lblIsAnonymous"

        Runat="server" />

    <br />

    Number Of Visits:

    <asp:Label

        id="lblNumberOfVisits"

        Runat="server" />

    <hr />

    <asp:Button

        id="btnReload"

        Text="Reload"

        Runat="server" />

    <asp:Button

        id="btnLogin"

        Text="Login"

        OnClick="btnLogin_Click" 

        Runat="server" />

        

    <asp:Button

        id="btnLogout"

        Text="Logout"

        OnClick="btnLogout_Click" 

        Runat="server" />

            

    </div>

    </form>

</body>

</html>

 

 


 

每次请求代码清单1-24所示的页面时,numberOfVisits这个Profile属性加1并显示。页面包含了3个按钮:Reload,Login和Logout(见图1-8)。

页面同样显示了Profile.UserName属性的值。该属性或者代表当前的用户名,或者代表匿名用户标识符。numberOfVisits这个Profile属性的值在Profile.UserName属性的值之后显示。

点击Reload按钮会很快地重新加载页面,并增加numberOfVisits属性的值。

点击Login按钮,则Profile.UserName变为Bob。numberOfVisits属性被重置。

点击Logout按钮,则Profile.UserName属性切换回显示匿名用户标识符。numberOfVisits属性变回它前一个值。

1-8  创建匿名用户配置文件

1.3.3  合并匿名用户配置文件

在前一部分,我们已经看到,当用户从匿名切换到鉴别状态时,所有的用户配置信息会丢失。例如,如果在Profile对象中存储了购物车,登录后则所有的购物车项目会丢失。

可以在用户从匿名切换到鉴别状态时,处理Global.asax文件中的MigrateAnonymous事件,预存Profile属性的值。该事件在拥有用户配置的用户登录时触发。

例如,代码清单1-25中,MigrateAnonymous事件自动复制所有的匿名Profile属性到用户当前通过验证的Profile。

代码清单1-25  Global.asax

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

<script runat="server">

    void Application_Start(object sender, EventArgs e) 

    {

        Application["SessionCount"] = 0;

    }

    void Session_Start(object sender, EventArgs e) 

    {

        Application.Lock();

        int count = (int)Application["SessionCount"];

        Application["SessionCount"] = count + 1;

        Application.UnLock();

    }

    void Session_End(object sender, EventArgs e) 

    {

        Application.Lock();

        int count = (int)Application["SessionCount"];

        Application["SessionCount"] = count - 1;

        Application.UnLock();

    }

    //public void Profile_OnMigrateAnonymous(object sender, ProfileMigrateEventArgs args)

    //{

    //    // Get anonymous profile

    //    ProfileCommon anonProfile = Profile.GetProfile(args.AnonymousID);

    //    // Copy anonymous properties to authenticated

    //    foreach (SettingsProperty prop in ProfileBase.Properties)

    //        Profile[prop.Name] = anonProfile[prop.Name];

    //    // Kill the anonymous profile

    //    ProfileManager.DeleteProfile(args.AnonymousID);

    //    AnonymousIdentificationModule.ClearAnonymousIdentifier();

    //}

    //public void Profile_ProfileAutoSaving(object s, ProfileAutoSaveEventArgs e)

    //{

    //    if (Profile.ShoppingCart.HasChanged)

    //        e.ContinueWithProfileAutoSave = true;

    //    else

    //        e.ContinueWithProfileAutoSave = false;

    //}

       

</script>

 

当用户的匿名标识传递给Profile.GetProfile()方法时,关联用户的匿名Profile会返回。接着,所有匿名Profile的属性被复制到当前Profile。最后,匿名Profile被删除,匿名标识被销毁(如果不销毁匿名标识,则MigrateAnonymous事件在登录认证后的每次页面请求都会被执行)。

1.3.4  从自定义类继承Profile

除了在Web配置文件中定义Profile属性列表,也可以在一个类中定义Profile属性。例如,代码清单1-26所示的类包含了名为FirstName和LastName的两个属性。

代码清单1-26  App_Code\SiteProfile.cs

 

using System;

using System.Web.Profile;

public class SiteProfile : ProfileBase

{

    private string _firstName = "Your First Name";

    private string _lastName = "Your Last Name";

    [SettingsAllowAnonymous(true)]

    public string FirstName

    {

        get { return _firstName; }

        set { _firstName = value; }

    }

    [SettingsAllowAnonymous(true)]

    public string LastName

    {

        get { return _lastName; }

        set { _lastName = value; }

    }

}

 

注意,代码清单1-26所示的类从BaseProfile类继承。

声明类之后,就可以在Web配置文件中通过从该类继承Profile对象来定义Profile。代码清单1-27所示的Web配置文件使用inherits属性从SiteProfile类继承Profile。

代码清单1-27  Web.config

<?xml version="1.0"?>

<configuration>

  <system.web>

    <anonymousIdentification enabled="true" />

    <profile inherits="SiteProfile" />

  </system.web>

</configuration>

 

从Web配置文件中继承Profile之后,就可以以正常的方式使用这个Profile了。可以通过访问Profile的属性读写在SieProfile类中定义的任何属性。

注解   随书附带资源中包含一个名叫ShowSiteProfile.aspx的页面,用于显示代码清单1-27中定义的Profile属性。

注解   如果从一个类继承Profile属性,同时在Web配置文件中定义Profile属性,则两组Profile属性将会被合并。

当在一个类中定义Profile属性时,可以使用下面的attribute修饰那些属性:

q SettingAllowAnonymous——用于允许匿名用户读写属性;

q ProfileProvider——用于关联属性到一个特定的Profile提供程序;

q CustomProviderData——用于传递自定义数据到Profile提供程序。

例如,所有声明于代码清单1-28中的SiteProfile类的属性都包含了SettingAllowAnonymous attribute,允许匿名用户读写这些属性。

 

1.3.5  创建复杂Profile属性

到目前为止,我们已经用Profile属性表达过字符串和整数这些简单类型了。我们也可以使用Profile属性表达诸如自定义购物车这样的复杂类。

例如,代码清单1-28所示的类表示一个简单的购物车。

代码清单1-28  App_Code\ShoppingCart.cs

using System;

using System.Collections.Generic;

using System.Web.Profile;

namespace AspNetUnleashed

{

    public class ShoppingCart

    {

        private List<CartItem> _items = new List<CartItem>();

        public List<CartItem> Items

        {

            get { return _items; }

        }

    }

    public class CartItem

    {

        private string _name;

        private decimal _price;

        private string _description;

        public string Name

        {

            get { return _name; }

            set { _name = value; }

        }

        public decimal Price

        {

            get { return _price; }

            set { _price = value; }

        }

        public string Description

        {

            get { return _description; }

            set { _description = value; }

        }

        public CartItem() { }

        public CartItem(string name, decimal price, string description)

        {

            _name = name;

            _price = price;

            _description = description;

        }

    }

}

 

代码清单1-28中的文件实际上包含了两个类:ShoppingCart类和CartItem类。ShoppingCart类公开了一个CartItem对象的集合。

代码清单1-29所示的Web配置文件定义了一个名为ShoppingCart的Profile属性来表示ShoppingCart类。type属性设为ShoppingCart类的完全标识名称。

代码清单1-29  Web.config

<?xml version="1.0"?>

<configuration>

  <system.web>

    <profile>

      <properties>

        <add name="ShoppingCart" type="AspNetUnleashed.ShoppingCart" />

      </properties>

    </profile>

  </system.web>

</configuration>

最后,代码清单1-30所示的页面使用了Profile.ShoppingCart属性。ShoppingCart的

抱歉!评论已关闭.