asp.net中Profile实战篇

来源:互联网 发布:java 接受表单文件 编辑:程序博客网 时间:2024/05/08 19:41

1.什么是个性化服务

个性化服务是Asp.net自带的一种技术框架,为用户提供了自定义站点外观、内容、布局、角色管理等功能,如同QQ空间等。

2.个性化服务需要程序员学习哪些方面,才能实现这些功能

个性化服务是一个框架,这个框架包含3个核心功能:个性化用户配置、web部件、成员资格与角色管理。我们就是要着重学习这3个功能。

3.时刻记住

一般情况下只有登录的用户才能使用个性化服务,比如博主对博客板块的添加、删除或对样式进行修改,所以我们在开发的时候一般情况下会有登录、注册模块。但这不是绝对的匿名用户也可以使用个性化功能,比如google的个性化搜索主页,如果为匿名用户启动个性化功能,需要对web.config文件进行相关配置。

4.个性化服务包含的三大方面

  • 个性化用户配置
  • WEB部件
  • 成员资格与角色管理

这三大功能如果自己完全从零开始编写不仅技术难度大,而且后期的维护也是一件麻烦事。ASP.NET 2.0提供了一系列与个性化有关的控件供我们使用,使开发更加的敏捷迅速。

(1).个性化用户配置

在手工时代需要把个性化信息存储在Session或数据库中(比如主题皮肤、每页显示的条数),存储这些信息是实现个性化服务的基础,但需要编写大量的代码,效率低下。2.0提供的这些都是自动完成的。 
个性化用户配置功能的核心是Web.config文件中的Profile节的配置。注意既然是核心也是学习的重点。

(2).Web部件

得益于Web部件,用户才能根据喜好对页面所包含的模块进行调整

(3). 成员资格与角色管理

成员资格:能否进行登录,由成员资格进行决定。 
角色管理:登录后能进行什么操作,由角色来管理。

5.详细介绍个性化服务之一《个性化用户配置》

掌握:Profile配置节

掌握:有关API

掌握:SQL Server数据库配置

使用个性化用户配置功能的两个核心步骤是:

<1>在web.config文件中配置<profile>节以启动该功能。 
<2>使用相关API对用户配置信息进行存储、访问。

<profile>配置节声明 学习建议查看MSDN文档中的profile配置节

<profile enabled="true|false" inherits="fully qualified type reference" automaticSaveEnabled="true|false" defaultProvider="provider name"> <properties>...</properties> <providers>...</providers> </profile>

<profile>配置节位于<system.web>配置节之下,部分解释采用了MSDN中的解释:

  • enabled:可选属性用于设置profile个性化功能是否启动,该属性的默认值为true
  • inherits:可选属性在MSDN上是这样说的:“可选的String属性,包含从ProfileBase抽象类派生的自定义类型的类型引用。ASP.NET动态地生成一个从该类型继承的ProfileCommon类,并将该类放在当前HttpContext的Profile属性中。”该属性是可选的,属性值是一个字符串。该字符串是一个从ProfileBase类继承的子类名。大部分情况下该属性不用配置,也不用写在Profile属性中,会在运行时动态生一个类,这个类的类名是ProfileCommon,父类是ProfileBase。我们所要保存的个性化信息都会动态的注入到该类中,成为该类的实例成员。该类与<properties>属性节有关。在代码中通过当前页面的Profile属性访问该类的实例。
  • automaticSqveEnabled:可选属性指定用户配置文件是否在 ASP.NET 页执行结束时自动保存。如果为 true,则用户配置文件在 ASP.NET 页执行结束时自动保存。默认值为true。
  • defaultProvider:可选的String属性。指定默认配置文件提供程序的名称。默认值为AspNetSqlProfileProvider。
  • <properies>子节点(必选元素)用于定义需要保存到数据库中的个性化信息,在<properties>属性节中定义的每一个子节点都会成为ProfileCommon类的实例的成员变量。
  • <providers>子节点(可选元素)用于定义个性化提供程序,提供程序起到了持久层的作用, 用于和具体的数据库进行交互,将ProfileCommon类(起到了实体类的作用)的实例写到数据库或将数据库的信息读到实体类中。

