Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Beginning ASP.NET 2

.0.pdf
Скачиваний:
23
Добавлен:
17.08.2013
Размер:
24.67 Mб
Скачать

E-Commerce

You added a control LoginView, which contained your anonymous template:

<asp:LoginView ID=”LoginView1” Runat=”server”> <AnonymousTemplate>

<asp:passwordrecovery id=”PasswordRecovery1” runat=”server” /> </AnonymousTemplate>

</asp:LoginView>

This displayed the password recovery control, which is displayed to aid any user who might have forgotten their password.

Once again it was left to the code-behind to provide the meat of the example. When the page first loads, you check to see if there is anything in the cart. If there isn’t, then you make the wizard invisible and show the no cart label, which informs the user that there is nothing in the cart. The second check is to see if the user identity has been authenticated. This is a test of whether or not they have logged in. If they have logged in already then you jump them past the login stage, or else you have to get them logged in first:

Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles Me.Load

If Not Page.IsPostBack Then

If Profile.Cart Is Nothing Then

NoCartlabel.Visible = True

Wizard1.Visible = False

End If

If User.Identity.IsAuthenticated Then

Wizard1.ActiveStepIndex = 1

Else

Wizard1.ActiveStepIndex = 0

End If

End If

End Sub

The next procedure in the code is the code that responds to the checkbox being altered in Step 2, the delivery address. If this box is checked, you fill the text boxes with the details stored in the user’s profile. Otherwise you leave them empty:

Sub chkUseProfileAddress_CheckedChanged(ByVal sender As Object, ByVal e As System.EventArgs)

fill the delivery address from the profile, but only if it’s empty

we don’t want to overwrite the values

If chkUseProfileAddress.Checked AndAlso txtName.Text.Trim() = “” Then txtName.Text = Profile.Name

txtAddress.Text = Profile.Address txtCity.Text = Profile.City txtCounty.Text = Profile.County txtPostCode.Text = Profile.PostCode txtCountry.Text = Profile.Country

End If

End Sub

519

Chapter 13

The NextButtonClick is used to check whether the user has logged in successfully and can therefore progress to the next step of the wizard. This step only comes into play if you are actually on the login stage at the time. You check to see if the user has been validated and, if not, you display an appropriate error message informing the user that they haven’t been able to log in this time. Otherwise you validate the user:

Sub Wizard1_NextButtonClick(ByVal sender As Object, ByVal e As

System.Web.UI.WebControls.WizardNavigationEventArgs)

If e.CurrentStepIndex = 0 Then

Dim l As System.Web.UI.WebControls.Login = _

CType(Wizard1.FindControl(“Login1”), Login)

If Membership.ValidateUser(l.UserName, l.Password) Then

FormsAuthentication.SetAuthCookie(l.UserName, l.RememberMeSet)

e.Cancel = False Else

l.InstructionText = “Your login attempt was not successful. “ & _ “Please try again.”

l.InstructionTextStyle.ForeColor = System.Drawing.Color.Red

e.Cancel = True End If

Else

If Not User.Identity.IsAuthenticated Then e.Cancel = True Wizard1.ActiveStepIndex = 0

End If End If

End Sub

The FinishButtonClick contains perhaps the longest set of code, but it isn’t as daunting as it looks. This is where you write the user’s order to the database. You have to be able to roll this back if a mistake has occurred. You start by creating a connection string, and you create a transaction. Then you read in all of the details supplied in the checkout process into parameters. There are a lot of them! You have the member name, the delivery address, the credit card details, the whole shopping cart total:

Sub Wizard1_FinishButtonClick(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.WizardNavigationEventArgs)

‘ Insert the order and order lines into the database Dim conn As SqlConnection = Nothing

Dim trans As SqlTransaction = Nothing Dim cmd As SqlCommand

Try

conn = New SqlConnection(ConfigurationManager.ConnectionStrings(“WroxUnited”).ConnectionString

)

520

E-Commerce

conn.Open()

trans = conn.BeginTransaction

cmd = New SqlCommand() cmd.Connection = conn cmd.Transaction = trans ‘ set the order details

