CIS Logo SVC Logo

   Computing & Information Systems
   Department

 

Schoology Facebook        Search CIS Site      Tutorials

Ecommerce App: Car Store 3



The Goals for this Example


This example expands on and completes the previous car store app. Thus you should work on a copy of that web site. The main goal is to add the checkout process.

  • This version adds new features, such as the shipping page and payment page, as well as the confirm and deny pages (which is shown as decided by a web service that checks whether the given credit card is adequate for the desired purchase).

Adjusting Forms and Code



New or Revised Forms

  • First, make sure that you have made a copy of your Store2 website folder and named the copy Store3. Have this on your W drive so that it can be accessed by the live web server.
  • The new files and revised ones can be obtained from Store3.zip.
  • Files such as Cart.aspx, Cart.aspx.vb, Results.aspx, Results.aspx.vb that you already had in Store2 should replace your old ones, but be careful to copy in any code you put into your Store2 files to fill in the blanks that were left for you or to add improvements. Read the new and old code carefully to see what goes where. The new forms can simply replace the old ones unless you customized them in some way.
  • If, in Store2, you figured out some useful VB code, you probably want to check if you can fill it in at the same places in the new files.
  • Note that the new aspx.vb files once again have a few blanks for you to fill in with the correct code. These lines are usually commented off to try to keep syntax error messages to a minimum. Once you get the code filled in, uncomment these lines.
  • You may need to comment entire sections of code that is not yet finished, in order to test what you have completed. Otherwise, the code that is only partially written might not compile or might interfere with the execution of what you do have finished.

Results.aspx.vb

  • This should be largely the same, though the fix for the IF test on Session("BasketNum") has been incorporated. It looks like this:
  • If Session("BasketNum") Is Nothing
  • Checking for the empty string does not work in this case, for if there is nothing for BasketNum in Session state, we get Nothing, not an empty string.
  • However, as we will see in Confirm.aspx.vb, if you really want to get an empty string when there is nothing in Session state, you can use this:
  • CType(Session("BasketNum"), String) as this will convert Nothing to the empty string.

The Cart Page

  • Replace the old Cart.aspx form with the new one, as there may have been small changes in it.
  • Cart.aspx.vb has a few changes in it.
  • This includes the Session("BasketNum") Is Nothing fix that was also used above.
  • The EmptyButton_Click routine has added the following line:
  • Session.Remove("BasketNum") 'Will prevent the user from seeing the shipping page.
  • The way this code achieves what the comment says is to remove the basket number from Session state. Then if the user clicks on the Buy button and tries to go to the next page, Shipping.aspx, that page checks to see if Session state has a basket number. If not, it redirects the browser to the Cart.aspx page, to show the user that the shopping cart is empty. You can't check out if you have nothing in your cart!
  • In addition, you might want to make the Buy button invisible in such a case.
  • The GridView1_RowDeleting page adds an IF test to see if the row being deleted from the shopping cart is the last item in the cart. It does this by looking at the number of CarBasketItem objects that have the current BasketNum. If that number is 1, then we are deleting the last item from the basket (or cart, if you prefer that metaphor). If it is 1, the BasketNum is removed from Session state to prevent the user from seeing the Shipping page, even if the user does click on the Buy button. It's the same idea that we just used above.

New Pages and Code



The Shipping Page

  • The Shipping.aspx form has the user fill in name, address, email address, and phone (with all but the phone being required fields).
  • Required field validators are used to force the user to fill out what is necessary.
  • Regular expression validators are used to make sure the data in most of these fields is of a reasonable form. This helps to reduce hacking attempts.
  • Note that there is no regular expression validator for the phone number. This is something that you can look up and add as an improvement.
  • There is also a custom validator to make sure that the user selects a state from the drop-down list. In the code-behind file, the CustomValidator1_ServerValidate routine checks to see if the selected item is "Select a state", which means that the user has not yet selected a state.
  • The Page_Load routine does nothing but check if there is no BasketNum defined in Session state. If that is the case, the user should not be on the Shipping page and is immediately redirected to the Cart page, where the user can see that there is no shopping cart. This matches what the code in the Results page expects the Shipping page to do, as discussed above.
  • The SubmitButton_Click routine simply stores into Session state the various pieces of contact information that the user has filled in on this page and then redirects to the Payment page.