说句题外话,machine.config文件中的配置为全局配置,会应用到服务器(IIS)下的每一个Web应用程序中,每一个Web应用程序在创建时首先都会从machine.config文件继承配置设置,过后也可以在具体的web应用程序的web.config文件中对machine.config的同名配置进行改写(需要加<clear/>清除对父文件的继承),这样会产生覆盖,与父类子类的继承、覆盖的道理类似。不到万不得已不要改写machine.config文件,毕竟会影响到服务器下的每一个网站。

以下是C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG\machine.config的部分配置:

<connectionStrings>  <add name="LocalSqlServer"       connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true"       providerName="System.Data.SqlClient"/></connectionStrings><system.web>  <profile>    <providers>      <add name="AspNetSqlProfileProvider"           connectionStringName="LocalSqlServer"           applicationame="/"            type="System.Web.Profile.SqlProfileProvider, System.Web,Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>    </providers>  </profile><system.web>

connectionStrings用于定义数据库连接字符串的集合

profile用于定义个性化配置

5.1 测试connectionStrings配置节的继承性

1. 创建新的网站或新的项目

2. 在Default.aspx.cs文件中编写代码

screenshot1

3. 运行后的结果

screenshot2

通过结果可以看到在该项目的web.config文件中虽然没有编写<connectionStrings>配置节但该配置节却有默认值,这些默认值来自于machine.config文件,继承于machine.config文件中的<connectionstrings>配置节。

4. 让我们继续测试,在web.config文件中加入如下配置节

screenshot1

第一个”LocalSqlServer”配置是从machine.config文件中粘贴过来的(为了同名),第二个是随便写的。

 

5. 运行后的结果

screenshot3

可以看到第一个<add>配置对父文件产生了覆盖,不会与父文件中同名的“LocalSqlServer”产生冲突。但如果把子文件“LocalSqlServer”除name属性的其他属性值改一改,就会发生重复定义错误,需要在web.config<add>节点前加<clear/>节点清除继承性,大家可以动手试一试。

5.2 测试profile配置节的继承性

1. 继续上面的网站,不要在web.config中加任何有关<profile>节点的设置。

2. 在Default.aspx.cs文件中编写获得profile节点属性的代码:

