1. Chapter 21 – ASP .NET and Web Services Outline 21.1 Introduction 21.2 Web Services 21.3 Simple Object Access Protocol (SOAP) and Web Services 21.4 Publishing and Consuming Web Services 21.5 Session Tracking in Web Services 21.6 Using Web Forms and Web Services 21.7 Case Study: Temperature Information Application 21.8 User-Defined Types in Web Services
2. 21.2 Web Services Fig. 21.1 ASMX file rendered in Internet Explorer. Link to service description Links to web service methods
3. 21.2 Web Services Fig. 21.2 Service description for a Web service.
4. 21.2 Web Services Fig. 21.3 Invoking a method of a Web service from a Web browser.
5. 21.2 Web Services Fig. 21.4 Results of invoking a Web-service method from a Web browser.
6. 21.3 Simple Object Access Protocol (SOAP) and Web Services Fig. 21.5 SOAP request for the HugeInteger Web service. Name of method Represent arguments named first and second . The value string indicates that they need to be of type string , but in a method call they would be replaced with the argument values.
7. HugeInteger.asmx.cs 1 // Fig. 21.6: HugeInteger.asmx.cs 2 // HugeInteger Web Service. 3 4 using System; 5 using System.Text; 6 using System.Collections; 7 using System.ComponentModel; 8 using System.Data; 9 using System.Diagnostics; 10 using System.Web; 11 using System.Web.Services; // contains Web service related classes 12 13 namespace HugeIntegerWebService 14 { 15 /// <summary> 16 /// performs operations on large integers 17 /// </summary> 18 [ WebService( 19 Namespace = "http://www.deitel.com/csphtp1/ch21/" , 20 Description = "A Web service which provides methods that" + 21 " can manipulate large integer values." ) ] 22 public class HugeInteger : System.Web.Services.WebService 23 { 24 // default constructor 25 public HugeInteger() 26 { 27 // CODEGEN: This call is required by the ASP .NET Web 28 // Services Designer 29 InitializeComponent(); 30 31 number = new int [ MAXIMUM ]; 32 } 33 Set Namespace property of WebService attribute to specify the namespace that the Web service belongs to Set Description property of WebService attribute to describe the function of the Web Service Class HugeInteger inherits from System.Web.Services.WebService
8. HugeInteger.asmx.cs 34 #region Component Designer generated code 35 /// <summary> 36 /// Required method for Designer support - do not modify 37 /// the contents of this method with the code editor. 38 /// </summary> 39 private void InitializeComponent() 40 { 41 } 42 #endregion 43 44 /// <summary> 45 /// Clean up any resources being used. 46 /// </summary> 47 protected override void Dispose( bool disposing ) 48 { 49 } 50 51 // WEB SERVICE EXAMPLE 52 // The HelloWorld() example service returns 53 // the string Hello World 54 // To build, uncomment the following lines 55 // then save and build the project 56 // To test this web service, press F5 57 58 // [WebMethod] 59 // public string HelloWorld() 60 // { 61 // return "Hello World"; 62 // } 63 64 private const int MAXIMUM = 100 ; 65 66 public int [] number; 67
9. HugeInteger.asmx.cs 68 // indexer that accepts an integer parameter 69 public int this [ int index ] 70 { 71 get 72 { 73 return number[ index ]; 74 } 75 76 set 77 { 78 number[ index ] = value ; 79 } 80 81 } // end indexer 82 83 // returns string representation of HugeInteger 84 public override string ToString() 85 { 86 StringBuilder returnString = new StringBuilder(); 87 88 foreach ( int digit in number ) 89 returnString.Insert( 0 , digit ); 90 91 return returnString.ToString(); 92 } 93 94 // creates HugeInteger based on argument 95 public static HugeInteger FromString( string integer ) 96 { 97 HugeInteger parsedInteger = new HugeInteger(); 98 99 for ( int i = 0 ; i < integer. Length ; i++ ) 100 parsedInteger[ i ] = Int32.Parse( 101 integer[ integer. Length - i - 1 ].ToString() ); Indexer for class HugeInteger
10. HugeInteger.asmx.cs 102 103 return parsedInteger; 104 } 105 106 // WebMethod that performs integer addition 107 // represented by string arguments 108 [ WebMethod ( Description = "Adds two huge integers." ) ] 109 public string Add( string first, string second ) 110 { 111 int carry = 0 ; 112 113 HugeInteger operand1 = HugeInteger.FromString( first ); 114 HugeInteger operand2 = 115 HugeInteger.FromString( second ); 116 117 // store result of addition 118 HugeInteger result = new HugeInteger(); 119 120 // perform addition algorithm for each digit 121 for ( int i = 0 ; i < MAXIMUM ; i++ ) 122 { 123 // add two digits in same column 124 // result is their sum, plus carry from 125 // previous operation modulus 10 126 result[ i ] = 127 ( operand1[ i ] + operand2[ i ] ) % 10 + carry; 128 129 // store remainder of dividing 130 // sums of two digits by 10 131 carry = ( operand1[ i ] + operand2[ i ] ) / 10 ; 132 } 133 134 return result.ToString(); 135 136 } // end method Add Method Add that adds two HugeInteger s WebMethod attribute specifies that this method may be called by remote client applications Description property of WebMethod attribute summarizes the function of the method
11. HugeInteger.asmx.cs 137 138 // WebMethod that performs the subtraction of integers 139 // represented by string arguments 140 [ WebMethod ( 141 Description = "Subtracts two huge integers." ) ] 142 public string Subtract( string first, string second ) 143 { 144 HugeInteger operand1 = HugeInteger.FromString( first ); 145 HugeInteger operand2 = 146 HugeInteger.FromString( second ); 147 HugeInteger result = new HugeInteger(); 148 149 // subtract top digit from bottom digit 150 for ( int i = 0 ; i < MAXIMUM ; i++ ) 151 { 152 // if top digit is smaller than bottom 153 // digit we need to borrow 154 if ( operand1[ i ] < operand2[ i ] ) 155 Borrow( operand1, i ); 156 157 // subtract bottom from top 158 result[ i ] = operand1[ i ] - operand2[ i ]; 159 } 160 161 return result.ToString(); 162 163 } // end method Subtract 164 165 // borrows 1 from next digit 166 private void Borrow( HugeInteger integer, int place ) 167 { 168 // if no place to borrow from, signal problem 169 if ( place >= MAXIMUM - 1 ) 170 throw new ArgumentException(); 171 Method Subtract that subtracts one HugeInteger from another Helper method Borrow used by method Subtract when 1 needs to be borrowed from the next number
12. HugeInteger.asmx.cs 172 // otherwise if next digit is zero, 173 // borrow from digit to left 174 else if ( integer[ place + 1 ] == 0 ) 175 Borrow( integer, place + 1 ); 176 177 // add ten to current place because we borrowed 178 // and subtract one from previous digit - 179 // this is digit borrowed from 180 integer[ place ] += 10 ; 181 integer[ place + 1 ] -= 1 ; 182 183 } // end method Borrow 184 185 // WebMethod that returns true if first integer is 186 // bigger than second 187 [ WebMethod ( Description = "Determines whether first " + 188 "integer is larger than the second integer." ) ] 189 public bool Bigger( string first, string second ) 190 { 191 char [] zeroes = { '0' }; 192 193 try 194 { 195 // if elimination of all zeroes from result 196 // of subtraction is an empty string, 197 // numbers are equal, so return false, 198 // otherwise return true 199 if ( Subtract( first, second ).Trim( zeroes ) == "" ) 200 return false ; 201 else 202 return true ; 203 } 204 Returns true if the first integer is bigger then the second and false otherwise
13. HugeInteger.asmx.cs 205 // if ArgumentException occurs, first number 206 // was smaller, so return false 207 catch ( ArgumentException ) 208 { 209 return false ; 210 } 211 212 } // end method Bigger 213 214 // WebMethod returns true if first integer is 215 // smaller than second 216 [ WebMethod ( Description = "Determines whether the " + 217 "first integer is smaller than the second integer." ) ] 218 public bool Smaller( string first, string second ) 219 { 220 // if second is bigger than first, then first is 221 // smaller than second 222 return Bigger( second, first ); 223 } 224 225 // WebMethod that returns true if two integers are equal 226 [ WebMethod ( Description = "Determines whether the " + 227 "first integer is equal to the second integer." ) ] 228 public bool EqualTo( string first, string second ) 229 { 230 // if either first is bigger than second, or first is 231 // smaller than second, they are not equal 232 if ( Bigger( first, second ) || 233 Smaller( first, second ) ) 234 return false ; Returns true if the first integer is smaller then the second and false otherwise Returns true if the two integers are equal and false otherwise
14. HugeInteger.asmx.cs Program Output 235 else 236 return true ; 237 } 238 239 } // end class HugeInteger 240 241 } // end namespace HugeIntegerWebService
15. 21.4 Publishing and Consuming Web Services Fig. 21.7 Design view of a Web service.
16. 21.4 Publishing and Consuming Web Services Fig. 21.8 Adding a Web service reference to a project.
17. 21.4 Publishing and Consuming Web Services Fig. 21.9 Add Web Reference dialog. Link to root directory of web server
18. 21.4 Publishing and Consuming Web Services Fig. 21.10 Web services located on localhost .
19. 21.4 Publishing and Consuming Web Services Fig. 21.11 Web reference selection and description.
20. 21.4 Publishing and Consuming Web Services Fig. 21.12 Solution Explorer after adding a Web reference to a project. Service description Proxy class Web service discovery file
21. UsingHugeIntegerService.cs 1 // Fig. 21.13: UsingHugeIntegerService.cs 2 // Using the HugeInteger Web Service. 3 4 using System; 5 using System.Drawing; 6 using System.Collections; 7 using System.ComponentModel; 8 using System.Windows.Forms; 9 using System.Web.Services.Protocols; 10 11 // allows user to perform operations on large integers 12 public class UsingHugeIntService : System.Windows.Forms.Form 13 { 14 private System.Windows.Forms.Label promptLabel; 15 private System.Windows.Forms.Label resultLabel; 16 17 private System.Windows.Forms.TextBox firstTextBox; 18 private System.Windows.Forms.TextBox secondTextBox; 19 20 private System.Windows.Forms.Button addButton; 21 private System.Windows.Forms.Button subtractButton; 22 private System.Windows.Forms.Button biggerButton; 23 private System.Windows.Forms.Button smallerButton; 24 private System.Windows.Forms.Button equalButton; 25 26 private System.ComponentModel.Container components = null ; 27 28 // declare a reference Web service 29 private localhost.HugeInteger remoteInteger; 30 31 private char [] zeroes = { '0' }; 32
22. UsingHugeIntegerService.cs 33 // default constructor 34 public UsingHugeIntService() 35 { 36 InitializeComponent(); 37 38 // instantiate remoteInteger 39 remoteInteger = new localhost.HugeInteger(); 40 } 41 42 // Visual Studio .NET generated code 43 44 [STAThread] 45 static void Main() 46 { 47 Application.Run( new UsingHugeIntService() ); 48 49 } // end Main 50 51 // checks whether two numbers user input are equal 52 protected void equalButton_Click( 53 object sender, System.EventArgs e ) 54 { 55 // make sure HugeIntegers do not exceed 100 digits 56 if ( CheckSize( firstTextBox, secondTextBox ) ) 57 return ; 58 59 // call Web-service method to determine 60 // whether integers are equal 61 if ( remoteInteger.EqualTo( 62 firstTextBox.Text, secondTextBox.Text ) ) 63 64 resultLabel.Text = 65 firstTextBox.Text.TrimStart( zeroes ) + 66 " is equal to " + 67 secondTextBox.Text.TrimStart( zeroes ); Instantiate remoteInteger to be a new HugeInteger object Call HugeInteger Web method EqualTo remotely
23. UsingHugeIntegerService.cs 68 else 69 resultLabel.Text = 70 firstTextBox.Text.TrimStart( zeroes ) + 71 " is NOT equal to " + 72 secondTextBox.Text.TrimStart( zeroes ); 73 74 } // end method equalButton_Click 75 76 // checks whether first integer input 77 // by user is smaller than second 78 protected void smallerButton_Click( 79 object sender, System.EventArgs e ) 80 { 81 // make sure HugeIntegers do not exceed 100 digits 82 if ( CheckSize( firstTextBox, secondTextBox ) ) 83 return ; 84 85 // call Web-service method to determine whether first 86 // integer is smaller than second 87 if ( remoteInteger.Smaller( 88 firstTextBox.Text, secondTextBox.Text ) ) 89 90 resultLabel.Text = 91 firstTextBox.Text.TrimStart( zeroes ) + 92 " is smaller than " + 93 secondTextBox.Text.TrimStart( zeroes ); 94 else 95 resultLabel.Text = 96 firstTextBox.Text.TrimStart( zeroes ) + 97 " is NOT smaller than " + 98 secondTextBox.Text.TrimStart( zeroes ); 99 100 } // end method smallerButton_Click 101 Call HugeInteger Web method Smaller remotely
24. UsingHugeIntegerService.cs 102 // checks whether first integer input 103 // by user is bigger than second 104 protected void biggerButton_Click( 105 object sender, System.EventArgs e ) 106 { 107 // make sure HugeIntegers do not exceed 100 digits 108 if ( CheckSize( firstTextBox, secondTextBox ) ) 109 return ; 110 111 // call Web-service method to determine whether first 112 // integer is larger than the second 113 if ( remoteInteger.Bigger( firstTextBox.Text, 114 secondTextBox.Text ) ) 115 116 resultLabel.Text = 117 firstTextBox.Text.TrimStart( zeroes ) + 118 " is larger than " + 119 secondTextBox.Text.TrimStart( zeroes ); 120 else 121 resultLabel.Text = 122 firstTextBox.Text.TrimStart( zeroes ) + 123 " is NOT larger than " + 124 secondTextBox.Text.TrimStart( zeroes ); 125 126 } // end method biggerButton_Click 127 128 // subtract second integer from first 129 protected void subtractButton_Click( 130 object sender, System.EventArgs e ) 131 { 132 // make sure HugeIntegers do not exceed 100 digits 133 if ( CheckSize( firstTextBox, secondTextBox ) ) 134 return ; 135 Call HugeInteger Web method Bigger remotely
25. UsingHugeIntegerService.cs 136 // perform subtraction 137 try 138 { 139 string result = remoteInteger.Subtract( 140 firstTextBox.Text, 141 secondTextBox.Text ).TrimStart( zeroes ); 142 143 resultLabel.Text = ( ( result == "" ) ? "0" : result ); 144 } 145 146 // if WebMethod throws an exception, then first 147 // argument was smaller than second 148 catch ( SoapException ) 149 { 150 MessageBox.Show( 151 "First argument was smaller than the second" ); 152 } 153 154 } // end method subtractButton_Click 155 156 // adds two integers input by user 157 protected void addButton_Click( 158 object sender, System.EventArgs e ) 159 { 160 // make sure HugeInteger does not exceed 100 digits 161 // and is not situation where both integers are 100 162 // digits long--result in overflow 163 if ( firstTextBox.Text.Length > 100 || 164 secondTextBox.Text.Length > 100 || 165 ( firstTextBox.Text.Length == 100 && 166 secondTextBox.Text.Length == 100 ) ) 167 { Call HugeInteger Web method Subtract remotely
26. UsingHugeIntegerService.cs 168 MessageBox.Show( "HugeIntegers must not be more " 169 + "than 100 digitsBoth integers cannot be of" 170 + " length 100: this causes an overflow" , 171 "Error" , MessageBoxButtons. OK , 172 MessageBoxIcon. Information ); 173 174 return ; 175 } 176 177 // perform addition 178 resultLabel.Text = remoteInteger.Add( firstTextBox.Text, 179 secondTextBox.Text ).TrimStart( zeroes ).ToString(); 180 181 } // end method addButton_Click 182 183 // determines whether size of integers is too big 184 private bool CheckSize( TextBox first, TextBox second ) 185 { 186 if ( first.Text.Length > 100 || second.Text.Length > 100 ) 187 { 188 MessageBox.Show( "HugeIntegers must be less than 100" 189 + " digits" , "Error" , MessageBoxButtons. OK , 190 MessageBoxIcon. Information ); 191 192 return true ; 193 } 194 195 return false ; 196 197 } // end method CheckSize 198 199 } // end class UsingHugeIntegerService Call HugeInteger Web method Add remotely
28. BlackjackService.asmx.cs 1 // Fig. 21.14: BlackjackService.asmx.cs 2 // Blackjack Web Service which manipulates a deck of cards. 3 4 using System; 5 using System.Collections; 6 using System.ComponentModel; 7 using System.Data; 8 using System.Diagnostics; 9 using System.Web; 10 using System.Web.Services; 11 12 namespace BlackjackWebService 13 { 14 [ WebService( 15 Namespace = "http://www.deitel.com/csphtp1/ch21/" , 16 Description = "A Web service that provides methods " + 17 "to manipulate a deck of cards." ) ] 18 public class BlackjackService : System.Web.Services.WebService 19 { 20 21 // Visual Studio .NET generated code 22 23 // deal new card 24 [ WebMethod( EnableSession = true , 25 Description = "Deal a new card from the deck." ) ] 26 public string DealCard() 27 { 28 string card = "2 2" ; 29 Method DealCard with WebMethod attribute which allows client applications to invoke it Property EnableSession is set to true allowing this method to maintain session information
29. BlackjackService.asmx.cs 30 // get client's deck 31 ArrayList deck = ( ArrayList ) Session[ "deck" ]; 32 card = ( string ) deck[ 0 ]; 33 deck.RemoveAt( 0 ); 34 return card; 35 36 } // end method DealCard 37 38 [ WebMethod( EnableSession = true , 39 Description = "Create and shuffle a deck of cards." ) ] 40 public void Shuffle() 41 { 42 Random randomObject = new Random(); 43 44 ArrayList deck = new ArrayList(); 45 46 // generate all possible cards 47 for ( int i = 2 ; i < 15 ; i++ ) { 48 for ( int j = 0 ; j < 4 ; j++ ) { 49 deck.Add( i + " " + j ); 50 } 51 } 52 53 // swap each card with another card randomly 54 for ( int i = 0 ; i < deck.Count; i++ ) 55 { 56 int newIndex = randomObject.Next( deck.Count ); 57 object temporary = deck[ i ]; 58 deck[ i ] = deck[ newIndex ]; 59 deck[ newIndex ] = temporary; 60 } 61 62 // add this deck to user's session state 63 Session[ "deck" ] = deck; 64 } Retrieve the deck variable from the Session object. Cast the resulting object to an ArrayList and assign local variable deck to reference it Set card to be the first object in deck (cast to a string ) Remove the first object from deck Initialize deck to a new ArrayList object Generate all possible cards and add them to deck Swap each card with a random card from the deck Assign the Session variable deck to reference ArrayList deck
30. BlackjackService.asmx.cs 65 66 // computes value of hand 67 [ WebMethod ( Description = "Compute a " + 68 "numerical value for the current hand." ) ] 69 public int CountCards( string dealt ) 70 { 71 // split string containing cards 72 char [] tab = { '' }; 73 string [] cards = dealt.Split( tab ); 74 int total = 0 , face, aceCount = 0 ; 75 76 foreach ( string drawn in cards ) 77 { 78 // get face of card 79 face = 80 Int32.Parse( drawn.Substring( 81 0 , drawn.IndexOf( " " ) ) ); 82 83 switch ( face ) 84 { 85 // if ace, increment number of aces in hand 86 case 14 : 87 aceCount++; 88 break ; 89 90 // if Jack, Queen or King, add 10 to total 91 case 11 : case 12 : case 13 : 92 total += 10 ; 93 break ; 94 Use method Split to create a string array containing the individual cards (stored in dealt and separated by tab characters) Repeat loop for each member of cards If the card is in Ace, increment aceCount but do not add to total Add 10 to total if the card is a Jack, Queen or King
31. BlackjackService.asmx.cs 95 // otherwise, add value of face 96 default : 97 total += face; 98 break ; 99 100 } // end switch 101 102 } // end foreach 103 104 // if any aces, calculate optimum total 105 if ( aceCount > 0 ) 106 { 107 // if it is possible to count one ace as 11, and rest 108 // 1 each, do so; otherwise, count all aces as 1 each 109 if ( total + 11 + aceCount - 1 <= 21 ) 110 total += 11 + aceCount - 1 ; 111 else 112 total += aceCount; 113 } 114 115 return total; 116 117 } // end method CountCards 118 119 } // end class BlackjackService 120 121 } // end namespace BlackjackWebService Otherwise, add the value of the card to total If it is possible to count one ace as 11, do so; otherwise, count each ace as 1
32. Blackjack.cs 1 // Fig. 21.15: Blackjack.cs 2 // Blackjack game that uses the Blackjack Web service. 3 4 using System; 5 using System.Drawing; 6 using System.Collections; 7 using System.ComponentModel; 8 using System.Windows.Forms; 9 using System.Data; 10 using System.Net; 11 12 // game that uses Blackjack Web Service 13 public class Blackjack : System.Windows.Forms.Form 14 { 15 private System.Windows.Forms.PictureBox pictureBox1; 16 private System.Windows.Forms.PictureBox pictureBox2; 17 private System.Windows.Forms.PictureBox pictureBox3; 18 private System.Windows.Forms.PictureBox pictureBox4; 19 private System.Windows.Forms.PictureBox pictureBox5; 20 private System.Windows.Forms.PictureBox pictureBox6; 21 private System.Windows.Forms.PictureBox pictureBox7; 22 private System.Windows.Forms.PictureBox pictureBox8; 23 private System.Windows.Forms.PictureBox pictureBox9; 24 private System.Windows.Forms.PictureBox pictureBox10; 25 private System.Windows.Forms.PictureBox pictureBox11; 26 private System.Windows.Forms.PictureBox pictureBox12; 27 private System.Windows.Forms.PictureBox pictureBox13; 28 private System.Windows.Forms.PictureBox pictureBox14; 29 private System.Windows.Forms.PictureBox pictureBox15; 30 private System.Windows.Forms.PictureBox pictureBox16; 31 private System.Windows.Forms.PictureBox pictureBox17; 32 private System.Windows.Forms.PictureBox pictureBox18; 33 private System.Windows.Forms.PictureBox pictureBox19; 34 private System.Windows.Forms.PictureBox pictureBox20; 35 private System.Windows.Forms.PictureBox pictureBox21;
33. Blackjack.cs 36 private System.Windows.Forms.PictureBox pictureBox22; 37 38 private System.Windows.Forms.Button dealButton; 39 private System.Windows.Forms.Button hitButton; 40 private System.Windows.Forms.Button stayButton; 41 42 private System.ComponentModel.Container components = null ; 43 44 private localhost.BlackjackService dealer; 45 private string dealersCards, playersCards; 46 private ArrayList cardBoxes; 47 private int playerCard, dealerCard; 48 49 // labels displaying game status, dealer and player 50 private System.Windows.Forms.Label dealerLabel; 51 private System.Windows.Forms.Label playerLabel; 52 private System.Windows.Forms.Label statusLabel; 53 54 public enum GameStatus : 55 int { PUSH , LOSE , WIN , BLACKJACK }; 56 57 public Blackjack() 58 { 59 InitializeComponent(); 60 61 dealer = new localhost.BlackjackService(); 62 63 // allow session state 64 dealer.CookieContainer = new CookieContainer(); 65 66 cardBoxes = new ArrayList(); 67 68 // put PictureBoxes into cardBoxes 69 cardBoxes.Add( pictureBox1 ); 70 cardBoxes.Add( pictureBox2 ); Instantiate a new BlackjackService object Instantiate dealer ’s CookieContainer property to allow the Web service to maintain session state information
35. Blackjack.cs 103 // deals cards to dealer while dealer's total is 104 // less than 17, then computes value of each hand 105 // and determines winner 106 protected void stayButton_Click( 107 object sender, System.EventArgs e ) 108 { 109 stayButton.Enabled = false ; 110 hitButton.Enabled = false ; 111 dealButton.Enabled = true ; 112 DealerPlay(); 113 } 114 115 // process dealers turn 116 private void DealerPlay() 117 { 118 // while value of dealer's hand is below 17, 119 // dealer must take cards 120 while ( dealer.CountCards( dealersCards ) < 17 ) 121 { 122 dealersCards += "" + dealer.DealCard(); 123 DisplayCard( dealerCard, "" ); 124 dealerCard++; 125 MessageBox.Show( "Dealer takes a card" ); 126 } 127 128 int dealersTotal = dealer.CountCards( dealersCards ); 129 int playersTotal = dealer.CountCards( playersCards ); 130 131 // if dealer busted, player wins 132 if ( dealersTotal > 21 ) 133 { 134 GameOver( GameStatus. WIN ); 135 return ; 136 } 137 Call method DealerPlay to process the dealer’s turn when the user wishes to stay While the dealer’s hand totals less then 17, the dealer must take cards If dealer went over 21, players wins
36. Blackjack.cs 138 // if dealer and player have not exceeded 21, 139 // higher score wins; equal scores is a push. 140 if ( dealersTotal > playersTotal ) 141 GameOver( GameStatus. LOSE ); 142 else if ( playersTotal > dealersTotal ) 143 GameOver( GameStatus. WIN ); 144 else 145 GameOver( GameStatus. PUSH ); 146 147 } // end method DealerPlay 148 149 // deal another card to player 150 protected void hitButton_Click( 151 object sender, System.EventArgs e ) 152 { 153 // get player another card 154 string card = dealer.DealCard(); 155 playersCards += "" + card; 156 DisplayCard( playerCard, card ); 157 playerCard++; 158 159 int total = dealer.CountCards( playersCards ); 160 161 // if player exceeds 21, house wins 162 if ( total > 21 ) 163 GameOver( GameStatus.LOSE ); 164 If neither the dealer nor the player have went over 21, higher score wins; equal scores result in a push Deal the player a card as requested If player went over 21, the house wins
37. Blackjack.cs 165 // if player has 21, they cannot take more cards 166 // the dealer plays 167 if ( total == 21 ) 168 { 169 hitButton.Enabled = false ; 170 DealerPlay(); 171 } 172 173 } // end method hitButton_Click 174 175 // deal two cards each to dealer and player 176 protected void dealButton_Click( 177 object sender, System.EventArgs e ) 178 { 179 string card; 180 181 // clear card images 182 foreach ( PictureBox cardImage in cardBoxes ) 183 cardImage.Image = null ; 184 185 // clear status from previous game 186 statusLabel.Text = "" ; 187 188 // shuffle cards 189 dealer.Shuffle(); 190 191 // deal two cards to player 192 playersCards = dealer.DealCard(); 193 DisplayCard( 11 , playersCards ); 194 card = dealer.DealCard(); 195 DisplayCard( 12 , card ); 196 playersCards += "" + card; 197 If the player has 21, the player cannot take more cards; dealer’s turn Clear the PictureBox es containing the card images Shuffle the cards by calling BlackjackService method Shuffle Deal two cards to player
38. Blackjack.cs 198 // deal two cards to dealer, only display face 199 // of first card 200 dealersCards = dealer.DealCard() ; 201 DisplayCard( 0 , dealersCards ); 202 card = dealer.DealCard(); 203 DisplayCard( 1 , "" ); 204 dealersCards += "" + card; 205 206 stayButton.Enabled = true ; 207 hitButton.Enabled = true ; 208 dealButton.Enabled = false ; 209 210 int dealersTotal = dealer.CountCards( dealersCards ); 211 int playersTotal = dealer.CountCards( playersCards ); 212 213 // if hands equal 21, it is a push 214 if ( dealersTotal == playersTotal && 215 dealersTotal == 21 ) 216 GameOver( GameStatus. PUSH ); 217 218 // if player has 21 player wins with blackjack 219 else if ( playersTotal == 21 ) 220 GameOver( GameStatus. BLACKJACK ); 221 222 // if dealer has 21, dealer wins 223 else if ( dealersTotal == 21 ) 224 GameOver( GameStatus. LOSE ); 225 226 dealerCard = 2 ; 227 playerCard = 13 ; 228 229 } // end method dealButton_Click 230 Deal two cards to dealer but only display the face of the first one If both hands equal 21, it is a push If only the player has 21, the player wins If only the dealer has 21, the dealer wins
39. Blackjack.cs 231 // displays card represented by cardValue in 232 // PictureBox with number card 233 public void DisplayCard( int card, string cardValue ) 234 { 235 // retrieve appropriate PictureBox from ArrayList 236 PictureBox displayBox = ( PictureBox ) cardBoxes[ card ]; 237 238 // if string representing card is empty, 239 // set displayBox to display back of card 240 if ( cardValue == "" ) 241 { 242 displayBox.Image = 243 Image.FromFile( "blackjack_imagescardback.png" ); 244 return ; 245 } 246 247 // retrieve face value of card from cardValue 248 int faceNumber = Int32.Parse( cardValue.Substring( 0 , 249 cardValue.IndexOf( " " ) ) ); 250 251 string face = faceNumber.ToString(); 252 253 // retrieve the suit of the card from cardValue 254 string suit = cardValue.Substring( 255 cardValue.IndexOf( " " ) + 1 ); 256 257 char suitLetter; 258 259 // determine if suit is other than clubs 260 switch ( Convert.ToInt32( suit ) ) 261 { 262 // suit is clubs 263 case 0 : 264 suitLetter = 'c' ; 265 break ; If cardValue is an empty string , display the back of the card image Retrieve face and suit of card from cardValue
40. Blackjack.cs 266 267 // suit is diamonds 268 case 1 : 269 suitLetter = 'd' ; 270 break ; 271 272 // suit is hearts 273 case 2 : 274 suitLetter = 'h' ; 275 break ; 276 277 // else suit is spades 278 default : 279 suitLetter = 's' ; 280 break ; 281 } 282 283 // set displayBox to display appropriate image 284 displayBox.Image = Image.FromFile( 285 "blackjack_images" + face + suitLetter + ".png" ); 286 287 } // end method DisplayCard 288 289 // displays all player cards and shows 290 // appropriate game status message 291 public void GameOver( GameStatus winner ) 292 { 293 char [] tab = { '' }; 294 string [] cards = dealersCards.Split( tab ); 295 296 for ( int i = 0 ; i < cards.Length; i++ ) 297 DisplayCard( i, cards[ i ] ); 298 Display all of dealer’s cards
41. Blackjack.cs 299 // push 300 if ( winner == GameStatus. PUSH ) 301 statusLabel.Text = "It's a tie!" ; 302 303 // player loses 304 else if ( winner == GameStatus. LOSE ) 305 statusLabel.Text = "You Lose Try Again!" ; 306 307 // player wins 308 else if ( winner == GameStatus. WIN ) 309 statusLabel.Text = "You Win!" ; 310 311 // player has won with blackjack 312 else 313 statusLabel.Text = "BlackJack!" ; 314 315 stayButton.Enabled = false ; 316 hitButton.Enabled = false ; 317 dealButton.Enabled = true ; 318 319 } // end method GameOver 320 321 } // end class Blackjack Display appropriate message in statusLabel
45. Reservation.asmx.cs 1 // Fig. 21.16: Reservation.asmx.cs 2 // Airline reservation Web Service. 3 4 using System; 5 using System.Data; 6 using System.Diagnostics; 7 using System.Web; 8 using System.Web.Services; 9 using System.Data.OleDb; 10 11 namespace AirlineReservation 12 { 13 // performs reservation of a seat 14 [ WebService( Namespace = "http://www.deitel.com/csphtp1/ch21/" , 15 Description = "Service that enables a user to " + 16 "reserve a seat on a plane." ) ] 17 public class Reservation : System.Web.Services.WebService 18 { 19 private System.Data.OleDb.OleDbCommand 20 oleDbSelectCommand1; 21 private System.Data.OleDb.OleDbCommand 22 oleDbInsertCommand1; 23 private System.Data.OleDb.OleDbCommand 24 oleDbUpdateCommand1; 25 private System.Data.OleDb.OleDbCommand 26 oleDbDeleteCommand1; 27 private System.Data.OleDb.OleDbConnection 28 oleDbConnection1; 29 private System.Data.OleDb.OleDbDataAdapter 30 oleDbDataAdapter1; 31 32 // Visual Studio .NET generated code 33
46. Reservation.asmx.cs 34 // checks database to determine whether 35 // matching seat is available 36 [ WebMethod ( Description = "Method to reserve seat." ) ] 37 public bool Reserve( string seatType, string classType ) 38 { 39 OleDbDataReader dataReader; 40 41 // try database connection 42 try 43 { 44 // open database connection 45 oleDbConnection1.Open(); 46 47 // set and execute SQL query 48 oleDbDataAdapter1.SelectCommand.CommandText = 49 "SELECT Number FROM Seats WHERE Type = '" + 50 seatType + "' AND Class = '" + classType + 51 "' AND Taken = '0'" ; 52 dataReader = 53 oleDbDataAdapter1.SelectCommand.ExecuteReader(); 54 55 // if there were results, seat is available 56 if ( dataReader.Read() ) 57 { 58 string seatNumber = dataReader.GetString( 0 ); 59 60 dataReader.Close(); 61 Set a query to find seats of the specified criteria. Execute query. If Read method returned true, then query returned result(s) Retrieve the first string in the row (the seat number)
47. Reservation.asmx.cs 62 // update first available seat to be taken 63 oleDbDataAdapter1.UpdateCommand.CommandText = 64 "Update Seats Set Taken = '1' WHERE Number = '" 65 + seatNumber + "'" ; 66 oleDbDataAdapter1.UpdateCommand.ExecuteNonQuery(); 67 68 return true ; 69 70 } // end if 71 dataReader.Close(); 72 } 73 catch ( OleDbException ) // if connection problem 74 { 75 return false ; 76 } 77 finally 78 { 79 oleDbConnection1.Close(); 80 } 81 82 // no seat was reserved 83 return false ; 84 85 } // end method Reserve 86 87 } // end class Reservation 88 89 } // end namespace AirlineReservation Set a query that updates the seat numbered seatNumber to be taken. Execute query.
48. 21.6 Using Web Forms and Web Services Fig. 21.17 Airline Web Service in design view.
51. TicketReservation.aspx.cs 1 // Fig. 21.19: TicketReservation.aspx.cs 2 // Making a Reservation using a Web Service. 3 4 using System; 5 using System.Collections; 6 using System.ComponentModel; 7 using System.Data; 8 using System.Drawing; 9 using System.Web; 10 using System.Web.SessionState; 11 using System.Web.UI; 12 using System.Web.UI.WebControls; 13 using System.Web.UI.HtmlControls; 14 15 namespace MakeReservation 16 { 17 // allows visitors to select seat type to reserve, and 18 // then make reservation 19 public class TicketReservation : System.Web.UI.Page 20 { 21 protected System.Web.UI.WebControls.DropDownList 22 seatList; 23 protected System.Web.UI.WebControls.DropDownList 24 classList; 25 26 protected System.Web.UI.WebControls.Button 27 reserveButton; 28 protected System.Web.UI.WebControls.Label Label1; 29 30 private localhost.Reservation agent = 31 new localhost.Reservation(); 32
52. TicketReservation.aspx.cs 33 private void Page_Load( 34 object sender, System.EventArgs e ) 35 { 36 if ( IsPostBack ) 37 { 38 seatList.Visible = false ; 39 classList.Visible = false ; 40 reserveButton.Visible = false ; 41 Label1.Visible = false ; 42 } 43 } 44 45 // Visual Studio .NET generated code 46 47 // calls Web Service to try to reserve specified seat 48 public void reserveButton_Click ( 49 object sender, System.EventArgs e ) 50 { 51 // if Web-service method returned true, signal success 52 if ( agent.Reserve( seatList.SelectedItem.Text, 53 classList.SelectedItem.Text ) ) 54 Response.Write( "Your reservation has been made." 55 + " Thank you." ); 56 57 // Web-service method returned false, so signal failure 58 else 59 Response.Write( "This seat is not available, " + 60 "please hit the back button on your browser " + 61 "and try again." ); 62 63 } // end method reserveButton_Click 64 65 } // end class TicketReservation 66 67 } // end namespace MakeReservation
55. TemperatureServer.asmx.cs 1 // Fig. 21.20: TemperatureServer.asmx.cs 2 // TemperatureServer Web Service that extracts weather 3 // information from a Web page. 4 5 using System; 6 using System.Collections; 7 using System.ComponentModel; 8 using System.Data; 9 using System.Diagnostics; 10 using System.Web; 11 using System.Web.Services; 12 using System.IO; 13 using System.Net; 14 15 namespace TemperatureWebService 16 { 17 [ WebService( Namespace = "http://www.deitel.com/csphtp1/ch21/" , 18 Description = "A Web service that provides information " + 19 "from the National Weather Service." ) ] 20 public class TemperatureServer : 21 System.Web.Services.WebService 22 { 23 // Visual Studio .NET generated code 24 25 [ WebMethod( EnableSession = true , Description = 26 "Method to read information from the weather service." ) ] 27 public void UpdateWeatherConditions() 28 { 29 // create WebClient to get access to Web page 30 WebClient myClient = new WebClient(); 31 ArrayList cityList = new ArrayList(); 32
56. TemperatureServer.asmx.cs 33 // get StreamReader for response so we can read page 34 StreamReader input = new StreamReader( 35 myClient.OpenRead( 36 "http://iwin.nws.noaa.gov/iwin/us/" + 37 "traveler.html" ) ); 38 39 string separator = "TAV12" ; 40 41 // locate first horizontal line on Web page 42 while ( !input.ReadLine().StartsWith( 43 separator ) ) ; // do nothing 44 45 // day format and night format 46 string dayFormat = 47 "CITY WEA HI/LO WEA " + 48 "HI/LO" ; 49 string nightFormat = 50 "CITY WEA LO/HI WEA " + 51 "LO/HI" ; 52 string inputLine = "" ; 53 54 // locate header that begins weather information 55 do 56 { 57 inputLine = input.ReadLine(); 58 } while ( !inputLine.Equals( dayFormat ) && 59 !inputLine.Equals( nightFormat ) ); 60 61 // get first city's data 62 inputLine = input.ReadLine(); 63
57. TemperatureServer.asmx.cs 64 while ( inputLine.Length > 28 ) 65 { 66 // create CityWeather object for city 67 CityWeather weather = new CityWeather( 68 inputLine.Substring( 0 , 16 ), 69 inputLine.Substring( 16 , 7 ), 70 inputLine.Substring( 23 , 7 ) ); 71 72 // add to List 73 cityList.Add( weather ); 74 75 // get next city's data 76 inputLine = input.ReadLine(); 77 } 78 79 // close connection to NWS server 80 input.Close(); 81 82 // add city list to user session 83 Session.Add( "cityList" , cityList ); 84 85 } // end UpdateWeatherConditions 86 87 // gets all city names 88 [ WebMethod( EnableSession = true , Description = 89 "Method to retrieve a list of cities." ) ] 90 public string [] Cities() 91 { 92 ArrayList cityList = ( ArrayList ) Session[ "cityList" ]; 93 string [] cities= new string [ cityList.Count ]; 94
58. TemperatureServer.asmx.cs 95 // retrieve names for cities 96 for ( int i = 0 ; i < cityList.Count; i++ ) 97 { 98 CityWeather weather = ( CityWeather ) cityList[ i ]; 99 100 cities[ i ] = weather.CityName; 101 } 102 103 return cities; 104 105 } // end method Cities 106 107 // gets all city descriptions 108 [ WebMethod( EnableSession = true , Description = "Method" + 109 " to retrieve weather descriptions for a " + 110 "list of cities." )] 111 public string [] Descriptions() 112 { 113 ArrayList cityList = ( ArrayList ) Session[ "cityList" ]; 114 string [] descriptions= new string [ cityList.Count ]; 115 116 // retrieve weather descriptions for all cities 117 for ( int i = 0 ; i < cityList.Count; i++ ) 118 { 119 CityWeather weather = ( CityWeather )cityList[ i ]; 120 121 descriptions[ i ] = weather.Description; 122 } 123 124 return descriptions; 125 126 } // end method Descriptions 127
59. TemperatureServer.asmx.cs 128 // obtains each city temperature 129 [ WebMethod( EnableSession = true , Description = "Method " + 130 "to retrieve the temperature for a list of cities." ) ] 131 public string [] Temperatures() 132 { 133 ArrayList cityList = ( ArrayList ) Session[ "cityList" ]; 134 string [] temperatures= new string [ cityList.Count ]; 135 136 // retrieve temperatures for all cities 137 for ( int i = 0 ; i < cityList.Count; i++ ) 138 { 139 CityWeather weather = ( CityWeather )cityList[ i ]; 140 temperatures[ i ] = weather.Temperature; 141 } 142 143 return temperatures; 144 145 } // end method Temperatures 146 147 } // end class TemperatureServer 148 149 } // end namespace TemperatureWebService
60. CityWeather.cs 1 // Fig. 21.21: CityWeather.cs 2 // Class representing the weather information for one city. 3 4 using System; 5 6 namespace TemperatureWebService 7 { 8 public class CityWeather 9 { 10 private string cityName; 11 private string temperature; 12 private string description; 13 14 public CityWeather( 15 string city, string information, string degrees ) 16 { 17 cityName = city; 18 description = information; 19 temperature = degrees; 20 } 21 22 // city name 23 public string CityName 24 { 25 get 26 { 27 return cityName; 28 } 29 } 30
61. CityWeather.cs 31 // city temperature 32 public string Temperature 33 { 34 get 35 { 36 return temperature; 37 } 38 } 39 40 // forecast description 41 public string Description 42 { 43 get 44 { 45 return description; 46 } 47 } 48 49 } // end class CityWeather 50 } // end namespace TemperatureWebService
62. Client.cs 1 // Fig. 21.22: Client.cs 2 // Class that displays weather information that it receives 3 // from a Web service. 4 5 using System; 6 using System.Drawing; 7 using System.Collections; 8 using System.ComponentModel; 9 using System.Windows.Forms; 10 using System.Net; 11 12 namespace TemperatureClient 13 { 14 public class Client : System.Windows.Forms.Form 15 { 16 private System.Windows.Forms.Label label1; 17 private System.Windows.Forms.Label label2; 18 private System.Windows.Forms.Label label3; 19 private System.Windows.Forms.Label label4; 20 private System.Windows.Forms.Label label5; 21 private System.Windows.Forms.Label label6; 22 private System.Windows.Forms.Label label7; 23 private System.Windows.Forms.Label label8; 24 private System.Windows.Forms.Label label9; 25 private System.Windows.Forms.Label label10; 26 private System.Windows.Forms.Label label11; 27 private System.Windows.Forms.Label label12; 28 private System.Windows.Forms.Label label13; 29 private System.Windows.Forms.Label label14; 30 private System.Windows.Forms.Label label15; 31 private System.Windows.Forms.Label label16; 32 private System.Windows.Forms.Label label17; 33 private System.Windows.Forms.Label label18; 34 private System.Windows.Forms.Label label19; 35 private System.Windows.Forms.Label label20;
70. Equation.cs 68 69 set 70 { 71 } 72 } 73 74 // left operand get and set property 75 public int Left 76 { 77 get 78 { 79 return left; 80 } 81 82 set 83 { 84 left = value ; 85 } 86 } 87 88 // right operand get and set property 89 public int Right 90 { 91 get 92 { 93 return right; 94 } 95 96 set 97 { 98 right = value ; 99 } 100 } 101
71. Equation.cs 102 // get and set property of result of applying 103 // operation to left and right operands 104 public int Result 105 { 106 get 107 { 108 return result; 109 } 110 111 set 112 { 113 result = value ; 114 } 115 } 116 117 // get and set property for operation 118 public string Operation 119 { 120 get 121 { 122 return operation; 123 } 124 125 set 126 { 127 operation = value ; 128 } 129 } 130 131 } // end class Equation
72. Generator.asmx.cs 1 // Fig. 21.24: Generator.asmx.cs 2 // Web Service to generate random equations based on a 3 // specified operation and difficulty level. 4 5 using System; 6 using System.Collections; 7 using System.ComponentModel; 8 using System.Data; 9 using System.Diagnostics; 10 using System.Web; 11 using System.Web.Services; 12 13 namespace EquationGenerator 14 { 15 [ WebService( Namespace = "http://www.deitel.com/csphtp1/ch21" , 16 Description = "A Web service that generates questions " + 17 "based on the specified mathematical operation and " + 18 "level of difficulty chosen." ) ] 19 public class Generator : System.Web.Services.WebService 20 { 21 22 // Visual Studio .NET generated code 23 24 [ WebMethod ( Description = 25 "Method that generates a random equation." ) ] 26 public Equation GenerateEquation( string operation, 27 int level ) 28 { 29 // find maximum and minimum number to be used 30 int maximum = ( int ) Math.Pow( 10 , level ), 31 minimum = ( int ) Math.Pow( 10 , level - 1 ); 32
73. Generator.asmx.cs 33 Random random = new Random(); 34 35 // create equation consisting of two random numbers 36 // between minimum and maximum parameters 37 Equation equation = new Equation( 38 random.Next( minimum, maximum ), 39 random.Next( minimum, maximum ), operation ); 40 41 return equation; 42 43 } // end method GenerateEquation 44 45 } // end class Generator 46 47 } // end namespace EquationGenerator
74. 21.8 User Defined Types in Web Services Fig. 21.25 Returning an object from a Web-service method. (Part 1) Create a subtraction exercise Make exercise of user skill level 2
75. 21.8 User Defined Types in Web Services Fig. 21.25 Returning an object from a Web-service method. (Part 2)