在上一个实验我们实验了如何快速的配置起 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 显示出来,制作一个购物车。目前是将匿名用户的购物信息直接迁移到登录用户,而不是将当前匿名购物信息以追加的方式迁移过去。

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

  1. 在 git 中如何配置用户信息

    大家好,我是前端西瓜哥. 最近买了台新的笔记本,重新装了一些软件,这次就说说怎么在 git 中配置用户信息吧. 当我们安装了 git 后,一件非常重要的事情就是配置我们的用户名和邮箱地址,因为我们提交 ...

  2. 网站服务器安全维护,网站服务器安全维护

    网站服务器安全维护 内容精选 换一换 云服务器使用,服务器使用,服务器配置,云主机使用,弹性云服务器入门,ecs使用 来自:产品 域名注册(Domain Registration)是用户付费获取Int ...

  3. Linux 服务器安装、配置和维护,一文看全~

    每个 IP 地址都可以有一个主机名,主机名由一个或多个字符串组成,字符串之间用小数点隔开.有了主机名,就不要死记硬背每台 IP 设备的 IP 地址,只要记住相对直观有意义的主机名就行了.这就是 DNS ...

  4. 玩转华为数据中心交换机系列 | 配置M-LAG维护模式下升级示例

    素材来源:华为数据中心交换机配置指南 一边学习一边整理试验笔记,并与大家分享,侵权即删,谢谢支持! 附上汇总贴:玩转华为数据中心交换机系列 | 汇总_COCOgsta的博客-CSDN博客 组网需求 如 ...

  5. springboot配置文件属性大全

    springboot配置文件属性大全 1. application.yml参数 1. application.yml参数 #-------------------------------------- ...

  6. Spring Boot 如何正确读取配置文件属性

    前言 项目中经常会经常读取配置文件中的属性的值,Spring Boot提供了很多注解读取配置文件属性,那么如何正确使用呢? @Value @Value用来读取application.yml配置文件中属 ...

  7. VS Code 配置调试参数、launch.json 配置文件属性、task.json 变量替换、自动保存并格式化、空格和制表符、函数调用关系、文件搜索和全局搜索、

    1. 生成配置参数 对于大多数的调试都需要在当前项目目录下创建一个 lanch.json 文件,位置是在当前项目目录下生成一个 .vscode 的隐藏文件夹,在里面放置一些配置内容,比如:settin ...

  8. 网站安全配置(Nginx)防止网站被攻击(包括使用了CDN加速之后的配置)

    2019独角兽企业重金招聘Python工程师标准>>> 网站被攻击是一个永恒不变的话题,网站攻击的方式也是一个永恒不变的老套路.找几百个电脑(肉鸡),控制这些电脑同时访问你的网站,超 ...

  9. phpstudy一个域名配置两个网站(一个是thinkphp5,一个是原生php)

    phpstudy一个域名配置两个网站(一个是thinkphp5,一个是原生php) 一.总结 一句话总结:把原生php的网站直接放到thinkphp5的public目录下可以解决以stem.aaaa. ...

最新文章

  1. GBK和UTF-8之间的战争,websphere6.1乱码解决方案
  2. python使用集合实现筛选法求素数-python素数筛选法浅析
  3. 孤儿进程与僵尸进程[总结]
  4. macos 此服务器的证书无效_跨平台本地SSL证书生成工具,本地也能优雅的调试https...
  5. python字符串逆序输出代码_一行代码实现字符串逆序输出
  6. odis工程师使用方法_傅里叶红外光谱仪常见故障维修及排除方法,你了解有多少种呢?...
  7. ROSE User Case View
  8. keepalive+nginx实现负载均衡高可用_高可用、负载均衡 集群部署方案:Keepalived + Nginx + Tomcat...
  9. 第四范式完成超10亿元C轮融资,估值12亿美元
  10. class加载原理和Dex加载的原理-----android插件化技术
  11. ef6 mysql code first_使用EntityFramework6连接MySql数据库(code first方式)
  12. 实验7 OpenGL光照
  13. CryptoKitties加密猫合约详解
  14. 1.Oracle 安装教程及使用
  15. winpe iso镜像下载(exe转iso获取)
  16. Windows Server 2019/2022域控制器网络位置变为“专用网络”或“公共网络”
  17. UE4天气效果加白天黑夜的平滑过度切换
  18. android环信聊天界面上面显示昵称,【环信征文】在android中5分钟实现环信昵称头像的显示...
  19. 雪花飘落-面向对象编程
  20. 三维点云课程(七)——特征点描述

热门文章

  1. 【Python 数据科学】连接数据库
  2. 超好用的PDF转换软件
  3. 使用Intellij IDEA创建XML文件, DTD文件和XML Schema文件
  4. UNITY3D对接QQGame(PC)开发教程(2022)
  5. easyui textbox添加失去焦点事件
  6. CorelDRAW X3 刻刀工具
  7. Linux小白向 每日学习之网络管理
  8. UFO照片满天飞,为什么我们却找不到外星人?
  9. linux的yum命令无法使用在哪里下载_下载:微软正式发布Win10 2004版并即日起开始推送...
  10. 苹果手机老是提示存储空间不足