using System;using System.Configuration;using System.Web.Configuration;public partial class _Default : System.Web.UI.Page {    protected void Page_Load(object sender, EventArgs e) {        //测试ConnectionStrings配置节        ConnectionStringSettingsCollection col = ConfigurationManager.ConnectionStrings;        for (int i = 0; i < col.Count; i++) {            Response.Write("<font color=red> " +                            col[i].Name + "</font><font color=blue> " +                            col[i].ConnectionString + "</font><font color=black> " +                            col[i].ProviderName + "</font><br/>");        }        //测试Profile配置节        // Get the Web application configuration.        Configuration configuration = WebConfigurationManager.OpenWebConfiguration("/");        // Get the section.        ProfileSection profileSection =            (ProfileSection)configuration.GetSection("system.web/profile");        //ProfileSection profileSection = new ProfileSection();        Response.Write("默认提供程序defaultProvider属性=: " + profileSection.DefaultProvider + "<br/>");        Response.Write("profile是否启动enabled属性=:" + profileSection.Enabled + "<br/>");        Response.Write("inherits属性=: " + profileSection.Inherits + "<br/>");        Response.Write("automaticSaveEnabled属性=: " + profileSection.AutomaticSaveEnabled + "<br/>");        Response.Write("properties子配置节:<ul>");        foreach (ProfilePropertySettings temp in profileSection.PropertySettings) {            Response.Write("<li>属性名name=: " + temp.Name +                              " 属性类型type=: " + temp.Type +                              " 序列化格式serializeAs=:" + temp.SerializeAs.ToString() +                          "</li>");        }        Response.Write("</ul>");        Response.Write("providers子配置节:<ul>");        foreach (ProviderSettings temp in profileSection.Providers) {            Response.Write("<li>name=" + temp.Name + " type=" + temp.Type + " </li>");        }        Response.Write("</ul>");    }}

 

3. 运行结果

screenshot4

这些默认值继承于machine.config。

这些默认值整理如下:

<profile enabled="true"

             defaultProvider="AspNetSqlProfileProvider"

             inherits="ProfileCommon"

             automaticSaveEnabled="true">

     <providers>

          <clear/>

         <add name="AspNetSqlProfileProvider"

                  type="System.Web.Profile.SqlProfileProvider"

                  connectionStringName="LocalSqlServer"

                  applicationName="/"

                  commandTimeout="30"

                 description="" />

     </providers>

</profile>

inherits="ProfileCommon"中的ProfileCommon是一个在程序运行时动态生成的类继承于ProfileBase类,在这仅是一个属性默认值的示意,该类和<properties>子节点的配置有关。

示例01 匿名用户个性化

clip_image002    clip_image002[5]

以上是程序运行后的两张截图,当匿名用户首次登录时,显示左图。当用户输入完信息提交后,再次访问如右图,无论是刷新还是重新启动服务器,再次访问都是右图。匿名用户的标识借助于Cookie功能,存储于客户端的cookie中,匿名用户的数据存储于服务器的数据库中。每一个匿名用户在访问页面时会在用户的cookie中存放一个“令牌”,当用户输入完数据提交后这些数据和“令牌”存储于数据库中。当再次访问时拿出“令牌”就可以看到以前的数据,这些功能都是.net自动完成的。我们要做的仅仅是配置和简单的编码。

1. 配置数据库(示例01第一步)

这些数据存储于.net自带的数据库aspnetdb中。首先运行数据库创建程序:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ aspnet_regsql.exe

clip_image001

clip_image002[7]

clip_image002[9] 
数据库:<默认> 是让我们输入数据库的名字,默认数据库的名字是aspnetdb,最好采用默认。

clip_image002[11]

配置完成后可以看到我们数据库服务器上多了一个数据库:aspnetdb

clip_image002[13]

 

 

数据库现在创建好了,可以看看aspnet_profile表中有什么数据。对了,也可以在cmd中通过命令创建数据库,好处是可以要部分功能,也就是说库中的表不会有这么多。

2. 创建项目并编写default.aspx页面(示例01第二步)

项目结构图:

screenshot5

Default.aspx文件源代码:

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server">    <title>匿名用户个性化</title>    <link href="css/style.css" rel="stylesheet" type="text/css" /> </head><body>    <form id="form1" runat="server">    <div>    <fieldset class="area">        <legend class="mainTitle">匿名用户个性化</legend>        <br />        <table border="0" cellpadding="2" cellspacing="2" >            <tr><td class="head" colspan="2">&nbsp;</td></tr>            <tr>                <td>                    上次提交:</td>                <td>                    <asp:TextBox ID="TextBox1" runat="server" Enabled="False"></asp:TextBox></td>            </tr>            <tr>                <td>                    用户姓名:</td>                <td>                    <asp:TextBox ID="TextBox2" runat="server"></asp:TextBox></td>            </tr>            <tr>                <td>                    所在国家:</td>                <td>                    <asp:TextBox ID="TextBox3" runat="server"></asp:TextBox></td>            </tr>            <tr>                <td>                    邮政编码:</td>                <td>                    <asp:TextBox ID="TextBox4" runat="server"></asp:TextBox></td>            </tr>            <tr>                <td align="center" colspan="2">                    <asp:Button ID="Button1" runat="server" Text=" 提交 " onclick="Button1_Click" /></td>            </tr>            <tr><td class="head" colspan="2">&nbsp;</td></tr>        </table>    </fieldset>    </div>    </form></body></html>

 

css/style.css

body{    font-size: 9pt;    font-family: Arial,宋体;}fieldset table{    border: solid 1px #000;    width: 100%;}input{    border: solid 1px #000;}.area{    width: 300px;}.mainTitle{    font-size: 12pt;    font-weight: bold;}td.head{    font-size: 10pt;    font-weight: bold;    color: #fff;    background-color: #000;}

 

3.  配置web.config文件(示例01第三步)

要配置两个节点:

(1)<connectionstirng>用于定义项目所用到的数据库

(2)<profile>个性化设置

screenshot6

第30行配置数据库连接字符串。由于和父文件重名,要<clear/>清除重名配置。

第34行为匿名用户启动用户标识,默认情况下只为注册用户启动,不为匿名用户启动。 默认值为false。

第35行defaultProvider=”AspNetSqlProfileProvider”指profile的默认提供程序由name的值为”AspNetSqlProfileProvider”的子配置节指定,与38行对应。

第38行定义个性化提供程序,提供程序是类库中的”System.Web.Profile.SqlProfileProvider”类,该类操作数据库完成数据库信息存取,属于数据访问层,操作哪个数据库由connectionStringName属性值指定。多个web应用程序可以操作同一个数据库(aspnetdb),为了避免信息冲突使用applicationName属性值来指定,“/”指代当前web应用根目录。此<add>节点可以省略。

第43行是最为重要的,根据页面的表单在这定义个4个属性,这4个属性就是要保存到数据库中的数据。分别是”UserName”、”LastSubmitTime”、”City”、”ZipCode”,并且把”City”,”ZipCode”放到了组中,组的作用非常简单就是为了避免属性过多时的命名冲突。allowAnonymous=”true”是允许匿名访问与<anonymousIdentification enabled="true"/>配合使用,缺一不可,这样才会为匿名用户存储信息。Type用于指定该属性的数据类型,默认值为字符串。在程序中可以通过Profile对象操作这些属性,比如Profile.UserName或Profile.Address.City。 
关于Profile对象的解释请继续往下看。

4. 好了现在进行最后一步,编写代码(示例01第四步)

screenshot7

当用户首次访问页面时,调用display()方法,重点关注Profile对象,该对象是当前页面类的成员对象,所属的类是ProfileCommon,还记得吗ProfileCommon类是<profile>节点的inherits属性的默认值,该类是程序运行时.net动态生成的类,用于获取或设置<properties>配置的属性值。

比如Profile.UserName获取或设置的是<add name="UserName" allowAnonymous="true"/>的属性值。

Profile.LastSubmitTime获取或设置的是<add name="LastSubmitTime" allowAnonymous="true" type="System.DateTime"/>的属性值,Profile.LastSubmitTime的数据类型由配置的Type指定为”System.DateTime”类型,如果不写Type属性默认为”String”类型。

Profile.Address.City访问的是Address组中的City属性。

当用户点击按钮后,将页面收集到的数据赋值给Profile的各个属性,profile对象自身负责和数据库的交互。

当再次访问时,通过Profile对象可以把这些值取出来如代码的11~14行。如果我们在web.config文件中加入一个新属性,可以通过Profile对象智能感知出来(也就是Profile对象点出来,不过要先编译)。

最后看一看我们数据库中存的是什么,以此结束第一个示例。

screenshot8

每一个用户在aspnet_Profile表中只会占据一行,UserID用于存储用户的唯一标识,PropertyNames列用于存储<properties>配置节配置的属性名称,PropertyValuesString用于存储属性的值,PropertyValuesBinary用于存储采用二进制序列化后的用户配置属性的值。最后一个存储上次数据库更新日期。可以看到配置文件中的属性名存储在PropertyNames数据列中,而用户提交的值在PropertyValuesString列中。

ASP.NET 2.0 中的存储用户配置功能使您可以定义并存储要在整个应用程序中使用的基于用户的设置。而且,在用户未登录时,可以将这些设置存储在匿名配置文件中,然后在将来某个时间将其迁移到登录用户的配置文件中。


关键
1、配置<system.web>元素下的<profile>元素;如果需要支持匿名的话则还需要配置<system.web>元素下的<anonymousIdentification>元素。示例如下,仅为说明

    <profile enabled="true" defaultProvider="SqlProfileProvider" inherits="CustomProfile">
      <providers>
        <add name="SqlProfileProvider" type="System.Web.Profile.SqlProfileProvider, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
             connectionStringName
="SqlConnectionString"
             applicationName
="/" />
      </providers>
      <properties>
        <add name="Name" />
        <add name="Color" type="System.Drawing.Color" />
        <group name="Group">
          <add name="Collection" type="System.Collections.ArrayList" />
          <add name="Price" type="int" defaultValue="100" />
        </group>
      </properties>
    </profile>

    <anonymousIdentification
      
enabled="true"
      cookieName
=".VS2005_ANONYMOUS"
      cookieTimeout
="1440"
      cookiePath
="/"
      cookieRequireSSL
="false"
      cookieSlidingExpiration
="true"
      cookieProtection
="All"
      cookieless
="UseCookies" />

各属性详细说明参看MSDN,索引处查找“profile 元素”和“anonymousIdentification 元素”

注意:
<profile>元素的inherits属性指定自定义类,该类要继承自ProfileBase

Profile是自动保存的,但是某些复杂类型可能无法自动保存,此时需要设置<profile>元素的automaticSaveEnabled设置为false,要保存的话则调用 Profile 上的 Save 方法即可。要动态取消Profile的自动保存功能的话则需要在 global.asax 中加一个Profile_ProfileAutoSaving事件,示例如下,仅为说明
    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;    
}


2、通过ProfileManager执行相关任务,如搜索有关所有配置文件、经过身份验证用户的配置文件及匿名用户的配置文件的统计信息,确定在给定时间段内尚未修改的配置文件的数量,根据配置文件的上一次修改日期删除单个配置文件及多个配置文件等

3、将匿名配置文件迁移到经过身份验证的配置文件
在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();  
    }


示例
App_Code/CustomProfile.cs
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using System.Web.Profile;

/// <summary>
/// CustomProfile 的摘要说明
/// </summary>

public class CustomProfile : ProfileBase
{
    private string _customName;
    public string CustomName
    {
        get return (string)base["CustomName"]; }
        set base["CustomName"] = value; }
    }


    private bool _customSex;
    public bool CustomSex
    {
        get return (bool)base["CustomSex"]; }
        set base["CustomSex"] = value; }
    }

}