cmd.CommandText = “INSERT INTO Orders(MemberName, OrderDate, Name, “ & _ “Address, County, PostCode, Country, SubTotal, Discount, Total) “ & _ “VALUES (@MemberName, @OrderDate, @Name, “ & _

“@Address, @County, @PostCode, @Country, @Total)” cmd.Parameters.Add(“@MemberName”, Data.SqlDbType.VarChar, 50) cmd.Parameters.Add(“@OrderDate”, Data.SqlDbType.DateTime) cmd.Parameters.Add(“@Name”, Data.SqlDbType.VarChar, 50) cmd.Parameters.Add(“@Address”, Data.SqlDbType.VarChar, 255) cmd.Parameters.Add(“@County”, Data.SqlDbType.VarChar, 50) cmd.Parameters.Add(“@PostCode”, Data.SqlDbType.VarChar, 15) cmd.Parameters.Add(“@Country”, Data.SqlDbType.VarChar, 50)

cmd.Parameters.Add(“@Total”, Data.SqlDbType.Money)

cmd.Parameters(“@MemberName”).Value = User.Identity.Name cmd.Parameters(“@OrderDate”).Value = DateTime.Now() cmd.Parameters(“@Name”).Value = _

CType(Wizard1.FindControl(“txtName”), TextBox).Text cmd.Parameters(“@Address”).Value = _

CType(Wizard1.FindControl(“txtAddress”), TextBox).Text cmd.Parameters(“@County”).Value = _

CType(Wizard1.FindControl(“txtCounty”), TextBox).Text cmd.Parameters(“@PostCode”).Value = _

CType(Wizard1.FindControl(“txtPostCode”), TextBox).Text cmd.Parameters(“@Country”).Value = _

CType(Wizard1.FindControl(“txtCountry”), TextBox).Text

cmd.Parameters(“@Total”).Value = Profile.Cart.Total

Dim OrderID As Integer

OrderID = Convert.ToInt32(cmd.ExecuteScalar())

Once you’ve written the data into the Orders table, you need to create an order in which you write into the OrderLines table. This contains an order ID, the product ID, the quantity, and price. After this you commit the transaction:

‘ change the query and parameters for the order lines cmd.CommandText = “INSERT INTO OrderLines(OrderID, ProductID, “ & _

“Quantity, Price) “ & _

“VALUES (@OrderID, @ProductID, @Quantity, @Price)” cmd.Parameters.Clear() cmd.Parameters.Add(“@OrderID”, Data.SqlDbType.Int) cmd.Parameters.Add(“@ProductID”, Data.SqlDbType.Int) cmd.Parameters.Add(“@Quantity”, Data.SqlDbType.Int) cmd.Parameters.Add(“@Price”, Data.SqlDbType.Money)

cmd.Parameters(“@OrderID”).Value = OrderID

521

Chapter 13

For Each item As CartItem In Profile.Cart.Items cmd.Parameters(“@ProductID”).Value = item.ProductID cmd.Parameters(“@Quantity”).Value = item.Quantity cmd.Parameters(“@Price”).Value = item.Price

cmd.ExecuteNonQuery() Next

‘ commit the transaction trans.Commit()

The next part is the exception handler. If there is any kind of database error you have to roll back the exception and write it to the error log. Exception handling is explained in more detail in Chapter 15. This code is specifically tailored to handle SQL errors and will cause an error in the application

Catch SqlEx As SqlException

some form of error - rollback the transaction

and rethrow the exception

If trans IsNot Nothing Then trans.Rollback()

End If

‘ Log the exception

Tools.log(“An error occurred while creating the order”, SqlEx)

Throw New Exception(“An error occurred while creating the order”, SqlEx)

Return

Last, you close the connection and you clear the cart profile of the items if the transaction has been successful:

Finally

If conn IsNot Nothing Then

conn.Close()

End If

End Try

we will only reach here if the order has been created successfully

so clear the cart

Profile.Cart.Items.Clear()

End Sub

There is also a failsafe step that checks to see if you have jumped in the wizard. Normally this will be under the direction of the program; in other words, you check to see if the user has logged in and jump them forward one step. However, it’s possible an unscrupulous user might have jumped into this procedure halfway through, or that the procedure has accidentally “forgotten” the login details (normally caused by the session variable being lost — this might happen if ASP.NET restarts halfway

522

E-Commerce

through the wizard). In which case you check to see if the user has logged in or not, and if you have no record of them (in other words, they aren’t authenticated), then you jump them back to the login dialog.

Protected Sub Wizard1_ActiveStepChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Wizard1.ActiveStepChanged

If Not User.Identity.IsAuthenticated Then

