asp.net 2.0 build Shopping cart and payment System II

Source: Internet
Author: User
Tags bind continue count implement integer sql injection unique id server memory
Asp.net| Shopping Cart

In this article, we will explore the GridView through a simple online store demo program, and begin to analyze a method of generating the datasource of the GridView, and then continue to use that data to create a fully functional shopping interface. Note that the DataSource in this demo program is free to create.

First, Introduction


In the first article, we discussed what a GridView is and how to use it, including how the actual data is bound to it. In this article, we will analyze the source of these data more closely and how to use it with the GridView to implement a simple shopping interface.

Where does the data come from?

Fundamentally, this problem depends on what you are doing. It can come from a static XML file, a dynamic XML feed, a database, and perhaps it is freely created. However, you should ensure that you are satisfied: if there is data, you can ensure that it can "import" into a GridView. In this article, this part of the data is created freely each time the application is restarted.

The datasource used to populate the two GridView is a DataTable. It is built using DataColumns and DataRows. In this main class file there is a function called "Createproductdt", which shows how the DataTable was initially created. Here is the complete implementation of the function:


Private DataTable Createproductdt ()
{
DataTable dtproducts = new DataTable ();
DataColumn productcolumn = new DataColumn ();
Productcolumn.datatype = System.Type.GetType ("System.Int32");
Productcolumn.columnname = "id";
Productcolumn.unique = true;
DTPRODUCTS.COLUMNS.ADD (Productcolumn);
Productcolumn = new DataColumn ();
Productcolumn.datatype = System.Type.GetType ("System.String");
Productcolumn.columnname = "thumb";
DTPRODUCTS.COLUMNS.ADD (Productcolumn);
Productcolumn = new DataColumn ();
Productcolumn.datatype = System.Type.GetType ("System.String");
Productcolumn.columnname = "name";
DTPRODUCTS.COLUMNS.ADD (Productcolumn);
Productcolumn = new DataColumn ();
Productcolumn.datatype = System.Type.GetType ("System.Double");
Productcolumn.columnname = "Price";
DTPRODUCTS.COLUMNS.ADD (Productcolumn);
Productcolumn = new DataColumn ();
Productcolumn.datatype = System.Type.GetType ("System.Int32");
Productcolumn.columnname = "Quantity";
DTPRODUCTS.COLUMNS.ADD (Productcolumn);

Make "id" the primary key
datacolumn[] Pkcolumns = new Datacolumn[1];
Pkcolumns[0] = dtproducts.columns["id"];
Dtproducts.primarykey = Pkcolumns;
return dtproducts;
}

First, we create a DataTable object and then create a DataColumn. For most table columns, we just need to set the data type and column name, although we have to set it to unique for the first column ("id"). This is because we want to use it as our primary key, and at the end of the function we also need to configure it. The reason we want to keep IDs unique is because we use it to refer to a variety of products that we'll add to datasource later, so that we can select specific data, such as using only the price and product name of the product. This function returns an empty DataTable and is therefore used only in GetBasket () and populateproducts ().

Now, let's start by adding the actual row data to the DataSource in Populateproducts (), as detailed in the following code. Each line corresponds to a different product. Adding a new row to a DataTable requires you to create a new DataRow and then call the NewRow () function of the DataTable. This will leave a location for the new row within the DataTable, but it will not actually add the row.

