(搬运).net起步 (用配置文件属性维护网站用户信息 3)

来源:互联网 发布:淘宝代销协议书 编辑:程序博客网 时间:2024/05/28 15:27

在上一个实验我们实验了如何快速的配置起 Profile 和如何在应用程序中使用 Profile 存储用户自定义信息。 但是在前面, Profile 中存储的是简单数据类型,比如 int 、 String 等。现在,我们实验如何存储自定义数据类型,比如:购物车类。在这里就把 Petshop 中的这一块单独抠出来,稍许简化一点,做一个实验。

新建网站

按照前几次实验的内容配置好 Membership 、 profile 、连接字符串等,然后在里边添加一个类CartItemInfo 。内容如下:

[Serializable]public class CartItemInfo    {        public string Name { get; set; }        public string Type { get; set; }        public decimal Price { get; set; }        public int Quantity { get; set; }    }

代表购物车中存储的一项商品。

第三步:再添加一个类 Cart 代表购物车:

[Serializable]
public class Cart { private Dictionary<string, CartItemInfo> cartItems = new Dictionary<string,CartItemInfo>(); /// <summary> /// 总价 /// </summary> public decimal Total { get { decimal total = 0; foreach (CartItemInfo item in cartItems.Values) { total += item.Price * item.Quantity; } return total; } } /// <summary> /// 设置某一项产品的数量 /// </summary> /// <param name="Name"></param> /// <param name="qty"></param> public void SetQuantity(string Name, int qty) { cartItems[Name].Quantity = qty; } /// <summary> /// 购物车中 , 产品个数 /// </summary> public int Count { get { return cartItems.Count; } } public void Add(string name, string type, decimal price, int quantity) { CartItemInfo item; // 判断该产品是否在集合当中 , 如果有 , 则直接数量 +1 // 如果没有 , 则创建一个新的购物车项加入到集合当中 if (!cartItems.TryGetValue(name, out item)) { item = new CartItemInfo { Name = name, Type = type, Price = price, Quantity = quantity }; cartItems.Add(item.Name, item); } else { cartItems[name].Quantity++; } } public void Add(CartItemInfo item) { Add(item.Name, item.Type, item.Price, item.Quantity); } /// <summary> /// 从购物车中移除一项 /// </summary> /// <param name="name"></param> public void Remove(string name) { cartItems.Remove(name); } /// <summary> /// 清空购物车 /// </summary> public void Clear() { cartItems.Clear(); } /// <summary> /// 得到购物车列表 /// </summary> public ICollection<CartItemInfo> CartItems { get { return cartItems.Values; } } }
PS:1.Dictionary<TKey, TValue> 类表示键和值的集合。Dictionary类2.ICollection<T> 接口定义操作泛型集合的方法。T 集合中元素的类型。


ok 到此所有准备工作告一段落,开始配置 Profile 。打开网站的 web.config 文件,修改 Profile节点的 Properties 节点为下面内容:

      <properties>        <add name="Cart" type="Cart" allowAnonymous="true"/>      </properties>

注意: type 必须前面带上命名空间的名字,如果有的话。
配置完毕!
现在新建一个页面,页面很简单:

    <form id="form2" runat="server"><div>名称 :<asp:TextBox runat="server" ID="txtName"></asp:TextBox><br />类型 :<asp:TextBox runat="server" ID="txtType"></asp:TextBox><br />价格 :<asp:TextBox runat="server" ID="txtPrice"></asp:TextBox><br />数量 :<asp:TextBox runat="server" ID="txtQuantity"></asp:TextBox><br /><asp:Button runat="server" Text=" 添加到购物车 " ID="btnAddCart" OnClick="btnAddCart_Click"/></div>    </form>
后台代码为:
    public void btnAddCart_Click(object sender, EventArgs e)    {        CartItemInfo item = new CartItemInfo        {            Name = txtName.Text,            Type = txtType.Text,            Price = decimal.Parse(txtPrice.Text),            Quantity = int.Parse(txtQuantity.Text)        };        Profile.Cart.Add(item);    }
首先在 Profile.Cart.Add(item); 这里加一个断点,然后以调试方式运行页面。在四个文本框中分别输入内容,并单击添加到购物车,第一次命中断点时,可以从监视窗口中看到Profile.Cart.CartItems.Count=1 ,说明刚才创建的对象添加到了集合当中。可是当我们再次点击添加到购物车按钮时,情况发生了变化,在运行 Profile.Cart.Add(item); 这句代码之前Profile.Cart.CartItems.Count 属性 =0 !刚才添加的那个商品哪去了?为什么之前的简单数据类型数据可以保留,而现在变为购物车类之后却又不可以了呢?

要解决这个问题有两种做法:
第一种,修改 Properties 节点如下所示:

<properties>  <add name="Cart" type="Cart" allowAnonymous="true" serializeAs="Binary"/></properties>

给 Cart 增加了一个属性 serializeAs="Binary" ,然后给 CartItemInfo 类和 Cart 类,增加一个[Serializable] 特性:

[Serializable]public class Cart{....}
[Serializable]public class CartItemInfo{.....}

然后再次重复刚才的步骤,你会发现:数据可以正确保存了。

第二种方法:需要修改一下代码了:将 Cart 类的 Dictionary<string,CartItemInfo> 替换为List<CartItemInfo> ,并且将所有需要保存的成员设置为 Public 访问权限,即可。


为什么要做这两种修改之后,才可以正确保存用户的数据呢?这是因为, Profile 在保存用户自定义类型时,需要将产生的对象 “ 序列化 ” 后,保存到数据库当中。在需要读取数据时,将保存的数据 “ 反序列化 ” 后,还原成对象。前面的两种改变,其实就是序列化的两种方式:二进制序列化和 XML 序列化。当然,在存储简单数据类型时, Profile 会将这些内容序列化为字符串。

所谓序列化,就是将一个内存中的对象,转变成一个磁盘文件的过程。顾名思义,二进制序列化就是转变成一个二进制文件, XML 序列化转变成一个 XML 文件。举个例子,我们玩的游戏,《暗黑破坏神 2 》了,我们经常会去网上下载一些非常牛 X 的存档,然后放到游戏目录下,就可以去游戏中体验这些非常牛的角色和装备。那么这些存档,其实就是序列化之后的文件。游戏将这些磁盘上的文件反序列化后变成内存当中的对象,也就是人物了。 XML 序列化的好处在于你可以将对象中的数据传送给其他应用程序。

总结一下:当我们需要在 Profile 中存放自定义数据类型时,需要指明自定义对象的序列化方式(默认为 XML 序列化方式)。

XML 序列化需要将自定义类型的数据成员设为公有,私有成员和方法不会被保存。同时 XML 序列化方式支持实现了 ICollection 接口的集合(前面将 Dictionary 换成 List ,是因为 Dictionary 没有实现 ICollection 接口,它实现的是 IDictionary 接口)。下图是 XML 序列化后,数据库中保存的数据 :


二进制序列化同样非常简单,对于要序列化的对象没有任何要求,只要在需要序列化的类上面增加 [Serilizable] 特性即可。需要注意的是,类中的所有成员都必须有此特性。这种特性不能继承,也就是说父类加了,子类还得加。

在这个例子中,用户如果要使用 Profile ,可以有两种状态,一种是登陆后使用,另一种是不登陆匿名使用 Profile 。但是在一些电子商务应用中,往往用户在匿名状态中使用购物车,但是在结账的时候是要求登陆或是注册的。这就需要将用户匿名状态下添加进购物车的数据迁入用户登录后的购物车当中。要实现这种效果就必须编写代码才能实现 :

在实现本例的过程中,关键是实现了 ProfileModule 类中的 MigrateAnonymous 事件。该事件在匿名用户登录时,且 Profile 中存在数据时触发。与其他事件不同的是,该事件处理程序必须在Global.asax 文件中定义。

具体做法如下 :
在项目中添加一个 Global.asax 文件 , 复制以下代码到文件当中:

    void Profile_MigrateAnonymous(object sender, ProfileMigrateEventArgs pe)    {        //取得该用户在匿名状态下的数据        ProfileCommon pc = Profile.GetProfile(pe.AnonymousID);        //判断购物车中是否添加了数据        if (pc.Cart.Count != 0)        {            //如果有数据,则将匿名状态下添加的商品添加到登陆后的购物车当中            //注意;Profile.Cart 存放的是登陆后的数据            //pc.Cart 是该用户在匿名状态下添加的数据            Profile.Cart = pc.Cart;        }        //删除匿名用户在 aspnet_users 表中的记录        Membership.DeleteUser(pe.AnonymousID);        //删除匿名用户 Profile 数据        ProfileManager.DeleteProfile(pe.AnonymousID);        //删除匿名用户标识        AnonymousIdentificationModule.ClearAnonymousIdentifier();    }
注意:如果感兴趣的同学,可以再建立一个页面,将商品信息用 GridView 显示出来,制作一个购物车。目前是将匿名用户的购物信息直接迁移到登录用户,而不是将当前匿名购物信息以追加的方式迁移过去。

阅读全文
0 0
原创粉丝点击