Using Web Forms and Web Services

Our prior examples accessed Web services from Visual C# 2005 Windows applications. However, we can just as easily use them in Web applications created with Visual Web Developer. In fact, because Web-based businesses are becoming increasingly prevalent, it is common for Web applications to consume Web services. Figure 22.20 presents an airline reservation Web service that receives information regarding the type of seat a customer wishes to reserve and makes a reservation if such a seat is available. Later in this section, we present a Web application that allows a customer to specify a reservation request, then uses the airline reservation Web service to attempt to execute the request.

Figure 22.20. Airline reservation Web service.

1 // Fig. 22.20: ReservationService.cs 2 // Airline reservation Web Service. 3 using System; 4 using System.Web; 5 using System.Web.Services; 6 using System.Web.Services.Protocols; 7 8 [ WebService( Namespace = "http://www.deitel.com/", Description = 9 "Service that enables a user to reserve a seat on a plane." ) ] 10 [ WebServiceBinding( ConformsTo = WsiProfiles.BasicProfile1_1 ) ] 11 public class ReservationService : System.Web.Services.WebService 12 { 13 // create TicketsDataSet object for 14 // caching data from the Tickets database 15 private TicketsDataSet ticketsDataSet = new TicketsDataSet(); 16 17 // create SeatsTableAdapter for interacting with the database 18 private TicketsDataSetTableAdapters.SeatsTableAdapter 19 SeatsTableAdapter = 20 new TicketsDataSetTableAdapters.SeatsTableAdapter(); 21 22 // checks database to determine whether matching seat is available 23 [ WebMethod( Description = "Method to reserve a seat." ) ] 24 public bool Reserve( string seatType, string classType ) 25 { 26 // fill TicketsDataSet.Seats with rows that represent untaken 27 // seats that match the specified seatType and classType 28 SeatsTableAdapter.FillByTypeAndClass( 29 ticketsDataSet.Seats, seatType, classType ); 30 31 // if the number of seats returned is nonzero, 32 // obtain the first matching seat number and mark it as taken 33 if ( ticketsDataSet.Seats.Count != 0 ) 34 { 35 string seatNumber = ticketsDataSet.Seats[ 0 ].Number; 36 37 SeatsTableAdapter.UpdateSeatAsTaken( seatNumber ); 38 return true; // seat was reserved 39 } // end if 40 41 return false; // no seat was reserved 42 } // end method Reserve 43 } // end class ReservationService

The airline reservation Web service has a single Web methodReserve (lines 2442)which searches its seat database (Tickets.mdf) to locate a seat matching a user's request. If it finds an appropriate seat, Reserve updates the database, makes the reservation and returns TRue; otherwise, no reservation is made, and the method returns false. Note that the statements at lines 2829 and line 37, which query and update the database, use objects of classes TicketsDataSet and TicketsDataSetTableAdapters.SeatsTableAdapter. Recall from Chapter 20 that DataSet and TableAdapter classes are created for you when you use the DataSet Designer to add a DataSet to a project. We discuss the steps for adding the TicketsDataSet in Section 22.6.1.

Reserve takes two argumentsa string representing the desired seat type (i.e., Window, Middle or Aisle) and a string representing the desired class type (i.e., Economy or First). Our database contains four columnsthe seat number (i.e., 110), the seat type (i.e., Window, Middle or Aisle), the class type (i.e., Economy or First) and a column containing either 1 (true) or 0 (false) to indicate whether the seat is taken. Lines 2829 retrieve the seat numbers of any available seats matching the requested seat and class type. This statement fills the Seats table in ticketsDataSet with the results of the query

SELECT Number FROM Seats WHERE (Taken = 0) AND (Type = @type) AND (Class = @class)

The parameters @type and @class in the query are replaced with values of the seatType and classType arguments to SeatsTableAdapter method FillByTypeAndClass. In line 33, if the number of rows in the Seats table (ticketsDataSet.Seats.Count) is not zero, there was at least one seat that matched the user's request. In this case, the Web service reserves the first matching seat number. We obtain the seat number in line 35 by accessing the Seats table's first element (i.e., Seats[ 0 ]the first row in the table), then obtaining the value of that row's Number column. Line 37 invokes the SeatsTableAdapter method UpdateSeatAsTaken and passes to it seatNumberthe seat to reserve. Method UpdateSeatAsTaken uses the UPDATE statement

UPDATE Seats SET Taken = 1 WHERE (Number = @number)

to mark the seat as taken in the database by replacing parameter @number with the value of seatNumber. Method Reserve returns true (line 38) to indicate that the reservation was successful. If there are no matching seats (line 33), Reserve returns false (line 41) to indicate that no seats matched the user's request.

22.6.1. Adding Data Components to a Web Service

