你有這個代碼的幾個嚴重的問題。
首先,您的代碼容易受到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;
}
}
注意的時候我得到了做重構你的添加到購物車邏輯,我其實沒有需要進行數據庫調用獲取有關產品的信息。所以現在它運行得更快,效率更高。