The Payment Page: Non-Postback Case

  • The Payment form presents a summary of the order (showing the subtotal, shipping amount, tax amount, and total cost -- but not the details of the car(s) being ordered). It also asks for the needed credit card information.
  • Warning: The credit card number should be encrypted before being stored in the database. In order to make this application shorter we are skipping that. However, in real life it is important to protect credit card numbers from being easily harvested by a hacker. The industry has required standards (PCI standards) on this. It is, in fact, best not to store credit card numbers at all, even if they are encrypted.
  • The code-behind file only has a Page_Load routine, but it is a fairly long one.
  • It begins by retrieving a lot of stored information from Session state.
  • If we are not in the postback case (because the user has not clicked the Purchase button), a check is made to see if the user came here from the Shipping page (the normal route) or perhaps from the Payment page itself. If not, the user should not be here and gets immediately redirected to the Cart page.
  • You need to adjust the web addresses in this check so that they are exactly what you are using on the live web server. For your first attempt at running your app, it is probably best to comment off this check. Then when the rest of the code works, uncomment the check and test it.
  • A LINQ query is then used to look up the information on the car basket items for the given current basket number. What we need are the subtotal and quantity of items (total number of cars) for this order. These two numbers are not yet in the database, but we do have in each car basket item the number of cars and the total cost for those. Thus we need to loop through these items and add up the quantities and the costs. Once we have the quantity and subtotal, we store them into Session state.
  • A couple of sanity checks are made. If the number of car basket items is zero or the computed quantity (total number of cars) is zero, we redirect to the Cart page as for some reason there is nothing being ordered. It should not be possible for this to happen, but just in case there is a way, it is good to check for this.
  • The shipping amount is then computed using $125 per car. In practice the computation is probably more complex.
  • The amount of tax is found as 6% of the subtotal. This too is simplified. Various states have different tax rates and tax rates may change. Perhaps the best way to handle this is to create a web service that will give you the tax rate when you pass in the desired state as a parameter. You will see below the use of a web service. A possible improvement to this project, then, is to add a web service that gets used here to find the tax rate. If some state changes its tax rate, it would be much easier to change a small web service than to modify this whole car store web app.
  • The total is then calculated from the subtotal, tax, and shipping.
  • The newly computed items are then stored in Session state for use later.
  • The subtotal, shipping, tax, and total are then displayed on the Payment form, with currency formatting.
  • That is the end of what happens when this page is first loaded.

The Payment Page: Postback Case

  • If a postback occurs (because the user clicked the Purchase button), the credit card information is retrieved from the controls on the form. In addition, any dashes in the credit card number are removed by using the Replace function to replace each dash by the empty string. Another small improvement in the data is made by putting the month and year of expiration together into one string with a slash in between. This somewhat revised credit card information is then stored in Session state.
  • At this point we reach a critical spot in the purchase process: getting credit card approval. Skip this for the moment. That way any purchase on any credit card is accepted. Further below in this description, we will show how to call a web service to see if the credit card approval is True or False.
  • Next we need to record in the database a lot of the information we have gathered.
  • We begin by updating the CarBasket and CarShopper tables.
  • A LINQ query is used to find, for the current basket number, the CarBasket object and the associated CarShopper object. The latter is obtained by using the CarShopper navigation property in the CarBasket object.
  • In CarBasket, only the BasketNum and ShopperNum fields have values already. Thus we fill in the number of items, subtotal, total, shipping, tax, and also the important 1 in the BasketOrderPlaced field, showing that the user has indeed placed the order.
  • In the matching CarShopper object, only the ID field and the last name field already have values, and the last name was a temporary one based on the system time. Thus we fill in the name, address, and other contact information.
  • We next create a new CarOrder object that contains the information for the current order. This information consists of the shopper number, basket number, name, address, and contact information, plus the date of the order, found by using the property DateString. We then add this new object to our CarOrders collection of objects.
  • At this point, we save to the database what we have done thus far in the entities. Thus, our updates get written to the CarBasket and CarShopper tables and a new record is written to the CarOrder table. The main reason to save the changes now, instead of waiting until after adding a new CarPayment object, is that this gets us the order number. We need that order number in the new CarPayment object.
  • That new order ID can now be retrieved from the new CarOrder object.
  • A new car payment object is then created. It contains the order ID we just obtained and the credit card information.
  • That new car payment object is added to our collection of car payment objects and the changes are saved to the database.
  • At this point the browser is redirected to a confirmation page. A confirmation email might also be sent at this time. We skip the latter as our server is not configured to handle email.