We now use Visual Web Developer's tools to configure a DataSet that allows our Web service to interact with the Tickets.mdf SQL Server database file that is provided in the example folder for Fig. 22.20. We will add a new DataSet to the project, then configure the DataSet's TableAdapter using the TableAdapter Configuration Wizard. We will use the wizard to select the data source (Tickets.mdf) and to create the SQL statements necessary to support the database operations discussed in Fig. 22.20's description. The following steps for configuring the DataSet and its corresponding TableAdapter are similar to those you saw in Chapters 2021.

Step 1: Create ReservationService and Add a DataSet to the Project

Begin by creating an ASP.NET Web Service project named ReservationService. Rename the file Service.cs as ReservationService.cs and replace its code with the code in Fig. 22.20. Next, add a DataSet named TicketsDataSet to the project. Right click the App_Code folder in the Solution Explorer and select Add New Item... from the pop-up menu. In the Add New Item dialog, select DataSet, specify TicketsDataSet.xsd in the Name field and click Add. This displays the TicketsDataSet in design view and opens the TableAdapter Configuration Wizard. When you add a DataSet to a project, the IDE creates appropriate TableAdapter classes for interacting with the database tables.

Step 2: Select the Data Source and Create a Connection

We use the TableAdapter Configuration Wizard in the next several steps to configure a TableAdapter for manipulating the Seats table in the Tickets.mdf database. Now, we select the database. In the TableAdapter Configuration Wizard, click the New Connection... button to display the Add Connection dialog. In this dialog, specify Microsoft SQL Server Database File as the Data source, then click the Browse... button to display the Select SQL Server Database File dialog. Locate Tickets.mdf on your computer, select it and click the Open button to return to the Add Connection dialog. Click the Test Connection button to test the database connection, then click OK to return to the TableAdapter Configuration Wizard. Click the Next > button, then click Yes when you are asked whether you would like to add the file to your project and modify the connection. Click Next > to save the connection string in the application configuration file.

Step 3: Open the Query Builder and Add the Seats Table from Tickets.mdf

Now we must specify how the TableAdapter will access the database. In this example, we will use SQL statements, so choose Use SQL Statements, then click Next >. Click Query Builder... to display the Query Builder and Add Table dialogs. Before building a SQL query, we must specify the table(s) to use in the query. The Tickets.mdf database contains only one table, named Seats. Select this table from the Tables tab and click Add. Click Close to close the Add Table dialog.

Step 4: Configure a SELECT Query to Obtain Available Seats

Now let's create a query which selects seats that are not already reserved and that match a particular type and class. Begin by selecting Number from the Seats table at the top of the Query Builder dialog. Next, we must specify the criteria for selecting seats. In the middle of the Query Builder dialog, click the cell below Number in the Column column and select Taken. In the Filter column of this row, type 0 (i.e., false) to indicate that we should select only seat numbers that are not taken. In the next row, select Type in the Column column and specify @type as the Filter to indicate that the filter value will be specified as an argument to the method that implements this query. In the next row, select Class in the Column column and specify @class as the Filter to indicate that this filter value also will be specified as a method argument. Uncheck the checkboxes in the Output column for the Taken, Type and Class rows. The Query Builder dialog should now appear as shown in Fig. 22.21. Click OK to close the Query Builder dialog. Click the Next > button to choose the methods to generate. For the method name under Fill a DataTable, type FillByTypeAndClass. For the method name under Return a DataTable, type GetdataByTypeAndClass. Click the Finish button to generate these methods.

Figure 22.21. QueryBuilder dialog specifying a SELECT query that selects seats that are not already reserved and that match a particular type and class.

 

Step 5: Add Another Query to the SeatsTableAdapter for the TicketsDataSet

The last two steps we need to perform create an UPDATE query that reserves a seat. In the design area for the TicketsDataSet, click SeatsTableAdapter to select it, then right click it and select Add Query... to display the TableAdapter Query Configuration Wizard. Select Use SQL Statements and click the Next > button. Select Update as the query type and click the Next > button. Delete the existing UPDATE query. Click Query Builder... to display the Query Builder and Add Table dialogs. Then add the Seats table as we did in Step 3 and click Close to return to the Query Builder dialog.

Step 6: Configure an UPDATE Statement to Reserve a Seat

In the Query Builder dialog, select the Taken column from the Seats table at the top of the dialog. In the middle of the dialog, place the value 1 (i.e., true) in the New Value column for the Taken row. In the row below Taken, select Number, uncheck the checkbox in the Set column and specify @number as the Filter value to indicate that the seat number will be specified as an argument to the method that implements this query. The Query Builder dialog should now appear as shown in Fig. 22.22. Click OK in the Query Builder dialog to return to the TableAdapter Query Configuration Wizard. Then click the Next > button to choose the name of the method that will perform the UPDATE query. Name the method UpdateSeatAsTaken, then click Finish to close the TableAdapter Query Configuration Wizard. At this point, you can use the ReservationService.asmx page to test the Web service's Reserve method. To do so, select Start Without Debugging from the Debug menu. In Section 22.6.2, we build a Web form to consume this Web service.

