ASP.NET用户个性化设置Profile——配置2 - 建站学
时间:2010-08-30 来源:缘分星空
前面一篇文章讲到了如何快速的配置起Profile和如何在应用程序中使用Profile存储用户自定义信息。 但是在前面,Profile中存储的是简单数据类型,比如int、String等。现在,我们讲解如何存储自定义数据类型,比如:购物车类。在这里就把Petshop中的这一块单独抠出来,稍许简化一点,做一个讲解。
首先打开上一章的网站(或者新建一个网站,按照前几篇文章讲解的内容配置好Membership、profile、连接字符串等),然后在统一解决方案下再添加一个类库项目,起名为Models。在里边添加一个类CartItemInfo。内容如下:
public class CartItemInfo
{
public string Name { get; set; }
public string Type { get; set; }
public decimal Price { get; set; }
public int Quantity { get; set; }
}
代表购物车中存储的一项商品。
第三步:再次添加一个类库项目,起名为BLL。然后添加Models层的引用。然后在其中添加一个类Cart代表购物车:
代码 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;
}
}
}
第四步:在网站项目中添加BLL层和Models层的引用。
ok到此所有准备工作告一段落,开始配置Profile。打开网站的web.config文件,修改Profile节点的Properties节点为下面内容:
<properties>
<add name="Cart" type="BLL.Cart" allowAnonymous="true"/>
</properties>
注意:type必须前面带上命名空间的名字。
配置完毕!
现在新建一个页面,页面很简单:
<form id="form1" 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="BLL.Cart" allowAnonymous="true" serializeAs="Binary"/>
</properties>
给Cart增加了一个属性serializeAs="Binary",然后给Models层的CartItemInfo类和BLL层的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就先说到这里,后面还有两个点:匿名用户向登录用户的数据迁移,和自定义数据存储
源代码
anna sui handbagst john vrbocanvas leather totesbuy delsey luggageabc tv onlinebeach inn exuma reviewsartist killing dogpersonalized christmas gifts 2008personalized gable boxessamsonite computeralexandra walletlast minute flight bookingmiu miu handbags ukstill life artworkspersonalized graduation cardsfree monogram stencilsfabric duffle bagsunique silver necklacesmens briefcasesummer arts crafts projectscool travel bagspeace print scarf black whiteitaly cruise tourspolka dot rolling luggagewater color techniquesmodern art abstractblack sequin bagssamsonite 4 wheel luggagebuy cheap designer handbagsbeach flashvintage designer shoesmirages 2000snow falling screensaver macwalt disney cruise dealsaffordable coach handbagsgrandparents wedding giftsluggage laptop wheelscoatsst vincent and the grenadines newshalf life artworkpersonalized custom embossersmirage omni s8 reviewleather lace up boots for womenleather portfolio bagsoft leather luggagepaper napkinsbaby name charm necklacecomfort inn beachred pvc skirtdooney giraffe handbag Replica lv Hangbags Replica Hangbags Hangbags replica handbags replica handbags replica handbags replica handbags usb cable usb cable usb cable usb cable