Wizard1.ActiveStepIndex = 0

End If

End Sub

End Class

The checkout process is a lengthy one, but it is the most essential part. If you get this wrong, you will never get any orders!

Secure Transactions

You might be forgiven for thinking that you’re missing one vital part of the process. How do you ensure that your transaction isn’t compromised and that credit card details aren’t left wide open to the ether? Of course the nature of the HTTP protocol is exactly that, you send text across to the web server and you receive text back again. There’s nothing to stop anybody out there from listening and recording your details.

Fortunately, there is a two-pronged attack with which you can ensure transactions are secure and that the credit card details and other confidential information are not compromised:

Encryption: You must encode, or scramble, the information that is sent to the web server and received back from the web server. The web server has a public key, and users will have a private key that enables them to decode the information. Only having the public key and the private key together will allow you to encrypt the message. The web server will have a public key and its own private key at the other end. To encrypt messages, you use a secure

communications protocol; either Secure Sockets Layer (SSL) or Secure HTTP (S-HTTP) would provide this functionality. You can specify encryption methods and whether to use SSL on a connection in the Web.config file.

Certificates: To guarantee that the site you are dealing with at the other end is reputable, it can be certified by a Certificate Authority. Verisign (www.verisign.com) is perhaps the most common Certificate Authority. The authority is paid a yearly fee by the e-commerce vendor and in return the authority performs checks on the business to prove that it is legitimate. These checks are then recorded in the form of a certificate. You can browse particular sites’ certificates during the checkout process. To make your site trustworthy, you should go about obtaining a certificate from a Certificate Authority.

You’re not going to implement any of these features on the Wrox United site for reasons of practicality, but if you want to implement an e-commerce solution, you must make use of encryption and certificates.

523

Chapter 13

What Else Can You Do?

Having reached this far in the chapter you probably deserve a cup of tea and a sit down. However, while you’re enjoying your well-earned brew, this would be a good time to get your thinking cap on and have a think about what else you could add to the shop. An e-commerce site is like a community and can continually evolve as your site evolves; you shouldn’t think that you’ve done everything possible with it. The following list outlines some things to consider as your e-commerce site evolves:

Improving the Product Catalog: To improve the product catalog, you can show how many products are currently in stock, show how long they will take to deliver, show the release date of a product, add customer reviews or testimonies to how wonderful or appalling the product is, and add a cross-linking reference that mentions which other items a customer purchased when they purchased a particular item.

Improving Membership Tracking and Personalization: Add a member discount, record credit card details, mail out special offers related to past purchases (so if a customer bought a replica kit in 2004, when the 2005 version comes out, it might be good to e-mail them).

Improving the Shopping Cart: Make the shopping cart visible at all times.

Improving the Checkout Process: Make the checkout process simpler so that it can be achieved in as few clicks as possible.

Summar y

Hopefully this rather lengthy chapter hasn’t scared you away. E-commerce is a lengthy and complex process; however, the new features of ASP.NET 2.0 make it approachable and possible to program for the first time without weeks of heartache and stress. While e-commerce isn’t something to be taken lightly, it is something that can be added to an application with a little bit of thought and careful work.

This chapter started by describing the e-commerce pipeline, which is outlined as follows:

Select an item from the catalog

Put the item in the shopping cart

Checkout with the item or items

Supply address details

Pay for the item

Confirm the transaction

You started by creating a design for your product catalog and then you built a Catalog page. From the catalog you allowed the user to hone in on particular items, and you did this via a Product Item page. Neither of these items specifically required the use of the shopping cart so you held off creating one.

They just queried the database and displayed the relevant details. However, without these pages, you would not be able to shop effectively.

524

E-Commerce

With a catalog working, you could add the cart. The cart consisted of two objects, the CartItem object (one for each item selected by the user from the catalog) and the WroxShoppingCart object, which contained a bundle of CartItem objects. To enable the shopping cart you added Insert, Update, and Delete methods, which allowed you to put things in, change the amount of, and remove items from your shopping cart. Last, you connected the shopping cart to your catalog by creating an Add an Item button to your Product Item page.

Next you created a checkout process that handled the login, the confirmation of the delivery address, the credit card details, and finished the procedure. Although you couldn’t handle the card details with

the application, you learned about the various options offered. Finally you learned how to make the transactions secure and some ways to extend and improve the e-commerce procedure in Wrox United.