Figure 22.22. QueryBuilder dialog specifying an UPDATE statement that reserves a seat.

 

22.6.2. Creating a Web Form to Interact with the Airline Reservation Web Service

Figure 22.23 presents the ASPX listing for a Web Form through which users can select seat types. This page allows users to reserve a seat on the basis of its class (Economy or First) and location (Aisle, Middle or Window) in a row of seats. The page then uses the airline reservation Web service to carry out users' requests. If the database request is not successful, the user is instructed to modify the request and try again.

Figure 22.23. ASPX file that takes reservation information.

(This item is displayed on page 1209 in the print version)

1 <%-- Fig. 22.23: ReservationClient.aspx --%> 2 <%-- Web Form that allows users to reserve seats on a plane. --%> 3 <%@ Page Language="C#" AutoEventWireup="true" 4 CodeFile="ReservationClient.aspx.cs" 5 Inherits="ReservationClient" %> 6 7 "-//W3C//DTD XHTML 1.1//EN" 8 "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> 9 10

="http://www.w3.org/1999/xhtml" > 11 ="server"> 12 Ticket Reservation 13 14 15 16 ="form1" runat="server"> 17

18 ="instructionsLabel" runat="server" 19 Text="Please select the seat type and class to reserve:"> 20

21 22 ="seatList" runat="server" 23 Height="22px" Width="100px"> 24 Aisle 25 Middle 26 Window 27       28 29 ="classList" runat="server" Width="100px"> 30 Economy 31 First 32       33 34 ="reserveButton" runat="server" Height="24px" 35 OnClick="reserveButton_Click" 36 Text="Reserve" Width="102px" />

37 38 ="errorLabel" runat="server" ForeColor="#C00000" 39 Height="19px" Width="343px"> 40

41 42 43

This page defines two DropDownList objects and a Button. One DropDownList (lines 2227) displays all the seat types from which users can select. The second (lines 2932) provides choices for the class type. Users click the Button named reserveButton (lines 3436) to submit requests after making selections from the DropDownLists. The page also defines an initially blank Label named errorLabel (lines 3839), which displays an appropriate message if no seat matching the user's selection is available. The code-behind file (Fig. 22.24) attaches an event handler to reserveButton.

Figure 22.24. Code-behind file for the reservation page.

(This item is displayed on page 1210 in the print version)

1 // Fig. 22.24: ReservationClient.aspx.cs 2 // ReservationClient code behind file. 3 using System; 4 using System.Data; 5 using System.Configuration; 6 using System.Web; 7 using System.Web.Security; 8 using System.Web.UI; 9 using System.Web.UI.WebControls; 10 using System.Web.UI.WebControls.WebParts; 11 using System.Web.UI.HtmlControls; 12 13 public partial class ReservationClient : System.Web.UI.Page 14 { 15 // object of proxy type used to connect to Reservation Web service 16 private localhost.ReservationService ticketAgent = 17 new localhost.ReservationService(); 18 19 // attempt to reserve the selected type of seat 20 protected void reserveButton_Click( object sender, EventArgs e ) 21 { 22 // if WebMethod returned true, signal success 23 if ( ticketAgent.Reserve( seatList.SelectedItem.Text, 24 classList.SelectedItem.Text ) ) 25 { 26 // hide other controls 27 instructionsLabel.Visible = false; 28 seatList.Visible = false; 29 classList.Visible = false; 30 reserveButton.Visible = false; 31 errorLabel.Visible = false; 32 33 // display message indicating success 34 Response.Write( "Your reservation has been made. Thank you." ); 35 } // end if 36 else // WebMethod returned false, so signal failure 37 { 38 // display message in the initially blank errorLabel 39 errorLabel.Text = "This type of seat is not available. " + 40 "Please modify your request and try again."; 41 } // end else 42 } // end method reserveButton_Click 43 } // end class ReservationClient

Lines 1617 of Fig. 22.24 create a ReservationService object. (Recall that you must add a Web reference to this Web service.) When the user clicks Reserve (Fig. 22.25), the reserveButton_Click event handler (lines 2042 of Fig. 22.24) executes, and the page reloads. The event handler calls the Web service's Reserve method and passes to it the selected seat and class type as arguments (lines 2324). If Reserve returns true, the application displays a message thanking the user for making a reservation (line 34); otherwise, errorLabel notifies the user that the type of seat requested is not available and instructs the user to try again (lines 3940). Use the techniques presented in Chapter 21 to build this ASP.NET Web Form.

Figure 22.25. Ticket reservation Web Form sample execution.

a) Selecting a seat.

b) Seat reserved successfully.

c) Attempting to reserve another seat.

d) No seats match the requested type and class.

Категории