The Payment Page: Calling the Web Service

  • As mentioned above, a web service, CreditCardCheck.asmx, has already been created for you to indicate whether or not a given amount has been approved for purchase using a given credit card.
  • This is for testing purposes and is probably not what would be used in a real ecommerce site. Whoever you sign up with to handle your credit card purchases would specify what you need to use here.
  • This particular web service has a function named Authorized, with only 2 parameters. These are the credit card number and the amount of the proposed purchase. Returning in the function name is either the string "True" indicating approval of the purchase or "False" indicating rejection. Here is the function's complete header:
  • Public Function Authorized(ByVal CardNum As String, ByVal Amount As Decimal) As String
  • This function, of course, is a fake. It just pretends to do its task so that our demo ecommerce site might be more complete. In reality, it decides the authorization or rejection of a purchase as follows:
    • If the first digit of the credit card number is a 1 or a 3, any purchase amount is approved.
    • If the first digit of the credit card number is a 5, 7, or 9, then any purchase amount under $50,000 is approved, but larger amounts are rejected.
    • If the first digit of the credit card number is an even integer, then all purchase amounts are rejected.
    • This give sufficient variety for the purpose of testing your ecommerce web site.
  • You can read about how to create and then invoke a web service in chapter 13 of the book by Gaylord, Wenz, Rasstogi, Miranda, and Hanselman. Professional ASP.NET 4.5 in C# and VB. Wiley (2013). You can borrow this from Br. David, but if all you are doing is to use (invoke) the web service, the directions here should suffice. If you should want to create your own web service as part of your final course project, then borrow the book.
  • The first step is to add a web reference to your website project. Before actually adding this reference, check that you can access the web service in a browser by using the URL http://cis2.stvincent.edu/carlsond/WebService/CreditCardCheck.asmx. It should show you what functions you can call, but you cannot call them from this web page. The function you want is the Authorized function.
  • The directions for adding the web service reference to your website are as follows:
    • In Solution Explorer, right click the main node for your Store3 website.
    • Select Add Service Reference.
    • Click Advanced and then click Add Web Reference.
    • Copy the URL http://cis2.stvincent.edu/carlsond/WebService/CreditCardCheck.asmx into the URL box on this page and then click the small right arrow button on the right side of that box.
    • You should then see the summary page for the CreditCardCheck web service and its functions, including the Authorized function.
    • Note that the web reference name, by default, is part of the URL backwards. In this case you get something like edu.stvincent.cis2 as the name. It is highly recommended that you change this to a more meaningful name, perhaps CreditCheck, as you will need to use this web reference in your VB code.
    • Click the Add Reference button.
  • In the place noted above in Payment.aspx.vb where we want to do the credit check, you first instantiate a proxy object like this: Dim VarName As New CreditCheck.CreditCardCheck(), where VarName is replaced by a variable name of your own choosing for this proxy object and CreditCheck is the exact name you used for the web reference above. CreditCardCheck, of course, is the name I gave the web service, so you have to use that name.
  • Then call the Authorized function in an IF test so that if the answer returned is "False", the browser is redirected to the Deny.aspx page. If the answer is "True" just continue on. Note that the call of this function looks like this: VarName.Authorized(Param1, Param2), where VarName is replaced by the name of the proxy object created in the previous step. Fill in the credit card number and desired purchase amount, as strings, for the 2 parameter values. Remember that you have these values saved in Session state, so they are easily available.

The Confirm and Deny Pages

  • The Confirm.aspx page is straight-forward. It presents a confirmation message that contains the order number.
  • Confirm.aspx.vb gets this order number from Session state. It also checks to see if there is no order number, and in that case, it redirects the browser to the Cart.aspx page, as the user should not be seeing the confirmation page if no order has been placed.
  • The VB code ends by clearing out all of the Session state information. There is no need for it now, plus it would not make sense to the user if that user went back to shop for more items (which should start a new shopping session instead of continuing the old one).
  • The Deny.aspx page is even simpler. It presents a message about credit card authorization being denied. The only item in the VB code is the clearing out of all Session state information.

Cleanup

  • If you commented off the URI test in Payment.aspx.vb, uncomment that section now and get it to work. You will need to have your website turned into an IIS web app and run your application on the live web server, cis2.stvincent.edu, instead of running it locally.
  • Once things are working, turn off the reporting of detailed error messages by turning ON CustomErrors in Web.config. Also turn off debugging if that is turned on in Web.config.
  • You should now have successfully created this ecommerce application.

Improvements

  • Now that the car store is working, it is time to start working on improvements to it. Do so in a new copy of your website named Store4. In CS 305, students are asked to make a few improvements that can be shown in the presentations to the class in finals week.
  • There are suggestions for improvements throughout the descriptions for Store 1 and Store 2, as well as this description for Store 3.
  • The supplied code also includes some comments that suggest improvements.
  • Also look at the Improvements section of the Store 2 description for ideas.
  • You might want to change the message on the Confirm.aspx page. If you consider the Authorized function as actually charging to the credit card and not just seeing if the amount would fit, then it would make sense to say that the order has been placed and the payment charged to the credit card (instead of saying that the order will be processed, etc.).
  • A very useful improvement would be to create a web service that provides the tax rate for whatever state is passed in as a parameter. You might limit this to a sampling of states instead of handling all 50. Read about how to create your own web service at the start of chapter 13 of our text. Note that you begin by creating a new, empty website. You then right click it in Solution Explorer and make the selections needed to add a new web service. Once your web service is complete, you also need to have this website turned into an IIS web app. Otherwise it will only be available locally.
  • You might password protect the section of the Car Store that deals with the checkout process, especially the payment page which collects credit card data. SSL should also be enabled at the web server. You could even password protect the entire store, but it would seem to be better to allow customers to browse through the products even if they have not logged in.
  • Maintaining customer profiles so that returning users do not have to fill in their contact information each time would be a nice improvement.
  • One large improvement would be to write a separate management application for the Car Store. It would allow an administrator to log into this protected site to fulfill orders, marking them as complete, to check on inventory perhaps, to clear out old data in the database, to send advertising emails to customers, etc. This is probably more than you have time to do.
  • Students in CS 305 should email me a list of the improvements they made to the car store (car store 4) no later than our final exam period (which we use for the final project presentations). This is to make sure that I am aware of all of your improvements and thus give you credit for doing these.

Back to the main page for ASP.NET 4.5 Web Apps



Author: Br. David Carlson
Last updated: November 13, 2017
Disclaimer