Exercises

An e-commerce site could potentially choose to offer many extra features. In these exercises you’re going to focus on just one. Some fan sites offer the capability for their members to purchase items at a reduced price, a membership discount. How would you go about implementing it? Each question is about a stage of the implementation and together they will give you this functionality.

1.The member discount is something that is applied to the shopping cart as you add items to the cart. What do you need to add to the ShoppingCart object to make sure it can store a discount of 10% for fan club members? You can assume that you can detect a fan club member with the property HttpContext.Current.User.IsInRole

(“FanClubMember”).

Hint: You will need to create a subtotal as well.

2.How can you display the member discount details on the Shopping Cart page so that only a fan club member will see them?

525

14

Performance

Throughout the book you’ve learned a range of techniques to help you build web sites, and really concentrated on the possibilities; what controls and code you can use to produce great functionality for your site. One thing you haven’t looked at, though, is how to make your site perform as well as it possibly can. After all, it doesn’t matter how great your site looks; if it performs badly it fails. Internet users are an impatient lot and expect sites to be fast.

Although performance should be addressed throughout the design and building of a site, this isn’t always practical, especially for the beginner. So this chapter revisits some of the earlier pages to see how they can be improved, and discusses the techniques that can be used to create the best performing sites.

In particular, this chapter looks at the following:

How to design and test for performance

The techniques to use in ASP.NET pages and data handling to ensure the fastest possible pages

What caching is and how it can be used

Let’s start with the things you can do to either existing code or new code that you write.

Simple Techniques

Several simple things are easy to do and provide good performance, as well as being good design techniques and aiding future development work and maintenance. After all, writing applications isn’t just about getting the best from them now, but also getting the best from them in the future.

Being able to fix and update web applications easily is just as much a part of development as producing the application in the first place. This section on simple techniques looks at the following:

How to dispose of resources once they are no longer required.

How to ensure connecting to a database is done in the best possible way.

How using stored procedures can improve data access performance.

Chapter 14

How to use generics to improve performance of collections.

How session state can be minimized to allow less processing to be done by ASP.NET.

How view state can be tuned to reduce the amount of data sent to and from the web server.

This section starts with object disposal.

Object Disposal

In performance terms certain things are expensive; that is, they can lead to performance problems. The reason for this is that objects need resources to manage them, resources such as CPU and memory, so the fewer of these resources used, the less work the server is doing, which in turn leads to more pages for more users. If the use of these resources can be minimized, the site will perform better, and part of that minimization is to make sure you only use the resource for as little time as possible.

In general, objects that use expensive resources like the file system, graphics, or databases should be disposed of as soon as they are no longer needed. The only exception is database connections in ASP.NET applications, as discussed in the “Database Connections” section later in the chapter. Disposal of objects frees up resources, such as files and memory, allowing the web server to perform more efficiently. By default, resources are disposed of automatically by the Garbage Collector, but it is possible to improve performance by taking control of object disposal yourself, and you can do this in two ways. You can either use a standard pattern for creating the resource, using it, and then disposing of it, or you can use the Using statement. This section looks at both, because you’ll see both in documentation.

In the Wrox United site, one area where this is used is for images. Certain users have permission to upload images: Administrators can upload new images for the shop, the owner and coach can upload player pictures, and reporters and fan club members can upload match pictures. Part of this upload process involves creating a thumbnail image, which uses the Image object, something that should be disposed of as soon as it’s no longer required. Disposal is necessary for two reasons. The first is because the image is a file-based resource, and the file may be required by other pages, so making sure you don’t have any connection to it means it’s available for others — the sooner you remove your need for it, the sooner someone else can access it. The second reason for disposal is because images take memory, so disposing of the image means the memory is freed and available for other processes.

The routine for creating thumbnails is in the ImageHandling.vb file, in the simple class with a single shared method (well two methods, but one is only image handling and isn’t actually used).

App_Code directory, and is a required as part of the

The general structure of this code is to create a new Image object from an existing image stored on disc. Then a new Image object is created using the GetThumbnailImage method, which specifies the new width and height. It’s pretty simple, but does involve two Image objects, so it requires two lots of disposal. The next section looks at how this routine works using the two ways of resource disposal.

Disposal with Try/Catch

To dispose using the Try/Catch methods you follow this simple pattern:

Try

create resource Catch

handle exception

528