| Introduction | 1 |
| What Is This Book About? | 1 |
| Who Is This Book For? | 3 |
| What This Book Is Not | 3 |
| What This Book Is | 4 |
| What Do You Need To Use This Book? | 4 |
| Conventions | 4 |
| Customer Support and Feedback | 6 |
| Source Code and Updates | 6 |
| Errata | 6 |
| Technical Support | 6 |
| p2p.wrox.com | 7 |
| Chapter 1: Getting Started | 9 |
| Why ASP.NET? | 10 |
| A Note on Terminology | 10 |
| Is It a Bird? ... Is It a Plane? ... No, It's a Wapplisite! | 10 |
| ASP.NET Fundamentals | 11 |
| Event-Driven Applications | 11 |
| The ASP.NET Page as a Compiled Class | 13 |
| The ASP.NET Postback Architecture | 16 |
| ASP.NET Server Controls | 25 |
| Other Useful ASP.NET Features | 26 |
| Designing an Interactive Web Site | 28 |
| The Overall Site Design | 28 |
| Requirements Analysis | 28 |
| The Wrox Car Company | 29 |
| The Home Page | 32 |
| The Ingredients for the Home Page | 33 |
| The Car Model Details Page | 34 |
| The Color Options Section | 34 |
| The Engine Options Section | 36 |
| The Optional Extras Section | 37 |
| The Model Details Section | 38 |
| The Finance Options Section | 39 |
| The Compare Features Page | 40 |
| The Ingredients for the Compare Features Page | 40 |
| The Order Pages | 41 |
| Other "Peripheral" Pages | 41 |
| Is It All Actually Achievable? | 41 |
| Summary | 42 |
| Chapter 2: Browser Compatibility with ASP.NET Server Controls | 45 |
| Built-In Intelligence | 46 |
| A Test Application | 47 |
| Use a Selection of Browsers | 49 |
| Viewing the Test Pages | 49 |
| The Hyperlink Server Control | 51 |
| But Navigator Understands the Style Attribute! | 54 |
| The Calendar Control | 55 |
| Specifying Up-level or Down-Level Clients | 56 |
| The Definition of 'Up-level' and 'Down-level' | 58 |
| List Control Formatting and Templates | 59 |
| The Output from the DataList Control | 60 |
| Adding Templates to the DataList Control | 62 |
| More Complexity - the DataGrid Control | 64 |
| Specifying Column Information in a DataGrid Control | 65 |
| Formatting Within a TemplateColumn in a DataGrid Control | 67 |
| What If There's No Client-Side Script Support? | 68 |
| Example: a LinkButton in Amaya | 69 |
| Solving the 'No Script' Problem | 71 |
| When Scripting Is Supported but Disabled | 71 |
| The ASP.NET Validation Controls | 72 |
| The Validation Controls in Down-Level Clients | 74 |
| The ASP.NET Panel Control | 74 |
| The Panel Control in Down-Level Clients | 76 |
| Don't Get Caught Out by Output Caching | 77 |
| Caching by Browser Version | 78 |
| Caching by Client Target | 79 |
| Summary | 80 |
| Chapter 3: Laying the Foundations | 83 |
| Obtaining the Example Files | 84 |
| Installing the Wrox Car Company Site | 84 |
| Wrox Cars' Client-Side Technical Requirements | 85 |
| What 'Standards' Do We Support or Require? | 86 |
| ASP.NET Sessions | 87 |
| Requirements for Session Support | 87 |
| Maximizing Performance When Using Sessions | 90 |
| Client-Side Scripting | 91 |
| Users and User IDs in the Wrox Car Company Site | 91 |
| Checking for Sessions and Scripting Support | 92 |
| Client Capabilities and User ID Detection | 93 |
| The Code in default.aspx | 94 |
| The HTML and Content in default.aspx | 95 |
| The no-script.htm Page | 97 |
| Enabling and Disabling Client-side Scripting | 98 |
| The Detection Code in home.aspx | 99 |
| The no-sessions.htm Page | 100 |
| Cookie Based or Cookie-less Sessions? | 101 |
| Enabling and Disabling Cookie Support | 102 |
| Cross-Browser Compatibility Issues | 103 |
| Browsers for Testing Your Pages | 104 |
| Other User Agents | 104 |
| Solving Browser Compatibility Issues | 106 |
| Techniques for Maximizing Compatibility | 106 |
| Declaring and Linking to CSS Stylesheets | 107 |
| Font Styles, Types, and Sizes | 108 |
| ASP.NET Server Controls and the CssClass Property | 111 |
| Layout of Page Sections and Individual Elements | 114 |
| Script-Driven Animations and Other 'Actions' | 116 |
| Coping with Navigator/Communicator 4.x. | 119 |
| Making Sites Accessible to All Visitors | 119 |
| Why Provide Universal Accessibility? | 120 |
| A Summary of Techniques for Accessibility | 120 |
| Summary | 122 |
| Chapter 4: The Home Page | 125 |
| The Overall Page Structure | 126 |
| Creating the Page Structure | 128 |
| The HTML Table for the Outline Structure | 128 |
| Setting the Styles for the Page | 132 |
| Specifying the CSS Style Sheet | 132 |
| The Standard Style Sheet | 132 |
| The Netscape/Mozilla Stylesheet | 134 |
| Detecting the Client Type | 134 |
| Linking to the Correct Stylesheet | 136 |
| Providing Accessibility Navigational Aids | 137 |
| Implementing 'Skip To' Links | 138 |
| The Source Code for the 'Skip To' Links | 140 |
| Remember those 'title' and 'alt' Attributes | 141 |
| The Links to Other Pages | 142 |
| The ASP.NET Hyperlink Control | 144 |
| Setting the 'title' and 'alt' Attributes | 144 |
| The 'News and Special Offers' Section | 145 |
| The Data Access Code for the 'News' List | 145 |
| The GetNewsList Stored Procedure | 145 |
| The GetNewsListDR Function | 146 |
| Data Binding the Repeater Control | 147 |
| Choosing the Appropriate ASP.NET 'List' Control | 148 |
| The Static Section of the 'News' List | 149 |
| The ASP.NET Repeater Control for the 'News' List | 150 |
| Data Binding Syntax in a List Control Template | 151 |
| The List of Car Models | 153 |
| Choosing the Appropriate List Control | 153 |
| Changing the Behavior for Script-Enabled Clients | 154 |
| The Data Access Code for the 'Car Models' List | 154 |
| The GetModelList Stored Procedure | 155 |
| The GetModelListDR Function | 155 |
| Data Binding the DataGrid Control | 155 |
| The DataGrid Control for the 'Car Models' List | 156 |
| Specifying Styles and Templates | 157 |
| Specifying Column Information in a DataGrid Template | 157 |
| Handling the ItemDataBound Event for a DataGrid | 162 |
| Summary | 165 |
| Chapter 5: Banners, Footers, and E-Mail | 169 |
| About ASP.NET User Controls | 169 |
| Reusable Code and Content | 170 |
| Building a User Control | 171 |
| The Contents of a User Control | 172 |
| Using a User Control in an ASP.NET Page | 174 |
| Setting Properties | 174 |
| The Animated Page Banner | 175 |
| Building the Animated Banner Control | 175 |
| The Structure of the 'Page Banner' User Control | 176 |
| The ASP.NET Literal Control | 178 |
| The Properties of our User Control | 179 |
| The Page_Load Event Handler | 180 |
| The Animation Content for CSS-Enabled Clients | 182 |
| The Animation Content for Internet Explorer 4.x and Above | 185 |
| The Animation Content for Netscape 4.x Only | 187 |
| Using the Animated Banner Control | 189 |
| Setting the Banner Control Properties | 189 |
| The Page Footer Section | 190 |
| Dynamic Hyperlinks in the Footer | 191 |
| Building the Page Footer Control | 191 |
| The HtmlAnchor Control | 192 |
| The Code for the Page Footer Control | 193 |
| Using the Page Footer Control | 195 |
| Adding Users to the Mailing List | 195 |
| The Controls to Submit an E-Mail Address | 197 |
| ASP.NET Form Controls and the <form> Element | 198 |
| ASP.NET Validation Controls | 198 |
| The Validation Controls in the 'Home' Page | 201 |
| The ValidationSummary Control in the 'Home' Page | 202 |
| Online Server Controls Examples | 203 |
| The Code to Handle E-Mail Addresses | 204 |
| Using the Page.IsValid Property | 204 |
| The UpdateMailingList Function | 205 |
| The SendMail User Control | 207 |
| The SendEmailConfirmation Routine | 208 |
| Summary | 210 |
| Chapter 6: The Ancillary Pages | 213 |
| The Structure of the Ancillary Pages | 214 |
| The Overall Layout | 214 |
| 'Terms & Conditions' and 'Contact' Pages | 214 |
| The HTML Table for the Ancillary Pages Structure | 215 |
| The Code for the Ancillary Pages | 216 |
| The MainLink User Control | 218 |
| The Script Section | 220 |
| Using the MainLink Control | 220 |
| Choosing Static or Dynamic Content | 221 |
| Making Static Content Dynamic | 221 |
| Dynamic Content Without a Database | 222 |
| Making Dynamic Content Static | 223 |
| Generating Static Pages with ASP.NET | 223 |
| Using ASP.NET Caching to Expose 'Static' Pages | 224 |
| The 'Read News Item' Page | 225 |
| Inserting Dynamic Content into Pages | 227 |
| The HTML and Code for the 'Read News' Page | 228 |
| Getting the Content from the Data Store | 228 |
| Inserting the Content into the Page | 229 |
| Extracting Values from a DataReader | 231 |
| The 'Compare Models' Page | 233 |
| Accessibility Issues with Complex Images | 234 |
| Using a Long Description | 235 |
| Providing Alternative Content Formats | 237 |
| Building the 'Compare Models' Page | 238 |
| The 'Skip To' Links | 238 |
| The Main Page Structure Table | 238 |
| The Controls to Select the Comparison Type | 239 |
| The Controls to Display the Results of the Comparison | 241 |
| The Code To Make It All Work | 244 |
| Getting the Car and Engine Data | 250 |
| Generating the Comparison Results | 252 |
| Testing for Accessibility | 259 |
| Using a Text-Only Browser | 259 |
| Using an Aural Page Reader | 260 |
| Summary | 262 |
| Chapter 7: Creating Graphs and Charts | 265 |
| Dynamically Generated Graphics and Images | 266 |
| Performance and Caching | 267 |
| Generating Graphics on the Client | 267 |
| ASP.NET Caching for Images and Graphics | 267 |
| Writing Images to Disk Files | 268 |
| Using Dynamic Images in Web Pages | 268 |
| Alternative Elements for Inserting Images | 269 |
| Using Multiple Static Image Files | 269 |
| Passing Values to an Image Generation Page | 270 |
| The .NET Framework Drawing Classes | 271 |
| The System.Drawing Namespace | 271 |
| It's All Very Simple | 272 |
| Creating a Simple Pie Chart | 274 |
| Providing the Data Source | 274 |
| Creating the DataSet for the Pie Chart Example | 275 |
| The Pie Chart Example Page | 276 |
| Adding the Import Directives | 276 |
| The Page_Load Event Handler | 277 |
| Drawing Text on a Bitmap | 278 |
| Creating and Using Colors in Images | 280 |
| The Browser-Safe and Standard Colors | 283 |
| Our Generic Pie Chart Routine | 289 |
| Calculating the Position of the Main Chart Elements | 290 |
| Creating Rectangles and Drawing Shadows | 291 |
| Declaring More Variables and Totaling the Rows | 292 |
| Drawing the Pie Slices | 293 |
| Adding the Key and Caption | 294 |
| Completing the Loop | 295 |
| A Note About Saving a Bitmap | 295 |
| The Vehicle Comparison Charts | 296 |
| Getting the Values and Data for the Chart | 296 |
| Creating the SQL Statement | 297 |
| Drawing the Appropriate Chart | 298 |
| Drawing the Line Chart | 300 |
| Declaring the Variables We'll Need | 301 |
| Creating Arrow Caps for the Axes | 301 |
| Drawing the Y-Axis Values | 302 |
| Drawing the X-Axis Values | 303 |
| Drawing the Value Lines | 304 |
| Drawing the 'Key' Boxes and Descriptions | 306 |
| Drawing the Bar Chart | 307 |
| The Routine Parameters and Variable Declarations | 308 |
| Drawing the Axes and 'Key' Boxes | 308 |
| Calculating the X-Axis Values | 309 |
| Drawing the X-Axis Values | 311 |
| Drawing the Y-Axis Values | 311 |
| Summary | 314 |
| Chapter 8: Interactive Web Forms | 317 |
| Meeting the Design Requirements | 318 |
| The Original Design | 318 |
| Selecting a Color for the Vehicle | 318 |
| Selecting the Engine for the Vehicle | 319 |
| Selecting the Optional Extras for the Vehicle | 320 |
| Viewing the Standard Features of the Vehicle | 322 |
| Selecting a Finance Package for the Vehicle | 323 |
| Supporting 'No-Script' Clients | 324 |
| Supporting 'Text-Only' Clients | 325 |
| Supporting 'Page-Reader' Clients | 325 |
| Saving Quotations and Closing the Window | 326 |
| The Navigation Issue in Lynx | 327 |
| The 'Model Details' Page in Outline | 327 |
| Opening the 'Model Details' Page | 327 |
| Using the Postback Architecture | 328 |
| A Schematic of the Whole Process | 328 |
| What Happened to the Frames? | 330 |
| Implementing a 'Tabbed Dialog' | 331 |
| About the IE Web Controls | 331 |
| Coping Without Client-Side Scripting Support | 333 |
| Client-Side Versus Server-Side Page Updates | 334 |
| Saving Quotations and Orders | 336 |
| The Structure of the Model Details Page | 337 |
| Importing and Registering the IE Web Controls | 337 |
| The HTML Section of the Page | 338 |
| The Model Description, Price, and Image | 339 |
| The 'Tabbed Dialog' Section | 340 |
| The TabStrip Control | 341 |
| The MultiPage Control | 342 |
| Linking the TabStrip and MultiPage Controls | 343 |
| What Output Do the TabStrip and MultiPage Controls Create? | 344 |
| The Information and Error Messages Label | 347 |
| The Instructions, Save, and Close Buttons | 347 |
| Summary | 351 |
| Chapter 9: The Interactive Model Details | 353 |
| The Data for the 'Model Details' Page | 354 |
| The Vehicle Details Database Tables | 354 |
| But in the Real World... | 355 |
| The Stored Procedures for the 'Model Details' Page | 355 |
| Extracting the Vehicle Details | 355 |
| Extracting the List of Available Colors | 356 |
| Extracting the List of Available Extras | 357 |
| The Finance PMT Values Table | 357 |
| Using global.asax to Handle Application-Level Events | 357 |
| Calculating the Payment Amounts | 360 |
| Writing Status Messages to the Event Log and a Text Log File | 361 |
| Running Code when an Application Error Occurs | 363 |
| The GetFinancePMTRates Stored Procedure | 363 |
| Fetching and Storing the Data for the Page | 363 |
| Accessing the Database and Filling the DataSet | 364 |
| The Code in the 'Model Details' Page | 366 |
| The Page_Load Event Handler | 367 |
| Checking for an Active Session | 368 |
| Collecting the DataSet | 369 |
| Collecting the Price and Finance Terms | 369 |
| The 'Model Details' 'Tab' Pages in Detail | 371 |
| The Color Selection Section | 372 |
| Displaying the Color Blocks | 373 |
| Where Do the Colors Come From? | 374 |
| Populating the Page Heading and Colors Section | 375 |
| Reacting to Events in the Colors Section | 376 |
| The Engine Selection Section | 377 |
| The Engine Details (DataGrid) Table | 378 |
| Populating the Engine Section | 379 |
| Reacting to Events in the Engine Section | 379 |
| The 'Optional Extras' Selection Section | 380 |
| Populating the 'Extras' Section | 381 |
| Reacting to Events in the 'Extras' Section | 381 |
| The 'Standard Features' (Details) Section | 381 |
| The IE Web Controls TreeView Control | 382 |
| The HTML for the 'Details' Section | 384 |
| Populating the 'Details' Section | 386 |
| Reacting to Events in the 'Details' Section | 388 |
| The Finance Package Selection Section | 389 |
| Enabling and Disabling Buttons and Other Controls | 391 |
| Populating the 'Finance' Section | 391 |
| Reacting to Events in the Finance Section | 391 |
| Summary | 393 |
| Chapter 10: Car Prices and Quotations | 395 |
| Calculating the Price of the Vehicle | 395 |
| The CalculateCarPrice Routine | 396 |
| Clearing Any Existing Finance Terms | 397 |
| Getting the Price for the Current Car/Engine Combination | 397 |
| Adding the Extra Cost for a Metallic Color | 399 |
| Adding the Cost of Optional Extras | 401 |
| Storing the Total Price in the Prices Array | 402 |
| Calculating the Finance Terms | 403 |
| The ShowFinanceTerms Routine | 404 |
| Handling an Error in the Calculation | 405 |
| The CalculateFinanceTerms Function | 405 |
| The GetNumberPayments Function | 409 |
| The ClearFinanceTerms Routine | 411 |
| Saving the Configuration as a Quotation | 412 |
| The Saved Quotes and Orders Tables | 412 |
| Updating the Data within a Transaction | 413 |
| Saving a Quotation | 414 |
| The Stored Procedures for the SaveCarDetails Routine | 414 |
| The SaveCarDetails Routine | 415 |
| The No-Script Version of the Page | 422 |
| Avoiding the TabStrip and MultiPage Controls | 423 |
| Custom Multi-Page Effects | 424 |
| Our Solution - Use Hyperlinks and Horizontal Rules | 425 |
| Working Around the Lack of AutoPostBack | 425 |
| Replacing the TreeView Control | 426 |
| The ASP.NET Xml Web Forms Control | 426 |
| Managing Without the setOptionButtons Function | 429 |
| Managing Without the mainWindowPage Function | 430 |
| Managing Without a Close Button | 431 |
| Summary | 431 |
| Chapter 11: The Login and Register Page | 435 |
| Web Site Users and Identities | 436 |
| Authentication | 436 |
| Authorization | 437 |
| Impersonation | 438 |
| Permissions for the Anonymous Accounts | 439 |
| ASP.NET Authentication Methods | 439 |
| Windows Authentication | 440 |
| Passport Authentication | 441 |
| Forms Authentication | 441 |
| Specifying Users and Groups | 444 |
| Avoiding Nested ASP.NET Applications | 445 |
| Wrox Cars Login and Register Process | 446 |
| The Root Folder web.config File | 447 |
| The "secure" Sub-folder web.config File | 447 |
| Authentication for Cookie-Less Clients | 448 |
| Custom Authentication and Authorization Techniques | 448 |
| The Process Step-By-Step | 450 |
| Why Use Anonymous User IDs? | 452 |
| Why Use a Combined Login and Register Page? | 453 |
| The Login and Register Page | 454 |
| The HTML Page Declarations | 454 |
| The ASP.NET Validation Controls | 455 |
| The 'Login' Section of the Page | 455 |
| The ValidationSummary Control | 459 |
| The 'Register' Section of the Page | 459 |
| The Client-Side Script Functions | 462 |
| Disabling the Submit Buttons | 463 |
| The ASP.NET Server-Side Code | 464 |
| The Page_Load Event Handler | 464 |
| The DoLogin Event Handler | 466 |
| The DoRegister Event Handler | 475 |
| Summary | 479 |
| Chapter 12: Quotations and Orders | 481 |
| Binding List Controls to Related Data | 481 |
| Binding to a Single Data Source | 482 |
| Binding Nested List Controls | 482 |
| An Example of Nested Bound Controls | 483 |
| Binding to Hierarchical Data | 492 |
| Hierarchical Binding in the 'My Cars' Page | 493 |
| Building the 'My Cars' Page | 494 |
| The HTML for the 'My Cars' Page | 495 |
| The Name and Address Details, and Log Off Button | 496 |
| The Messages Label | 497 |
| The Caption for the Quotations Section | 497 |
| The List Control for the Quotations Section | 498 |
| The 'Orders' Section | 501 |
| The Code for the 'My Cars' Page | 502 |
| Generating the DataSet of User Details | 502 |
| The Page_Load Event Handler | 505 |
| Displaying Details of the User | 507 |
| Displaying Details of the User's Vehicles | 508 |
| The ItemDataBound Event Handlers | 509 |
| Logging Out of the Application | 510 |
| Placing an Order | 511 |
| Sending Order Confirmation E-mail Messages | 514 |
| Summary | 518 |
| Index | 521 |