你有这个代码的几个严重的问题。
首先,您的代码容易受到SQL注入攻击。您正在连接字符串以形成您的SQL查询。如果某人操纵了按钮上的命令参数,以便其值为1; update products set price = 0;
?他们只是设法在你的系统上执行代码!我们解决这个问题的方式是使用参数化查询。
另一个问题是您要将产品定价信息存储在客户的Cookie中。这听起来不危险吗?任何只有一点专业知识的客户都可以修改他们的cookie,以便所有产品的成本为0美元。相反,只能将产品ID和数量存储在Cookie中,然后自行检索产品名称和价格。
你的代码中有一个神奇的字符串“Addtocart”。如果你想更新它,你必须在多个地方进行更改。相反,为它创建一个常量,然后在需要的地方引用该常量。那么你只有一个地方需要更新它。
DataTables不好用。它们消耗了大量内存,它们很难处理,并且比使用POCO(Plain Old C#Objects)或“model”类更慢。
您正在以自定义格式将数据存储在cookie中。当你想要将数据从cookie中取出时,这将是一个痛苦的屁股解析。相反,使用JSON或其他一些简单的格式。
您正在将产品价格存储为字符串。不要这样做!你不能用字符串做数学。当您使用金钱工作时,请使用decimal
类型。
缩进你的代码!它使阅读更容易。
这是你更新的代码解决这些问题:
首先,我们将创建一个代表我们的产品一类。注意价格是decimal
。
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
该课程将作为一个集中位置从我们的数据库中检索有关产品的数据。
public class ProductRepository
{
private readonly string _connectionString;
public ProductRepository(string connectionString)
{
_connectionString = connectionString;
}
public Product GetProductById(string productId)
{
using(var connection = new SqlConnection(_connectionString))
{
// I'm going to use Dapper here because it's super handy
// https://github.com/StackExchange/Dapper
var product = connection.QueryOne<Product>(
@"select
Id,
Name,
Price
from
products
where
Id = @ProductId",
new { ProductId = productId });
return product;
}
}
}
这两个类将代表用户想要购买的产品的特定产品和数量。这可以安全地与用户保存在一起,因为它不包含价格信息。
public class CartItem
{
public string ProductId { get; set; }
public int Quantity {get; set; }
}
public class Cart
{
public Dictionary<string, CartItem> Items { get; set; }
public Cart()
{
Items = new Dictionary<string, CartItem>();
}
}
这个常数应该放在一些中心位置。
public constant string ShoppingCartCookieName = "Cart";
现在我们的页面上实际的逻辑:
protected void btnAddtoCart_Click(object sender, EventArgs e)
{
var addToCartButton = (Button)sender;
// notice I don't call .ToString() below
// because Button.CommandArgument is already a string
var productId = addToCartButton.CommandArgument;
var cart = GetShoppingCartFromCookie();
if(cart.Items.ContainsKey(productId)
{
//their cart already contained this product, so let's bump the quantity
cart.Items[productId].Quantity += 1;
}
else
{
//their cart didn't contain this product, so we'll add it
var cartItem = new CartItem { ProductId = productId, Quantity = 1 };
cart.Items.Add(cartItem.ProductId, cartItem);
}
SaveShoppingCartToCookie(cart);
}
private void SaveShoppingCartToCookie(Cart cart)
{
var cartJson = JsonConvert.SerializeObject(cart); //using Newtonsoft.Json
Response.Cookies[ShoppingCartCookieName].Value = cartJson;
Response.Cookies[ShoppingCartCookieName].Expires = DateTime.Now.AddHours(1);
}
private Cart GetShoppingCartFromCookie()
{
if (Request.Cookies[ShoppingCartCookieName] == null)
{
return new Cart();
}
else
{
var existingCartJson = Response.Cookies[ShoppingCartCookieName].Value;
// you may wish for some logic here to make sure the JSON can be converted
// to a Cart since a user could have modified the cookie value.
var cart = JsonConvert.DeserializeObject<Cart>(existingCartJson);
return cart;
}
}
注意的时候我得到了做重构你的添加到购物车逻辑,我其实没有需要进行数据库调用获取有关产品的信息。所以现在它运行得更快,效率更高。