web.config
    <profile enabled="true" defaultProvider="SqlProfileProvider" inherits="CustomProfile">
      <providers>
        <add name="SqlProfileProvider" type="System.Web.Profile.SqlProfileProvider, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
             connectionStringName
="SqlConnectionString"
             applicationName
="/" />
      </providers>
      <properties>
        <add name="Name" />
        <add name="Color" type="System.Drawing.Color" />
        <group name="Group">
          <add name="Collection" type="System.Collections.ArrayList" />
          <add name="Price" type="int" defaultValue="100" />
        </group>
      </properties>
    </profile>

Profile/Test.aspx
<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="Test.aspx.cs"
    Inherits
="Profile_Test" Title="存储用户配置测试" 
%>

<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
    <asp:Label ID="lbl" runat="Server" />
</asp:Content>

Profile/Test.aspx.cs
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class Profile_Test : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        // 一看就懂
        Profile.Name = User.Identity.Name;
        Profile.Color = System.Drawing.Color.AliceBlue;
        Profile.Group.Collection.Clear();
        Profile.Group.Collection.Add("冰棍");
        Profile.Group.Collection.Add("瓜子");
        Profile.Group.Price = 999999;

        Profile.CustomName = User.Identity.Name;
        Profile.CustomSex = true;



        lbl.Text = "Name:" + Profile.Name + "<br />";
        lbl.Text += "Color:" + Profile.Color.ToString() + "<br />";
        foreach (string s in Profile.Group.Collection)
        {
            lbl.Text += "商品有:" + s + "<br />";
        }

        lbl.Text += "价格:" + Profile.Group.Price + "<br />";

        lbl.Text += "自定义类名字:" + Profile.CustomName + "<br />";
        lbl.Text += "自定义类姓名:" + Profile.CustomSex;
    }

}


用“abc”这个用户登录后的运行结果
Name:abc
Color:Color [AliceBlue]
商品有:冰棍
商品有:瓜子
价格:999999
自定义类名字:abc
自定义类姓名:True

原创粉丝点击