private void Populateproducts ()
{
Create a basic structure
DataTable dtproducts = Createproductdt ();
Add a product to its top
To create an initial row
DataRow aproduct = Dtproducts.newrow ();
aproduct["id"] = 11;
aproduct["thumb"] = "images/widget0.jpg";
aproduct["Name" = "Red Widget";
aproduct["price"] = 19.99;
DTPRODUCTS.ROWS.ADD (aproduct);
Reuse the line to add a new product
Aproduct = Dtproducts.newrow ();
aproduct["id"] = 22;
aproduct["thumb"] = "images/widget1.jpg";
aproduct["Name" = "Green Widget";
aproduct["price"] = 50.99;
DTPRODUCTS.ROWS.ADD (aproduct);
Bind the DataTable to the product GridView
Gvproducts.datasource = dtproducts;
Gvproducts.databind ();

Store the product in session
session["dtproducts"] = dtproducts;
}

First, we need to add some data to the line (for example, id, thumbnail image path, name, and price). Once added, we can call the Add () function to actually add our new rows to the DataTable. In this demo, we added six products, although we added only two of them in the previous fragment. You can see how I implemented "spoofing" and reused only the same columns and the same rows. Once this is achieved, we bind the DataTable to our GridView. For details, see the following code:

Gvproducts.datasource = dtproducts;
Gvproducts.databind ();

Remember the RowDataBound event we discussed in the first article? OK, once we call DataBind (), the function is activated, that is, start creating our data on the page. You should be aware that there may be other events between the two events on the underlying implementation, but for the sake of ease of understanding, we only consider these two events.

Thereafter, we also store a copy of the DataTable in session state, so that each time we want to access the product data, we can retrieve it directly without having to re-create it. It is noteworthy that, although this situation is more suitable for a small portion of the data for a small-scale project; however, when it comes to large applications, you should not use session state like this in this case-it can easily "swallow" Your server memory, so even with a subset of the data it is possible to use a lot of memory, If thousands of users have access to it at the same time. In this demo, you will see that the data is extracted multiple times from the session, but in practice, you may implement numerous database calls to extract a specific subset of data (when it is needed).

One thing to note is that you can set up "datakeynames" that can be used to index the items in the GridView. The product list and shopping basket each implement a single datakeyname:

datakeynames= "id"

This way, when you later click the "Add to basket" button to identify the product we want to add, use it. In the shopping basket, use it when updating the quantity. You can have multiple key names, although in most cases you only need one.

Before populating the GridView, you can bind an empty DataTable to it. This will force it to display a blank line (you can use a string to pre-filled). In this demo, this is implemented with two GridView, although you can only see one of them corresponds to the shopping basket, because it doesn't matter if the product doesn't exist in your store. You can set this by using the "Emptydatatext" GridView property as follows:

Emptydatatext= "~basket is empty~"

It will then be generated like the following figure 1:

third, Shopping basket


Figure 2. The shopping basket implemented in the sample program.

The shopping basket (reference Figure 2) is used to store the product (the customer selects from the Product list by clicking the "ADD to basket" button next to each product). The realization of storing the basket in session state is a good technique because all of the data can be discarded at any time when the customer decides to leave your site or may empty their basket. Of course, for a number of reasons, for example, for market research purposes to identify who is analyzing what and how to determine the trend of shopping, you can also choose to store the customer's shopping basket content in a database. Another reason may be to show them "last time you were this looked at this ..." type. This requires you to have a way to differentiate between customers. Two commonly used techniques are to store a cookie in the user's own system-identify their future access by using a unique ID, or use their login ID to differentiate (if you have already implemented a customer login).

The updated shopping basket also uses the CREATEPRODUCTDT () function to create its initial empty DataTable. In this demo, we'll use the same table structure, but you can further "refine" your shopping basket by deleting some data columns. In most cases, you only need to store the ID and number of each product, because you can easily base its ID to find the actual product details.

Each time a product is added to the basket via the product list, its add to basket button activates a OnServerClick event:

protected void Shopbuy_onserverclick (object source, EventArgs e)
{
int index = ((GridViewRow) ((HtmlInputButton) source). Parent.namingcontainer). RowIndex;
Addtobasket (Convert.ToInt32 (Gvproducts.datakeys[index). Value));
}
protected void Addtobasket (int productID)
{
DataTable dtbasket = Getbasketdt ();
Loops through the shopping basket and checks to see if the item already exists
BOOL found = false;
for (int i = 0; i < DtBasket.Rows.Count; i++)
{
if (Convert.ToInt32 (dtbasket.rows[i]["id"]) = = ProductID)
{
Increase quantity and mark as discovered
dtbasket.rows[i]["Quantity"] = Convert.ToInt32 (dtbasket.rows[i]["Quantity"]) + 1;
Found = true;
When we've found one, jump out of the loop.
Break
}
}
If the item is not found, add it as a new row
if (!found)
{
DataTable dtproducts = GETPRODUCTSDT ();
DataRow drproduct = DtProducts.Rows.Find (ProductID);
Now that we've got the data we need from the data source, we're going to add a new line to the basket
DataRow NewRow = Dtbasket.newrow ();
newrow["id"] = drproduct["id"];
newrow["name"] = drproduct["name"];
newrow["price"] = drproduct["Price"];
newrow["Quantity"] = 1;
DTBASKET.ROWS.ADD (NewRow);
}
Store the newly updated shopping basket back in the session
session["Dtbasket"] = Dtbasket;
Update the shopping basket, or "rebind it"
Updateshopbasket ();
}

We use the Shopbuy_onserverclick () function to "capture" this (this function can identify which line the button belongs to), get the relevant product ID and use it to invoke Addtobasket (). Within this function, we can check the shopping basket with the given product ID. If it already exists in the shopping basket, then we need to increase the number of it, and if it doesn't exist, then we add it as a new line. Finally, we rebind the shopping basket to its updated datasource. Refer to Figure 3.


Figure 3. The shopping basket actually in use.

The shopping basket, like the product GridView, also uses templatecolumns, so we can create a quantity text box on each line. This provides an easy way for customers to update the number of each item they ask for. Once they have changed these values, they click on the "Update quantities" button below the basket. This activates a OnServerClick event that is captured for Shopupdatebasketquantities_onserverclick (). This is similar to the Addtobasket () function: We have to locate the product in the basket and then update its quantity. The difference is that when checking the data retrieved from the text box, we have to be careful because you never know who is going to be able to get in there and mess with your system. Here is a partial code fragment of the function that handles this check:

Reading data from the Quantity text box
HtmlInputText itquant = (htmlinputtext) row. FindControl ("itproductquantity");
Converts the value to an integer
Try
{
int quant = Convert.ToInt32 (Itquant.value);

/* If the value is successfully converted to an integer, then we
Need to check that it is not a negative number; otherwise, we may owe
Customer Money!*/
if (Quant > 0)
{
drproduct["Quantity"] = quant;
}
Else
{
Drproduct.delete ();
}
}
Catch
{
If we can't convert it to an integer, then we don't make any changes.
}

For example, if someone enters 100 in the quantity domain, you may still owe them money! Generally, though, you may not pay them, but it depends on how your payment system is built. For this reason, we wrap this integer analysis inside a try/catch statement block so that we can leave the original value unchanged without parsing. Thereafter, we check the quantity to make sure it is greater than 0. If it is less than or equal to zero, then we delete the line. Finally, after checking all the products in the shopping basket and modifying their respective numbers, we save the basket and update the display.

The last key component of the shopping basket is the Updateshopbasket () function:

private void Updateshopbasket ()
{
Gvbasket.datasource = Getbasketdt ();
Gvbasket.databind ();
ibemptybasket.visible = ibupdatebasketquantities.visible = ibbasketcheckout.visible = gvBasket.Rows.Count > 0;
}

This function can extract a copy of the basket from the session state, which in turn creates a session basket, which, if it does not already exist, is then bound to the GridView. The ultimate goal is to hide or display three basket buttons, because if the basket is empty, you do not need to display them.四、一个 The safety problem worth paying attention to

Users in your system should have strict controls anywhere they can enter data to make sure they don't enter anything they don't want to implement. One common problem is SQL injection. In this position, some people can enter the SQL code into a part of a site, and then you can use it in the original SQL statement you want. So, for example, for the Quantity field, you can use:

"UPDATE tbl_basket SET quantity =" + Quantity. Text + "WHERE user_id =" + user_id;

If the customer enters 6 in the "Quantity" text box and their login ID is 230, the code above will look like this:

UPDATE tbl_basket SET quantity = 6 WHERE user_id = 230;

And if the customer enters:

"1 WHERE 1 = 1; DROP tbl_users; --"

So, the original statement now looks like this:

UPDATE tbl_basket SET quantity = 1 WHERE 1 = 1; DROP tbl_users; --WHERE user_id =;

Since then, they can use "1 WHERE 1 = 1;" To complete the original statement, and then continue "Drop Tbl_ users;" Operation, this is very bad! Finally, they can comment out the other parts of the original statement. In fact, this is only a very simple example. For questions about SQL injection, you can search the web for a lot of information.

   v. Payment

There are a number of ways to receive payments using electronic means of business. Some of the following are listed below:

· The online store is not just an online catalog, but customers often have to be able to contact you for an order by telephone.

· Similar to the above situation, unless you personally find customers to complete the transaction. If this is about some architectural work (such as a yard or a kitchen) and you need to offer them a quote on the spot after the field trip, it may be important.

· Use a built-in, secure payment method. In this way, customers can enter their credit card details and can be handled automatically by the system.

· Use an external payment method such as PayPal, Worldpay, or Debitech.

The demo store in this article is based on a legacy-style method of using PayPal to receive payments. It should work in conjunction with other external payment systems, such as slightly modified Worldpay. The reason we say "old-fashioned style" is that PayPal now generally offers its own. NET toolkit-the system that implements their own sites that are connected to them.

The entire collection of basket data and transfer to PayPal is implemented within the Shopbasketcheckout_onserverclick () function:

protected void Shopbasketcheckout_onserverclick (Object Source,eventargs e)
{
string postdata = "";
PostData + = "CURRENCY_CODE=GBP";
PostData + = "&cmd=_cart";
PostData + = "&business=youremailaddress@yourdomain.net";
PostData + = "&upload=1";
PostData + = "&cancel_return=www.davidmillington.net";
DataTable dtbasket = Getbasketdt ();
Double total = 0.00;
for (int i = 0; i < DtBasket.Rows.Count; i++)
{
PostData + + "&item_name_" + (i + 1) + "=" +
dtbasket.rows[i]["Name"];
PostData + + "&quantity_" + (i + 1) + "=" +
dtbasket.rows[i]["Quantity"];
PostData + + "&amount_" + (i + 1) + "=" +
Convert.todouble (dtbasket.rows[i]["Price"]);
Total + = (convert.todouble (dtbasket.rows[i)
["Price"]) * Convert.ToInt32 (dtbasket.rows[i]["Quantity"));
if (i = = dtbasket.rows.count-1)
{
PostData + = "&shipping_" + (i + 1) + "=" + calcdeliverycost (total);
}
Else
{
PostData + = "&shipping_" + (i + 1) + "= 0.00";
}
PostData + = "&shipping2_" + (i + 1) + "= 0.00";
PostData + = "&handling_" + (i + 1) + "= 0.00";
}
PostData + + "&handling=" + calcdeliverycost (total);
byte[] data = Encoding.ASCII.GetBytes (postdata);
HttpWebRequest pprequest = (HttpWebRequest)
WebRequest.Create ("HTTPS://WWW.PAYPAL.COM/CGI-BIN/WEBSCR");;
Pprequest.method = "POST";
Pprequest.contenttype = "application/x-www-form-
Urlencoded ";
Pprequest.contentlength = data. Length;
Send
Stream PPStream = Pprequest.getrequeststream ();
Ppstream.write (data, 0, data.) Length);
Ppstream.close ();
Receive
HttpWebResponse ppresponse = (HttpWebResponse) pprequest.getresponse ();
StreamReader sr = new StreamReader (Ppresponse.getresponsestream ());
String strresult = Sr. ReadToEnd ();
Sr. Close ();
Output to screen
Response.Clear ();
Response.Write (Strresult);
Response.End ();
}

Because there seems to be no way to send a C # application implementation and redirect it to another site (as you typically do with a <form > action attribute), we have to adopt a slightly different approach. We built a long string that contains multiple name/value pairs, and then uses the HttpWebRequest and HttpWebResponse objects to send and receive data from the payment service.

The first part of the function specifies the PayPal account details, such as the currency used, the account name, and the page that PayPal should return the customer (if they decide to cancel the transaction).

The next step is to traverse the shopping basket and retrieve all the product information we want to pass to PayPal. This includes the product name, quantity, and price. Due to the characteristics of the demo program, we have a little bit of skill in shipping costs and add the entire shipping cost to the last item in the basket instead of adding to each product. This is because we find total shipping costs based solely on the total price of the basket, not on any product category.

Now, let's talk about the interesting part. I admit, this is the result of my query via Google engine. First we create a request object that we use when we contact PayPal via a stream. We use a response object to receive the response and simply output it to the screen via Response.Write (). This can send the entire basket information to the PayPal site and guide it to the correct account.

The problem now is that the first page the customer arrives in the corresponding address bar still has your store address. If they click on any link to the PayPal site, such as watching the contents of the basket or logging in, the address should be changed accordingly to reflect that it is really paypal. You may realize that some people may be misunderstood because of the fact that they can still see the address of your store in the address bar and may even think you are trying to defraud them of PayPal or bank account details. If you are planning to implement payments via an external system such as PayPal or Worldpay, then you should check their developer site to see what their recommended. NET scenario is.

   Vi. Conclusion

In this section, we first analyze a method that generates the datasource of the GridView, and then continue to use that data to create a fully functional shopping interface. Although the DataSource in the demo program is free to create, if you either have a large number of products or just have a constantly changing product line, you really need to consider using a database to store your product information. Of course, adding a database to the system equals opening its own virus library; Therefore, this is a measure that should not be taken lightly.

The place to pay special attention to is the payment system. The demo store uses an easy way to collect the required basket information and send it to an external payment system. You may want to use more controls to implement payment processing, such as extracting customer payment details and storing them in a database, or writing your own electronic point-of-sale functionality. No matter what method you choose, you should be aware of the legality of receiving and paying in your country.

In the next installment of this series, we'll discuss some ways to change the appearance of the GridView.


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.