Developing XML Web Services and Server Components with Visual Basic .NET and the .NET Framework
Mike Gunderloy
MCAD/MCSD Developing XML Web Services and Server Components with Visual Basic .NET and the .NET Framework (Exam 70-310)
Publisher Paul Boger
Copyright 2004 by Que Certification All rights reserved. No part of this book shall be reproduced, stored in a retrieval system, or transmitted by any means, electronic, mechanical, photocopying, recording, or otherwise, without written permission from the publisher. No patent liability is assumed with respect to the use of the information contained herein. Although every precaution has been taken in the preparation of this book, the publisher and author assume no responsibility for errors or omissions. Nor is any liability assumed for damages resulting from the use of the information contained herein. International Standard Book Number: 0-7897-2900-8
Executive Editor Jeff Riley
Development Editors Ginny Bess Munroe Grant Munroe
Managing Editor Charlotte Clapp
Library of Congress Catalog Card Number: 2003100976 Printed in the United States of America
Project Editor Tricia Liebig
First Printing: July 2003 06
05
04
03
4
3
2
1
Que Publishing offers excellent discounts on this book when ordered in quantity for bulk purchases or special sales. For more information, please contact U.S. Corporate and Government Sales 1-800-382-3419
Copy Editor Bart Reed
Indexer John Sleeva
[email protected] For sales outside of the U.S., please contact International Sales 1-317-581-3793
[email protected] Proofreader Juli Cook
Technical Editors Ken Cox Steve Heckler
Trademarks All terms mentioned in this book that are known to be trademarks or service marks have been appropriately capitalized. Que Certification cannot attest to the accuracy of this information. Use of a term in this book should not be regarded as affecting the validity of any trademark or service mark.
Team Coordinator Pamalee Nelson
Multimedia Developer Dan Scherf
Warning and Disclaimer Every effort has been made to make this book as complete and as accurate as possible, but no warranty or fitness is implied. The information provided is on an “as is” basis. The authors and the publisher shall have neither liability nor responsibility to any person or entity with respect to any loss or damages arising from the information contained in this book or from the use of the CD or programs accompanying it.
Page Layout Kelly Maish
Graphics Tammy Graham
Que Certification • 201 West 103rd Street • Indianapolis, Indiana 46290
A Note from Series Editor Ed Tittel You know better than to trust your certification preparation to just anybody. That’s why you, and more than two million others, have purchased an Exam Cram book. As Series Editor for the new and improved Exam Cram 2 series, I have worked with the staff at Que Certification to ensure you won’t be disappointed. That’s why we’ve taken the world’s best-selling certification product—a finalist for “Best Study Guide” in a CertCities reader poll in 2002—and made it even better. As a “Favorite Study Guide Author” finalist in a 2002 poll of CertCities readers, I know the value of good books. You’ll be impressed with Que Certification’s stringent review process, which ensures the books are high-quality, relevant, and technically accurate. Rest assured that at least a dozen industry experts—including the panel of certification experts at CramSession—have reviewed this material, helping us deliver an excellent solution to your exam preparation needs. We’ve also added a preview edition of PrepLogic’s powerful, full-featured test engine, which is trusted by certification students throughout the world. As a 20-year-plus veteran of the computing industry and the original creator and editor of the Exam Cram series, I’ve brought my IT experience to bear on these books. During my tenure at Novell from 1989 to 1994, I worked with and around its excellent education and certification department. This experience helped push my writing and teaching activities heavily in the certification direction. Since then, I’ve worked on more than 70 certification-related books, and I write about certification topics for numerous Web sites and for Certification magazine. In 1996, while studying for various MCP exams, I became frustrated with the huge, unwieldy study guides that were the only preparation tools available. As an experienced IT professional and former instructor, I wanted “nothing but the facts” necessary to prepare for the exams. From this impetus, Exam Cram emerged in 1997. It quickly became the best-selling computer book series since “…For Dummies,” and the best-selling certification book series ever. By maintaining an intense focus on subject matter, tracking errata and updates quickly, and following the certification market closely, Exam Cram was able to establish the dominant position in cert prep books. You will not be disappointed in your decision to purchase this book. If you are, please contact me at
[email protected]. All suggestions, ideas, input, or constructive criticism are welcome!
Need More In-Depth Study? Get a Training Guide at 40% Savings!! MCAD/MCSD Developing XML Web Services and Server Components with Visual Basic .NET and the .NET Framework Exam 70-310 Training Guide Mike Gunderloy ISBN 0-7897-2820-6 $49.99 US/$77.99 CAN/£36.50 Net UK
Your cost is only $29.99 US! Free shipping for US orders only.
Have you discovered that you need more in-depth study before taking that exam? Check out the Training Guide series, also from Que Certification. These comprehensive study guides get you up-to-speed on the information tested in the exam, as well as provide test-taking tips and advice for exam day. Inside you’ll find • Study and Exam Tips section at the start of the book • Exam objectives highlighted in every chapter • Step-by-step exercises for hands-on practice • Final review with Fast Facts and a Practice Exam • CD of PrepLogic Practice Tests for complete evaluation of your knowledge
Get 40% off your next Training Guide purchase!
Here’s what to do: 1) Visit www.quepublishing.com 2) Select the Training Guide of your choice 3) Proceed to checkout 4) Enter coupon code TGUIDE321 when prompted Offer good on purchase of one Training Guide through December 31, 2003.
www.examcram.com
For Princess and Max, eternally faithful. ❧
About the Author
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Mike Gunderloy pursued his first Microsoft certification the year the program was introduced, and he has earned the MCP, MCT, MCSE, MCDBA, MCAD, and MCSD credentials in the decade since. As lead developer for Lark Group, Inc., Mike has worked with small businesses, nonprofit organizations, and Fortune 500 corporations alike, as well as trained many other developers in the use of Microsoft products. He got hooked on computers when you still had to build your own out of parts and is still passionately interested in cutting-edge software technology. As a long-time member of the editorial staff of MCP Magazine, Mike has remained in close touch with the certification community. Mike lives on a farm in eastern Washington state, along with his wife and children and an ever-changing array of horses, sheep, llamas, geese, turkeys, chickens, ducks, peacocks, cats, dogs, and guinea fowl. When he’s not busy testing and writing about software, Mike can usually be found in his garden or greenhouse, trying to persuade recalcitrant vegetables to grow, or out on the land, trying to persuade noxious weeds to stop growing. You can reach Mike at
[email protected] or www.larkware.com.
About the Technical Editors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Ken Cox is a technical writer and Web applications programmer in Toronto, specializing in .NET technologies. For the past six years, Microsoft has selected him as a Most Valuable Professional (MVP) for ASP/ASP.NET. Ken is co-author of several books, including Inside ASP.NET (New Riders), Teach Yourself Object-Oriented Programming with Visual Basic .NET in 21 Days (Sams), and .NET Mobile Web Developer’s Guide (Syngress). His software reviews and articles appear frequently in Visual Studio Magazine. Ken has a bachelor’s degree in Radio and Television Arts and a college certificate in Technical Communication. In a previous life he was a broadcast journalist in Toronto and Quebec City. Steve Heckler is president of Accelebrate, an IT training and programming firm based in Atlanta. An avid ASP.NET, Java, and ColdFusion developer and trainer, Steve served more than six years as a senior manager and instructor at a leading East Coast IT training firm prior to founding Accelebrate. He holds bachelors and masters degrees from Stanford University.
Acknowledgments
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
This is the spot where the author traditionally explains that books don’t exist in a vacuum; without a good editorial staff, all the writing in the world won’t add up to a book. Well, who am I to break with tradition? Thanks to Jeff Riley for getting me into this project, and to Ginny Bess Munroe, Grant Munroe, Tricia Liebig, Bart Reed, and the rest of the editorial team for turning it into a book. And while I’m being traditional, yes, all of the errors in this book are my responsibility alone. In addition to the editorial staff, I owe thanks to the production staff for actually getting this stuff ready to print. So thanks to Juli Cook, John Sleeva, Tammy Graham, and Kelly Maish for somehow turning the final manuscript from a mass of Word documents and TIF images into a real printed book. I’ve been working with Microsoft software and certifications for over a decade now, which makes it impossible to even mention everyone who has contributed to my understanding. But high on any such list must be my former business partners Steve White, Ken Getz, Mary Chipman, and Brian Randell, as well as fellow MCP Magazine editors Dian Schaffhauser, Keith Ward, Michael Domingo, Becky Nagel, and Kris McCarthy. Amit Kalani was instrumental in shaping my view of remoting and serviced components, and also developed the practice exams for this book. I’ve also benefited from the dozens of developers now maintaining weblogs who spend their time sharing information with their peers, as well as those who contribute to various newsgroups and mailing lists. So thanks to the great mass of active developers who believe that sharing knowledge is a good thing. When I get away from the computer, I also have supportive people in my real life. My parents have always encouraged my writing, and my two wonderful kids, Adam and Kayla, at least put up with it (although they would rather hunt crocodiles and pull on my beard, respectively). And last on the list but first in importance is my dear wife, Dana, who supplies endless quantities of help, inspiration, and love to keep me going.
Contents at a Glance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Introduction
xxi
Self-Assessment
xxxi
Chapter 1
Microsoft Certification Exams
1
Chapter 2
Creating and Manipulating DataSets
Chapter 3
Accessing and Manipulating XML Data
Chapter 4
.NET Remoting
Chapter 5
Basic Web Services
Chapter 6
Advanced Web Services
Chapter 7
Windows Services
Chapter 8
Component Services
Chapter 9
Calling Unmanaged Code
23
97 123 141
167 187 217
Chapter 10
Testing and Debugging
235
Chapter 11
Deployment
Chapter 12
Security Issues
Chapter 13
Practice Exam #1
Chapter 14
Answer Key for Practice Exam #1
Chapter 15
Practice Exam #2
Chapter 16
Answer Key for Practice Exam #2
Appendix A
ADO.NET Basics
Appendix B
XML Standards and Syntax
265 289 317 349
369
423 443
403
57
Appendix C
What’s on the CD
Appendix D
Using PrepLogic Practice Tests, Preview Edition Software 451 Glossary Index
459
467
449
Table of Contents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Introduction .....................................................................xxi Self-Assessment ..............................................................xxxi Chapter 1 Microsoft Certification Exams .................................................1 Assessing Exam-Readiness 2 What to Expect at the Testing Center 3 Exam Layout and Design 4 Multiple-Choice Question Format 5 Build-List-and-Reorder Question Format 6 Create-a-Tree Question Format 8 Drag-and-Connect Question Format 10 Select-and-Place Question Format 11 Hot Area 12 Microsoft’s Testing Formats 13 Strategies for Different Testing Formats 15 Case Study Exam Strategy 15 Fixed-Length and Short-Form Exam Strategy Adaptive Exam Strategy 18 Question-Handling Strategies 19 Mastering the Inner Game 20 Additional Resources 20
16
Chapter 2 Creating and Manipulating DataSets .......................................23 Manipulating a DataSet Schema 24 Creating a DataSet Schema 24 Elements and Attributes 25 Using Server Explorer with the XML Designer Manipulating DataSet Relationships 28 Adding Keys to a DataSet Schema 29 One-to-Many Relationships 29 Nested Relationships 30
27
xii
Table . . . .of. Contents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Creating and Using Strongly Typed DataSets 31 Using the Component Designer to Create a Strongly Typed DataSet 31 Creating a Strongly Typed DataSet from a DataSet Schema 32 Using a Strongly Typed DataSet 33 Accessing and Manipulating SQL Server Data 33 Using Ad Hoc Queries 34 Using Stored Procedures 45 Exam Prep Questions 50 Need to Know More? 56
Chapter 3 Accessing and Manipulating XML Data ....................................57 Accessing an XML File 58 Understanding the DOM 58 Using an XmlReader Object 59 The XMLNode Class 62 The XmlDocument Class 63 The XmlDataDocument Class 65 Understanding XPath 68 The XPath Language 68 Using the XPathNavigator Class 71 Generating and Using XSD Schemas 76 Generating an XSD Schema 76 Using an XSD Schema 78 Using XML with SQL Server 81 Generating XML with SQL Statements 81 Using ExecuteXmlReader 85 Updating SQL Server Data by Using XML 86 Exam Prep Questions 89 Need to Know More? 95
Chapter 4 .NET Remoting .................................................................97 Developing Distributed Applications Using the .NET Framework 98 .NET Remoting Architecture 98 Object Marshalling 100 Channels 101 Formatters 101 The Relationship Between Channels and Formatters
101
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Table . . .of. Contents . . . . .
Remote Object Activation 102 Lifetime Leases 103 Applying .NET Remoting 104 Creating a Remotable Class 104 Creating a Server-Activated Object 105 Creating a Client-Activated Object 108 Using Configuration Files to Configure the Remoting Framework 110 Using IIS As an Activation Agent 112 Exam Prep Questions 115 Need to Know More? 121
Chapter 5 Basic Web Services ..........................................................123 Understanding Web Services 124 SOAP 124 Disco and UDDI 125 WSDL 125 Invoking Your First Web Service 125 Calling a Web Service Asynchronously 126 Creating Web Services 127 Creating a Web Service Project 127 Testing the Web Service Project 128 Customizing the WebMethod Attribute 129 Using Web Services 129 Discovering Web Services with Disco and UDDI 130 Using the Web Services Discovery Tool (disco.exe) 130 Creating Proxy Classes with the Web Services Description Language Tool (wsdl.exe) 131 Using Web References 132 Exam Prep Questions 134 Need to Know More? 139
Chapter 6 Advanced Web Services ....................................................141 Creating and Using SOAP Extensions 142 Writing a SOAP Extension 143 Testing the SOAP Extension 148 Creating Asynchronous Web Methods 149 Using a Callback Delegate 150 Using the WaitHandle Object 150
xiii
xiv
Table . . . .of. Contents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Controlling XML Wire Format 152 Using Literal Parameter Formatting 153 Using Encoded Parameter Formatting 155 Using RPC-Style Body Formatting 156 Wrapped and Bare Parameters 158 Using the XmlElement Attribute 159 Exam Prep Questions 160 Need to Know More? 165
Chapter 7 Windows Services ...........................................................167 Understanding Windows Services 168 Architecture of Windows Services 168 .NET Framework Support for Windows Services 169 Creating a Windows Service Application 169 Understanding How the SCM Interacts with a Windows Service 170 Creating a Windows Service Application 171 Installing a Windows Service 173 The ServiceProcessInstaller and the ServiceInstaller Classes 173 Adding Installer Classes to a Windows Service Project 175 Using installutil.exe to Install a Windows Service Application 175 Using Tools to Monitor and Control a Windows Service 176 Using the Services MMC Snap-In 176 Using Visual Studio .NET Server Explorer 177 Using the NET Utility (net.exe) 177 Using the Service Control Utility (sc.exe) 178 Controlling a Windows Service 178 Exam Prep Questions 181 Need to Know More? 186
Chapter 8 Component Services .........................................................187 Features of COM+ 188 Exposing .NET Components to COM/COM+ 189 Calling a .NET Component from COM/COM+ 189 Exporting .NET Components As COM Type Libraries Architecture of Component Services 190 Serviced Components 191 Declarative Programming Model 191
190
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Table . . .of. Contents . . . . .
COM+ Applications 193 COM+ Catalog 194 Serviced Component Activation 194 Creating and Consuming a Serviced Component 196 Creating a Serviced Component 196 Consuming a Serviced Component 198 Understanding and Using Enterprise Services 201 Object Pooling 201 Just-in-Time Activation 203 Automatic Transaction Processing 205 Queued Components 208 Exam Prep Questions 210 Need to Know More? 215
Chapter 9 Calling Unmanaged Code ...................................................217 Using COM Components 218 Understanding Runtime Callable Wrappers 219 Registering a COM DLL 220 Using the Type Library Importer Tool (tlbimp.exe) Using COM Components Directly 222 Using Platform Invoke 223 Exam Prep Questions 227 Need to Know More? 233
220
Chapter 10 Testing and Debugging ......................................................235 Testing 236 Tracing 237 Using Trace and Debug to Display Information 238 Trace Listeners 238 Trace Switches 239 Conditional Compilation 241 ASP.NET Tracing 242 Debugging 247 Setting Breakpoints and Stepping Through Program Execution 247 Analyzing Program State to Resolve Errors 248 Debugging When an Exception Occurs 249 Debugging a Running Process 250 Debugging a Remote Process 251 Debugging the Code in DLL Files 252
xv
xvi
Table . . . .of. Contents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Debugging Client-Side Scripts 252 Debugging a Windows Service 253 Debugging a Serviced Component 253 Debugging a .NET Remoting Object 254 Debugging an XML Web Service 255 Working with Event Logs 255 Working with Performance Counters 257 Exam Prep Questions 259 Need to Know More? 263
Chapter 11 Deployment ...................................................................265 Deploying Private Assemblies 266 Binding Policy for Privately Deployed Assemblies 266 How the CLR Binds to a Privately Deployed Assembly 267 Using the .NET Framework Configuration Tool to Specify Additional Probing Locations 269 Deploying Shared Assemblies 270 Assigning a Strong Name to an Assembly 270 Delay Signing an Assembly 272 Adding an Assembly to the GAC 272 Binding Policy for Shared Assemblies 273 How the CLR Binds to a Shared Assembly 274 Packaging a .NET Application for Deployment 274 Packaging an Application for Deployment by Copying the Files 274 Packaging an Application for Deployment Using Microsoft Windows Installer 275 Creating a Setup Project 276 Customizing Visual Studio .NET Setup and Deployment Projects 278 Deploying Server Applications 279 Deploying a Web Service 279 Deploying Windows Services 280 Deploying a Serviced Component 280 Deploying a .NET Remoting Object 281 Exam Prep Questions 283 Need to Know More? 288
Chapter 12 Security Issues ...............................................................289 Configuring Security 290 Understanding Code Access Security
290
xvii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Table . . .of. Contents . . . . .
Configuring Authentication 297 No Authentication 298 IIS and ASP.NET Authentication 298 Authentication Providers 299 Configuring IIS Authentication 300 Passport Authentication 300 Forms Authentication 301 Configuring Authorization 301 Implementing Impersonation 302 Security for Windows Services 302 Security for Web Services 304 Platform and Application Security 304 Configuring Web Services for Security 306 Remoting Security 307 Enterprise Services Security 308 Exam Prep Questions 310 Need to Know More? 315
Chapter 13 Practice Exam #1 .............................................................317 How to Take the Practice Exams Exam-taking Tips 318 Practice Exam 319
317
Chapter 14 Answer Key for Practice Exam #1 .........................................349 Answer Key 349 Detailed Answers 350
Chapter 15 Practice Exam #2 .............................................................369 Chapter 16 Answer Key for Practice Exam #2 ..........................................403 Answer Key 403 Detailed Answers 404
Appendix A ADO.NET Basics ..............................................................423 ADO.NET Architecture 423 The ADO.NET Object Model 424 Data Providers and Their Objects The DataSet Classes 427
424
xviii Table of Contents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Using DataSets 429 Populating a DataSet from a Database 430 Moving Around in DataSets and Retrieving Data DataSets with Multiple Tables 432 Editing Data with ADO.NET 437 Updating Data 437 Adding Data 438 Deleting Data 439 Need to Know More? 441
431
Appendix B XML Standards and Syntax .................................................443 Syntax of an XML Document 443 XML Declaration 444 XML Comments 444 XML Elements 445 XML Attributes 445 XML Naming Convention 446 Handling Special Characters in XML Data XML Namespaces 447 Need to Know More? 448
446
Appendix C What’s on the CD-ROM ......................................................449 PrepLogic Practice Tests, Preview Edition
449
Appendix D Using PrepLogic Practice Tests, Preview Edition Software ...........451 Exam Simulation 451 Question Quality 452 Interface Design 452 Effective Learning Environment 452 Software Requirements 452 Installing PrepLogic Practice Tests, Preview Edition 453 Removing PrepLogic Practice Tests, Preview Edition from Your Computer 453 Using PrepLogic Practice Tests, Preview Edition 453 Starting a Practice Test Mode Session 454 Starting a Flash Review Mode Session 455 Standard PrepLogic Practice Tests, Preview Edition Options 455
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Table . . .of. Contents . . . . .
Time Remaining 456 Your Examination Score Report 456 Reviewing Your Exam 456 Get More Exams 456 Contacting PrepLogic 457 Customer Service 457 Product Suggestions and Comments 457 License Agreement 457
Glossary .......................................................................459 Index ............................................................................467
xix
We Want to Hear from You!
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
As the reader of this book, you are our most important critic and commentator. We value your opinion and want to know what we’re doing right, what we could do better, what areas you’d like to see us publish in, and any other words of wisdom you’re willing to pass our way. As an executive editor for Que Certification, I welcome your comments. You can email or write me directly to let me know what you did or didn’t like about this book—as well as what we can do to make our books better. Please note that I cannot help you with technical problems related to the topic of this book. We do have a User Services group, however, where I will forward specific technical questions related to the book. When you write, please be sure to include this book’s title and author as well as your name, email address, and phone number. I will carefully review your comments and share them with the author and editors who worked on the book. Email:
[email protected] Mail: Jeff Riley Executive Editor Que Publishing 800 East 96th Street Indianapolis, IN 46240 USA For more information about this book or another Que title, visit our Web site at www.quepublishing.com. Type the ISBN (excluding hyphens) or the title of a book in the Search field to find the page you’re looking for. For information about the Exam Cram 2 series, visit www.examcram2.com.
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Welcome to Microsoft’s 70-310 Exam Cram 2! Whether this is your first or your fifteenth Exam Cram 2 series book, you’ll find information here that will help ensure your success as you pursue knowledge, experience, and certification. This Introduction explains Microsoft’s certification programs in general and talks about how the Exam Cram 2 series can help you prepare for Microsoft’s Certified Application Developer and Certified Solution Developer exams. Chapters 1 through 12 are designed to remind you of everything you’ll need to know in order to take—and pass—the Developing XML Web Services and Server Components with Microsoft Visual Basic .NET and the Microsoft .NET Framework (70-310) Microsoft MCAD/MCSD certification exam. Appendixes A and B provide quick references on ADO.NET and XML, respectively. The two sample tests (Chapters 13 and 15) at the end of the book should give you a reasonably accurate assessment of your knowledge—and, yes, I’ve provided the answers and explanations to the sample tests’ questions (Chapters 14 and 16). Read the book and understand the material, and you’ll stand a very good chance of passing the test. Exam Cram 2 books help you understand and appreciate the subjects and materials you need to pass Microsoft certification exams. Exam Cram 2 books are aimed strictly at test preparation and review. They do not teach you everything you need to know about a topic. Instead, I’ll present and dissect the questions and problems I’ve found that you’re likely to encounter on a test. I’ve worked to bring together as much information as possible about Microsoft certification exams. Nevertheless, to completely prepare yourself for any Microsoft test, I recommend that you begin by taking the Self-Assessment included in this book, immediately following this introduction. The Self-Assessment tool will help you evaluate your knowledge base against the requirements for a Microsoft Certified Application Developer (MCAD) or Microsoft Certified Solution Developer (MCSD) under both ideal and real circumstances. Based on what you learn from the Self-Assessment, you might decide to begin your studies with some classroom training, some practice with Visual
xxii Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Basic .NET, or some background reading. On the other hand, you might decide to pick up and read one of the many study guides available from Microsoft or third-party vendors on certain topics, including the awardwinning MCAD Training Guide series from Que Publishing. I also recommend that you supplement your study program with visits to www.examcram2.com to receive additional practice questions, get advice, and track the MCAD and MCSD program. I also strongly recommend that you install, configure, and play around with the software you’ll be tested on, because nothing beats hands-on experience and familiarity when it comes to understanding the questions you’re likely to encounter on a certification test. Book learning is essential, but without a doubt, hands-on experience is the best teacher of all! To help you work with the product, I’ve arranged to include all the source code from Que’s MCAD 70-310 Training Guide on the CD-ROM in this book. This provides you an opportunity to read, understand, and extend a lot of additional code that demonstrates various concepts related to the 70-310 exam objectives. The CD-ROM also contains the PrepLogic Practice Tests, Preview Edition examsimulation software. The Preview Edition exhibits most of the full functionality of the Premium Edition but offers questions sufficient for only one practice exam. To get the complete set of practice questions and exam functionality, visit www.preplogic.com.
Taking a Certification Exam After you’ve prepared for your exam, you need to register with a testing center. Each computer-based MCP exam costs $125, and if you don’t pass, you can retest for an additional $125 for each additional try. In the United States and Canada, tests are administered by Prometric and by VUE. Here’s how you can contact them: ➤ Prometric—You can sign up for a test through the company’s Web site at www.prometric.com.
Within the United States and Canada, you can register by phone at 800-755-3926. If you live outside this region, you should check the Prometric Web site for the appropriate phone number.
➤ VUE—You can sign up for a test or get the phone numbers for local test-
ing centers through the Web at www.vue.com/ms. To sign up for a test, you must possess a valid credit card or contact either Prometric or VUE for mailing instructions to send a check (in the United States). Only when payment is verified or your check has cleared can you actually register for the test.
xxiii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Introduction . . . . . . .
To schedule an exam, you need to call the number or visit either of the Web pages at least one day in advance. To cancel or reschedule an exam, you must call before 7 p.m. Pacific standard time the day before the scheduled test time (otherwise, you might be charged, even if you don’t show up to take the test). When you want to schedule a test, you should have the following information ready: ➤ Your name, organization, and mailing address. ➤ Your Microsoft test ID. (Inside the United States, this usually means your
Social Security number; citizens of other nations should call ahead to find out what type of identification number is required to register for a test.) ➤ The name and number of the exam you want to take. ➤ A method of payment. (As mentioned previously, a credit card is the most
convenient method, but alternate means can be arranged in advance, if necessary.) After you sign up for a test, you are told when and where the test is scheduled. You should try to arrive at least 15 minutes early. You must supply two forms of identification—one of which must be a photo ID—and sign a nondisclosure agreement to be admitted into the testing room. All Microsoft exams are completely closed book. In fact, you are not permitted to take anything with you into the testing area, but you are given a blank sheet of paper and a pen (or in some cases an erasable plastic sheet and an erasable pen). I suggest that you immediately write down on that sheet of paper all the information you’ve memorized for the test. In Exam Cram 2 books, this information appears on a tear-out sheet inside the front cover of each book. You are given some time to compose yourself, record this information, and take a sample orientation exam before you begin the real thing. I suggest that you take the orientation test before taking your first exam, but because all the certification exams are more or less identical in layout, behavior, and controls, you probably don’t need to do this more than once. When you complete a Microsoft certification exam, the software tells you immediately whether you’ve passed or failed. If you need to retake an exam, you have to schedule a new test with Prometric or VUE and pay another $125. The first time you fail a test, you can retake the test as soon as the next day. However, if you fail a second time, you must wait 14 days before retaking that test. The 14-day waiting period remains in effect for all retakes after the second failure.
xxiv Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Tracking MCP Status As soon as you pass any Microsoft exam, you attain MCP status. Microsoft generates transcripts that indicate which exams you have passed. You can view a copy of your transcript at any time by going to the MCP secured site and selecting Transcript Tool. This tool enables you to print a copy of your current transcript and confirm your certification status. After you pass the necessary set of exams, you are certified. Official certification is normally granted after three to six weeks, so you shouldn’t expect to get your credentials overnight. The package for official certification that arrives includes a Welcome Kit that contains a number of elements (see Microsoft’s Web site for other benefits of specific certifications): ➤ A certificate that is suitable for framing, along with a wallet card and lapel
pin. ➤ A license to use the applicable logo, which means you can use the logo in
advertisements, promotions, and documents, and on letterhead, business cards, and so on. Along with the license comes a logo sheet, which includes camera-ready artwork. (Note that before you use any of the artwork, you must sign and return a licensing agreement that indicates you’ll abide by its terms and conditions.) ➤ A subscription to Microsoft Certified Professional Magazine, which provides
ongoing data about testing and certification activities, requirements, and changes to the program. Many people believe that the benefits of MCP certification go well beyond the perks that Microsoft provides to newly anointed members of this elite group. We’re starting to see more job listings that request or require applicants to have MCP, MCAD, and other certifications, and many individuals who complete Microsoft certification programs can qualify for increases in pay and/or responsibility. As an official recognition of hard work and broad knowledge, one of the MCP credentials is a badge of honor in many IT organizations.
How to Prepare for an Exam Preparing for any MCAD- or MCSD-related test (including Exam 70-310) requires that you obtain and study materials designed to provide comprehensive information about the product and its capabilities that will appear on
xxv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Introduction . . . . . . .
the specific exam for which you are preparing. The following list of materials can help you study and prepare: ➤ The .NET Framework Software Development Kit (SDK). This SDK,
which you can download from
http://msdn.microsoft.com/downloads/
sample.asp?url=/msdn-files/027/000/976/msdncompositedoc.xml,
contains full documentation of .NET and should be a primary resource when you are preparing for the test. ➤ The exam-preparation materials, practice tests, and self-assessment exams
on the Microsoft Training & Services page at www.microsoft.com/traincert. The Exam Resources link offers examples of the new question types found on the MCAD and MCSD exams. You should find the materials, download them, and use them! ➤ The exam-preparation advice, practice tests, questions of the day, and dis-
cussion groups on the www.examcram2.com e-learning and certification destination Web site. In addition, you might find any or all of the following materials useful in your quest for Visual Basic .NET expertise: ➤ Microsoft training kits—Microsoft Press offers a training kit that specifical-
ly targets Exam 70-310. For more information, visit http://www. microsoft.com/mspress/certification/mcad.asp. This training kit contains information that you will find useful in preparing for the test. ➤ Microsoft Developer Network CD-ROM—This quarterly CD-ROM–based
or DVD-based publication delivers numerous electronic titles that include coverage of .NET Framework, Visual Basic .NET, and related topics. Its offerings include product facts, technical notes, tools and utilities, sample code, and much more. A subscription to the MSDN Library costs $199 per year, but it is well worth the price. Visit http://msdn. microsoft.com/subscriptions/prodinfo/overview.asp for more details. ➤ Study guides—Several publishers—including Que Publishing—offer certi-
fication titles. Que Publishing offers the following: ➤ The Exam Cram 2 series—These books give you information about
the material you need to know to pass the tests. ➤ The MCAD Training Guide series—These books provide a greater
level of detail than the Exam Cram 2 books and are designed to teach you everything you need to know about the subject covered by an exam. Each book comes with a CD-ROM that contains interactive practice exams in a variety of testing formats.
xxvi Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Together, these two series make a perfect pair. ➤ Classroom training—Certified Technical Education Centers (CTECs),
online partners, and third-party training companies (such as Wave Technologies, Learning Tree, and Data-Tech) all offer classroom training on Visual Basic .NET. These companies aim to help you prepare to pass Exam 70-310 (or other exams). Although such training runs upward of $350 per day in class, most of the individuals lucky enough to partake find this training to be quite worthwhile. ➤ Other publications—There’s no shortage of materials available about Visual
Basic .NET, XML, and the .NET Framework. The “Need to Know More?” resource sections at the end of each chapter in this book give you an idea of where I think you should look for further discussion. This set of required and recommended materials represents an unparalleled collection of sources and resources for Visual Basic .NET and related topics. I hope you’ll find that this book belongs in the same company.
What This Book Will Not Do This book will not teach you everything you need to know about computers, or even about a given topic. Nor is this book an introduction to computer technology. If you’re new to applications development and looking for an initial preparation guide, check out www.quepublishing.com, where you will find a whole section dedicated to the MCSD/MCAD certifications. This book will review what you need to know before you take the test, with the fundamental purpose dedicated to reviewing the information needed on the Microsoft 70-310 certification exam. This book uses a variety of teaching and memorization techniques to analyze the exam-related topics and to provide you with ways to input, index, and retrieve everything you’ll need to know in order to pass the test. Once again, it is not an introduction to application development.
What This Book Is Designed to Do This book is designed to be read as a pointer to the areas of knowledge you will be tested on. In other words, you may want to read the book one time, just to get an insight into how comprehensive your knowledge of computers is. The book is also designed to be read shortly before you go for the actual test and to give you a distillation of the entire field of Windows application development in as few pages as possible. I think you can use this book to get
xxvii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Introduction . . . . . . .
a sense of the underlying context of any topic in the chapters—or to skimread for Exam Alerts, bulleted points, summaries, and topic headings. I’ve drawn on material from Microsoft’s own listing of knowledge requirements, from other preparation guides, and from the exams themselves. I’ve also drawn from a battery of third-party test-preparation tools and technical Web sites as well as from my own experience with application development and the exam. My aim is to walk you through the knowledge you will need— looking over your shoulder, so to speak—and point out those things that are important for the exam (Exam Alerts, practice questions, and so on). The 70-310 exam makes a basic assumption that you already have a strong background of experience with the Windows development platform and its terminology. On the other hand, because the .NET development environment is so new, no one can be a complete expert. I’ve tried to demystify the jargon, acronyms, terms, and concepts. Also, wherever I think you’re likely to blur past an important concept, I’ve defined the assumptions and premises behind that concept.
About This Book If you’re preparing for the 70-310 certification exam for the first time, I’ve structured the topics in this book to build upon one another. Therefore, the topics covered in later chapters might refer to previous discussions in earlier chapters. I suggest you read this book from front to back. You won’t be wasting your time, because nothing I’ve written is a guess about an unknown exam. I’ve had to explain certain underlying information on such a regular basis that I’ve included those explanations here. Once you’ve read the book, you can brush up on a certain area by using the index or the table of contents to go straight to the topics and questions you want to reexamine. I’ve tried to use the headings and subheadings to provide outline information about each given topic. After you’ve been certified, I think you’ll find this book useful as a tightly focused reference and an essential foundation of .NET application development.
Chapter Formats Each Exam Cram 2 chapter follows a regular structure and provides graphical cues about especially important or useful material. The structure of a typical chapter is as follows:
xxviii Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ➤ Opening hotlists—Each chapter begins with lists of the terms you’ll need to
understand and the concepts you’ll need to master before you can be fully conversant with the chapter’s subject matter. I follow the hotlists with a few introductory paragraphs, setting the stage for the rest of the chapter. ➤ Topical coverage—After the opening hotlists, each chapter covers the top-
ics related to the chapter’s subject. ➤ Alerts—Throughout the topical coverage section, I highlight material
most likely to appear on the exam by using a special Exam Alert layout that looks like this: This is what an Exam Alert looks like. An Exam Alert stresses concepts, terms, software, or activities that will most likely appear in one or more certification exam questions. For that reason, I think any information found offset in Exam Alert format is worthy of unusual attentiveness on your part.
Even if material isn’t flagged as an Exam Alert, all the content in this book is associated in some way with test-related material. What appears in the chapter content is critical knowledge. ➤ Notes—This book is an overall examination of computers. As such, I’ll dip
into many aspects of .NET application development. Where a body of knowledge is deeper than the scope of the book, I use notes to indicate areas of concern or specialty training. Cramming for an exam will get you through a test, but it won’t make you a competent IT professional. Although you can memorize just the facts you need in order to become certified, your daily work in the field will rapidly put you in water over your head if you don’t know the underlying principles of application development.
➤ Tips—I provide tips that will help you to build a better foundation of
knowledge or to focus your attention on an important concept that will reappear later in the book. Tips provide a helpful way to remind you of the context surrounding a particular area of a topic under discussion. You should also carefully read Chapter 1, “Microsoft Certification Exams,” for helpful strategies used in taking a test. The introduction to Chapter 13, “Sample Test #1,” contains additional tips on how to figure out the correct response to a question and what to do if you draw a complete blank.
xxix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Introduction . . . . . . . ➤ Exam Prep Questions—This section presents a short list of test questions
related to the specific chapter topic. Each question has a following explanation of both correct and incorrect answers. The practice questions highlight the areas I found to be most important on the exam. ➤ Need to Know More?—Every chapter ends with a section titled “Need To
Know More?” This section provides pointers to resources that I found to be helpful in offering further details on the chapter’s subject matter. If you find a resource you like in this collection, use it, but don’t feel compelled to use all these resources. I use this section to recommend resources that I have used on a regular basis, so none of the recommendations will be a waste of your time or money. Because these resources may go out of print or be taken down (in the case of Web sites), I’ve tried to reference widely accepted resources. The bulk of the book follows this chapter structure, but there are a few other elements I would like to point out: ➤ Practice exams—The sample tests, which appear in Chapters 13 and 15
(with answer keys in Chapters 14 and 16), are very close approximations of the types of questions you are likely to see on the current 70-310 exam. ➤ Answer keys—These provide the answers to the sample tests, complete with
explanations of both the correct responses and the incorrect responses. ➤ Glossary—This is an extensive glossary of important terms used in this
book. ➤ The Cram Sheet—This appears as a tear-away sheet inside the front cover
of this Exam Cram 2 book. It is a valuable tool that represents a collection of the most difficult-to-remember facts and numbers I think you should memorize before taking the test. Remember, you can dump this information out of your head onto a piece of paper as soon as you enter the testing room. These are usually facts that I’ve found require brute-force memorization. You only need to remember this information long enough to write it down when you walk into the test room. Be advised that you will be asked to surrender all personal belongings before you enter the exam room itself. You might want to look at the Cram Sheet in your car or in the lobby of the testing center just before you walk into the testing center. The Cram Sheet is divided into headings, so you can review the appropriate parts just before the exam.
xxx Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ➤ The CD-ROM—The CD-ROM includes many helpful code samples that
demonstrate all the topics on the exam. If you work through the samples on the CD-ROM, you’ll understand the techniques you’re likely to be tested on. The CD-ROM also contains the PrepLogic Practice Tests, Preview Edition exam-simulation software. The Preview Edition exhibits most of the full functionality of the Premium Edition but offers questions sufficient for only one practice exam. To get the complete set of practice questions and exam functionality, visit www.preplogic.com.
Codes and Commands Limitations of printed pages will, many times, require me to write code with smaller margins than you might use in practice. In these cases, I’ve used the Visual Basic .NET line continuation character (_) whenever possible so that the code you see on the printed page is syntactically correct. In some cases, the margins force me to introduce line continuations into code that’s automatically generated by Visual Basic .NET, even though you won’t see those continuations when you re-create the code in your own copy.
Contacting the Author I’ve tried to create a real-world tool that you can use to prepare for and pass the 70-310 MCAD/MCSD certification exam. I’m interested in any feedback you would care to share about the book, especially if you have ideas about how I can improve it for future test-takers. I’ll consider everything you say carefully and will respond to all reasonable suggestions and comments. You can reach me via email at
[email protected]. Let me know if you found this book to be helpful in your preparation efforts. I’d also like to know how you felt about your chances of passing the exam before you read the book and then after you read the book. Of course, I’d love to hear that you passed the exam—and even if you just want to share your triumph, I’d be happy to hear from you. Thanks for choosing me as your personal trainer, and enjoy the book. I would wish you luck on the exam, but I know that if you read through all the chapters and work with the product, you won’t need luck—you’ll pass the test on the strength of real knowledge!
Self-Assessment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
The reason I included a Self-Assessment in this Exam Cram 2 book is to help you evaluate your readiness to tackle Microsoft certifications. It should also help you understand what you need to know to master the topic of this book—namely, Exam 70-310 “Developing XML Web Services and Server Components with Microsoft Visual Basic .NET and the Microsoft .NET Framework.” But before you tackle this Self-Assessment, let’s talk about concerns you may face when pursuing an MCSD (Microsoft Certified Solution Developer) or MCAD (Microsoft Certified Application Developer) for the .NET platform and what an ideal MCSD candidate might look like.
MCSDs in the Real World In the next section, I describe an ideal MCSD or MCAD candidate, knowing full well that only a few real candidates will meet this ideal. In fact, my description of that ideal candidate might seem downright scary, especially with the changes that have been made to the program to support the .NET development platform. But take heart: Although the requirements to obtain an MCSD may seem formidable, they are by no means impossible to meet. However, be keenly aware that it does take time, involves some expense, and requires real effort to get through the process. Remember, too, that you can get your MCAD on the way to your MCSD as you continue to develop your skills to the MCSD level. Increasing numbers of people are attaining Microsoft certifications, so the goal is within reach. You can get all the real-world motivation you need from knowing that many others have gone before, so you will be able to follow in their footsteps. If you’re willing to tackle the process seriously and do what it takes to obtain the necessary experience and knowledge, you can take—and pass—all the certification tests involved in obtaining an MCSD or MCAD. Besides MCSD and MCAD, other Microsoft certifications include the following:
xxxii
Self-Assessment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ➤ MCSA (Microsoft Certified Systems Administrator)—This is the brand-new
certification that Microsoft has provided for those Microsoft professionals who are not going to design networks but rather administer them. This certification includes three core exams and a single elective. ➤ MCDBA (Microsoft Certified Database Administrator)—This is aimed at
database administrators and developers who work with Microsoft SQL Server. The MCDBA certification requires three core exams and one elective exam. ➤ Other Microsoft certifications—The requirements for these certifications
range from one test (MCP) to several tests (MCSE).
The Ideal MCSD Candidate The MCSD test is aimed at software developers. The requirements have recently been revised for .NET and include one exam on Web application development, one on Windows application development, one on XML and server development, one on solution architecture, and a fifth, elective exam drawn from a different, but limited, pool of options. The 70-310 exam that this book prepares you for fulfills the XML and server exam requirement for the MCSD. Just to give you some idea of what an ideal MCSD candidate is like, here are some relevant statistics about the background and experience such an individual might have: ➤ Academic or professional training in applications-development theory,
concepts, and operations. This includes everything from programming and deployment planning through database integration and Web deployment. ➤ Two or more years of lead development experience, including business
process analysis, deployment management planning, and solution architecture design within an enterprise. The .NET platform is somewhat different from previous versions of the Microsoft development languages; therefore, you’ll really need some hands-on experience. Due to the structural changes made in creating an object-based development environment built around a Common Language Runtime, the more hands-on experience you have, the better.
xxxiii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Self-Assessment . . . . . . . . . ➤ Experience in developing applications designed to run within the
Windows 2000 Server, Windows 2000/XP Professional, and soon the Windows .NET Server environments. A solid understanding of each system’s architecture, installation, configuration, maintenance, and troubleshooting is also helpful when testing your code. ➤ A thorough understanding of the software-development lifecycle is
important, including analysis, design, development, testing, deployment, and maintenance of an application. ➤ An understanding of how to implement security for key network data in a
Windows 2000/XP environment. ➤ Experience developing XML and server components in the .NET envi-
ronment. ➤ Working knowledge of the .NET programming environment, preferably
with some hands-on experience with the Microsoft Visual Studio .NET development tools. The time you take practicing the use of Visual Studio .NET will be time very well spent! Don’t worry if you don’t meet these qualifications or don’t even come that close—this is a far-from-ideal world, and where you fall short is simply where you’ll have more work to do.
Fundamentally, this boils down to a bachelor’s degree in computer science (or equivalent experience on the job), plus two years’ experience working in a position involving applications design, testing, deployment, and maintenance, with some experience in database integration. I believe that well under half of all certification candidates meet these requirements and that, in fact, most meet less than half of these requirements—at least, when they begin the certification process. But because all the people who already have been certified have survived this ordeal, you can survive it, too—especially if you heed what this Self-Assessment can tell you about what you already know and what you need to learn.
Put Yourself to the Test The following series of questions and observations is designed to help you figure out how much work you must do to pursue Microsoft certification and what kinds of resources you should consult on your quest. Be absolutely honest in your answers; otherwise, you’ll end up wasting money on exams you’re
xxxiv Self-Assessment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
not yet ready to take. There are no right or wrong answers, only steps along the path to certification. Only you can decide where you really belong in the broad spectrum of aspiring candidates. Two things should be clear from the outset, however: ➤ Even a modest background in computer science and programming will be
helpful. ➤ Hands-on experience with Microsoft products and technologies is an
essential ingredient to Microsoft certification success.
Educational Background 1. Have you ever taken any computer-related classes? [Yes or No]
If Yes, proceed to Question 2; if No, proceed to Question 4. 2. Have you taken any classes on computer operating systems? [Yes or No]
If Yes, you will probably be able to handle Microsoft’s architecture and system component discussions. If you’re rusty, brush up on basic operating system concepts and general computer security topics. If No, consider some basic reading in this area. I strongly recommend a good general operating systems book, such as Operating System Concepts, 5th Edition, by Abraham Silberschatz and Peter Baer Galvin (John Wiley & Sons, 1998). If this title doesn’t appeal to you, check out reviews for other, similar titles at your favorite online bookstore. 3. Have you taken any programming classes, particularly ones focused on
Microsoft development languages and the .NET platform? [Yes or No] If Yes, you will probably be able to handle Microsoft’s terminology, concepts, and technologies (brace yourself for frequent departures from normal usage). If you’re rusty, brush up on basic programming concepts and terminology, with an eye toward the .NET development methodology. If No, you might want to read one or two books in this topic area. The best book that I know of is Applied Microsoft .NET Framework Programming, by Jeffrey Richter (Microsoft Press, 2002). 4. Have you done any reading on programming? [Yes or No]
If Yes, review the requirements stated in the first paragraphs after Questions 2 and 3. If you meet those requirements, move on to the next section.
xxxv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Self-Assessment . . . . . . . . .
If No, consult the recommended reading previously discussed in this section for both topics. A strong background will help you prepare for the Microsoft exams better than just about anything else.
Hands-on Experience The most important key to success on all the Microsoft tests is hands-on experience, especially with the Visual Studio .NET interface. If I leave you with only one realization after taking this Self-Assessment, it should be that there’s no substitute for time spent creating, configuring, and deploying applications created using the Visual Basic .NET product, upon which you’ll be tested repeatedly and in depth. You can download objectives, practice exams, and other data about Microsoft exams from the Training and Certification page at http://www.microsoft.com/ traincert/. Use the “Microsoft Certifications” link to obtain specific exam information.
5. Have you installed, configured, or used Visual Studio .NET and the
.NET Framework? [Yes or No] If Yes, you should be familiar with the main parts of the Visual Studio .NET Integrated Development Environment (IDE) and will be prepared to follow the examples in this book. If No, you must get some experience. Read on for suggestions on how to do this. Experience is a must with any Microsoft product exam, be it something as simple as FrontPage 2000 or as challenging as SQL Server 2000. For trial copies of other software, search Microsoft’s Web site using the name of the product as your search term. Also, search for bundles such as “BackOffice” or “Small Business Server.” 6. Have you developed any server-side components such as Web Services,
remoting objects, or serviced components? If Yes, you will be able to handle the sections of the exam dealing with these components. If No, you must get some experience with these particular types of components. The best experience is hands-on work in a client/server environment. You might also choose to work through a study guide such as the Que 70-310 Training Guide.
xxxvi Self-Assessment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7. Do you have experience creating and reading XML files?
If Yes, you’re ready to tackle the extensive XML content of the 70-310 exam. If No, you must ensure that you have a basic understanding of XML to pass this exam. Appendix B, “XML Standards and Syntax,” introduces you to the subject. You may also want to visit the Web site of the World Wide Web Consortium at http://www.w3c.org/ to view the many official specifications and documents relating to XML. If you have the funds, or your employer will pay your way, consider taking a class at a Certified Training and Education Center (CTEC). In addition to classroom exposure to the topic of your choice, you usually get a copy of the software that is the focus of your course, along with a trial version of whatever operating system it needs, with the training materials for that class.
Before you even think about taking any Microsoft exam, make sure you’ve spent enough time with the related software to understand how it may be installed, configured, and used. This will help you in the exam, and in real life!
Testing Your Exam-Readiness Whether you attend a formal class on a specific topic to get ready for an exam or use written materials to study on your own, some preparation for the Microsoft certification exams is essential. At $125 a try, pass or fail, you want to do everything you can to pass on your first try. That’s where studying comes in. I have included two practice exams in this book (Chapters 13 and 15), so if you don’t score that well on the first, you can study more and then tackle the second. For any given subject, consider taking a class if you’ve tackled self-study materials, taken the test, and failed anyway. The opportunity to interact with an instructor and fellow students can make all the difference in the world, if you can afford that privilege. For information about Microsoft classes, visit the Training and Certification page at http://www.microsoft.com/education/ partners/ctec.asp for Microsoft Certified Education Centers.
xxxvii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Self-Assessment . . . . . . . . .
If you can’t afford to take a class, visit the Training page at http://www.microsoft.com/traincert/training/find/default.asp anyway, because it also includes pointers to free practice exams and to Microsoft Certified Professional Approved Study Guides and other self-study tools. And even if you can’t afford to spend much at all, you should still invest in some low-cost practice exams from commercial vendors. 8. Have you taken a practice exam on your chosen test subject? [Yes or No]
If Yes, and you scored 70% or better, you’re probably ready to tackle the real thing. If your score isn’t above that threshold, keep at it until you break that barrier. If No, obtain all the free and low-budget practice tests you can find and get to work. Keep at it until you can break the passing threshold comfortably. When it comes to assessing your test readiness, there is no better way than to take a good-quality practice exam and pass with a score of 70% or better. When I’m preparing myself, I shoot for 80% or more, just to leave room for the “weirdness factor” that sometimes shows up on Microsoft exams. That is, you can know the material and still miss a question because it is worded in a peculiar way.
Assessing Readiness for Exam 70-310 In addition to the general exam-readiness information in the previous section, there are several things you can do to prepare for the Developing XML Web Services and Server Components with Microsoft Visual Basic .NET and the .NET Framework exam. I suggest that you join an active Microsoft Developers mailing list, obtain a Microsoft Developer Network (MSDN) subscription, and regularly visit the MSDN Web site for new information (http://msdn.microsoft.com). Microsoft exam mavens also recommend checking the Microsoft Knowledge Base (integrated into the MSDN CD-ROM, or on the Microsoft Web site at http://support.microsoft.com/support/) for “meaningful technical support issues” that relate to your exam’s topics. Although I’m not sure exactly what the quoted phrase means, I have noticed some overlap between technical support questions on particular products and troubleshooting questions on the exams for those products.
xxxviii Self-Assessment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
What’s Next? After you’ve assessed your readiness, undertaken the right background studies, obtained the hands-on experience that will help you understand the products and technologies at work, and reviewed the many sources of information to help you prepare for a test, you’ll be ready to take a round of practice tests. When your scores come back positive enough to get you through the exam, you’re ready to go after the real thing. If you follow my assessment regime, you’ll not only know what you need to study but also when you’re ready to make a test date at Prometric (www.prometric.com) or VUE (www.vue.com). Good luck!
1 Microsoft Certification Exams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terms you’ll need to understand: ✓ Case study ✓ Multiple-choice question formats ✓ Build-list-and-reorder question format ✓ Create-a-tree question format ✓ Drag-and-connect question format ✓ Select-and-place question format ✓ Fixed-length tests ✓ Simulations ✓ Adaptive tests ✓ Short-form tests
Techniques you’ll need to master: ✓ Assessing your exam readiness ✓ Answering Microsoft’s varying question types ✓ Altering your test strategy depending on the exam format ✓ Practicing (to make perfect) ✓ Making the best use of the testing software ✓ Budgeting your time ✓ Guessing (as a last resort)
2
Chapter . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exam-taking is not something that most people anticipate eagerly, no matter how well prepared they may be. In most cases, familiarity helps offset test anxiety. In plain English, this means you probably won’t be as nervous when you take your fourth or fifth Microsoft certification exam as you’ll be when you take your first one. Whether it’s your first exam or your tenth, understanding the details of taking the new exam (how much time to spend on questions, the environment you’ll be in, and so on) and the new exam software will help you concentrate on the material rather than on the setting. Likewise, mastering a few basic exam-taking skills should help you recognize (and perhaps even outfox) some of the tricks and snares you’re bound to find in some exam questions. This chapter explains the exam environment and software and describes some proven exam-taking strategies you can use to your advantage.
Assessing Exam-Readiness I strongly recommend that you read through and take the Self-Assessment included with this book (it appears after the introduction in this book). This will help you compare your knowledge base to the requirements for obtaining an MCAD (Microsoft Certified Application Developer) or MCSD (Microsoft Certified Solution Developer), and it will also help you identify parts of your background or experience that may need improvement or enhancement as well as where you need further learning. If you get the right set of basics under your belt, obtaining Microsoft certification will be that much easier. After you’ve gone through the Self-Assessment, you can remedy those topical areas in which your background or experience may be lacking. You can also tackle subject matter for individual tests at the same time, so you can continue making progress while you’re catching up in some areas. After you’ve worked through an Exam Cram 2, have read the supplementary materials, and have taken the practice test, you’ll have a pretty clear idea of when you should be ready to take the real exam. Although I strongly recommend that you keep practicing until your scores top the 70% mark, 80% is a better goal because it gives some margin for error when you are in an actual, stressful exam situation. Keep taking practice tests and studying the materials until you attain that score. You’ll find more pointers on how to study and prepare in the Self-Assessment. But now, on to the exam itself.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Microsoft . . . . . .Certification . . . . . . Exams . . . .
What to Expect at the Testing Center When you arrive at the testing center where you scheduled your exam, you must sign in with an exam coordinator and show two forms of identification, one of which must be a photo ID. After you’ve signed in and your time slot arrives, you’ll be asked to deposit any books, bags, cell phones, or other items you brought with you. Then, you’ll be escorted into a closed room. All exams are completely closed book. Although you are not permitted to take anything with you into the testing area, you are furnished with a blank sheet of paper and a pen (in some cases, an erasable plastic sheet and an erasable pen). Immediately before entering the testing center, try to memorize as much of the important material as you can so that you can write that information on the blank sheet as soon as you are seated in front of the computer. You can refer to this piece of paper during the test, but you’ll have to surrender the sheet when you leave the room. Because your timer does not start until you begin the testing process, it is best to do this first while the information is still fresh in your mind. You will have some time to compose yourself, write down information on the paper you’re given, and take a sample orientation exam before you begin the real thing. I suggest you take the orientation test before taking your first exam (because the exams are generally identical in layout, behavior, and controls, you probably won’t need to do this more than once). Typically, the room has one to six computers, and each workstation is separated from the others by dividers. Most test rooms feature a wall with a large picture window. This permits the exam coordinator to monitor the room, prevent exam-takers from talking to one another, and observe anything out of the ordinary. The exam coordinator will have preloaded the appropriate Microsoft certification exam (for this book, Exam 70-310), and you’ll be permitted to start as soon as you’re seated in front of the computer. All Microsoft certification exams allow a certain maximum amount of time in which to complete your work (this time is indicated on the exam by an onscreen counter/clock, so you can check the time remaining whenever you like). All Microsoft certification exams are computer generated. In addition to multiple choice, you may encounter select and place (drag and drop), create a tree (categorization and prioritization), drag and connect, and build list and reorder (list prioritization) on some exams. The questions are constructed to check your mastery of basic facts and figures about developing serverside solutions with Microsoft Visual Basic .NET and require you to evaluate
3
4
Chapter . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
one or more sets of circumstances or requirements. Often, you’ll be asked to give more than one answer to a question. You may also be asked to select the best or most effective solution to a problem from a range of choices, all of which are technically correct.
Exam Layout and Design The format of Microsoft exams can vary. For example, many exams consist of a series of case studies, with six types of questions regarding each presented case. Other exams may have the same six types of questions but no complex multi-question case studies. In this chapter, I’ll show you the wide range of questions that you might encounter on Microsoft exams, even though not all of these types of questions will appear on the 70-310 exam. For the Design exams, each case study presents a detailed problem that you must read and analyze. Figure 1.1 shows an example of what a case study looks like. You must select the different tabs in the case study to view the entire case.
Figure 1.1 This is a typical case study.
Following each case study is a set of questions related to the case study. These questions can be one of several types (which are discussed next). Careful attention to details provided in the case study is the key to success. Be prepared to toggle frequently between the case study and the questions as you work. Some of the case studies also include diagrams (called exhibits) that you’ll need to examine closely to understand how to answer the questions. After you complete a case study, you can review all the questions and your answers. However, when you move on to the next case study, you cannot return to the previous case study and make any changes.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Microsoft . . . . . .Certification . . . . . . Exams . . . .
Following are the types of question formats: ➤ Multiple-choice, single answer ➤ Multiple-choice, multiple answers ➤ Build list and reorder (list prioritization) ➤ Create a tree ➤ Drag and connect ➤ Select and place (drag and drop) ➤ Hot area
Multiple-Choice Question Format Some exam questions require you to select a single answer, whereas others ask you to select multiple correct answers. The following multiple-choice question requires you to select a single correct answer. Following the question is a brief summary of each potential answer and why it is either right or wrong.
Question 1 You have three domains connected to an empty root domain under one contiguous domain name: tutu.com. This organization is formed into a forest arrangement with a secondary domain called frog.com. How many Schema Masters exist for this arrangement? ❍ A. One ❍ B. Two ❍ C. Three ❍ D. Four
Answer A is correct. Only one Schema Master is necessary for a forest arrangement. The other answers (B, C, and D) are misleading because you are led to believe that Schema Masters may be in each domain or that you should have one for each contiguous domain namespace.
5
6
Chapter . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
This sample question format corresponds closely to the Microsoft certification exam format (of course, questions are not followed by answer keys on the exam). To select an answer, you position the cursor over the radio button next to the answer and click the mouse button to select it. Let’s examine a question where one or more answers are possible. This type of question provides check boxes rather than radio buttons (circles) for marking all appropriate selections.
Question 2 How can you seize FSMO roles? [Select all correct answers.] ❑ A. By using the ntdsutil.exe utility ❑ B. By using the Replication Monitor ❑ C. By using the secedit.exe utility ❑ D. By using Active Directory Domains and Trusts
Answers A and B are correct. You can seize FSMO roles from a server that is still running through the Replication Monitor, or in the case of a server failure, you can seize roles with the ntdsutil.exe utility. The secedit.exe utility is used to force group policies into play; therefore, answer C is incorrect. Active Directory Domains and Trusts is a combination of truth and fiction; therefore, answer D is incorrect. For this particular question, two answers are required. Microsoft sometimes gives partial credit for partially correct answers. For Question 2, you have to check the boxes next to answers A and B to obtain credit for a correct answer. Notice that picking the right answers also means knowing why the other answers are wrong.
Build-List-and-Reorder Question Format Questions in the build-list-and-reorder format present two lists of items: one on the left and one on the right. To answer the question, you must move items from the list on the right to the list on the left. The final list must then be arranged into a specific order.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Microsoft . . . . . .Certification . . . . . . Exams . . . .
These questions are usually in the form, “From the following list of choices, pick the choices that answer the question. Then arrange the list in a certain order.” To give you practice with this type of question, some questions of this type are included in this study guide. Here’s an example of how they appear in this book; for an example of how they appear on the test, see Figure 1.2.
Figure 1.2 This is how build-list-and-reorder questions appear.
Question 3 From the following list of famous people, pick those that have been elected President of the United States. Arrange the list in the order in which they served. Thomas Jefferson Ben Franklin Abe Lincoln George Washington Andrew Jackson Paul Revere
7
8
Chapter . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
The correct answer is: George Washington Thomas Jefferson Andrew Jackson Abe Lincoln On an actual exam, the entire list of famous people would initially appear in the list on the right. You would move the four correct answers to the list on the left and then reorder the list on the left. Notice that the answer to the question did not include all items from the initial list. However, this may not always be the case. To move an item from the right list to the left list, first select the item by clicking it and then clicking the Add button (left arrow). Once you move an item from one list to the other, you can move the item back by first selecting the item and then clicking the appropriate button (either the Add button or the Remove button). After items have been moved to the left list, you can reorder the list by selecting an item and clicking the up or down button.
Create-a-Tree Question Format Questions in the create-a-tree format also present two lists: one on the left and one on the right. The list on the right consists of individual items, and the list on the left consists of nodes in a tree. To answer the question, you must move items from the list on the right to the appropriate node in the tree. These questions are basically a matching exercise. Items from the list on the right are placed under the appropriate category in the list on the left. Here’s an example of how they appear in this book. For an example of how they appear on the test, see Figure 1.3.
Question 4 The calendar year is divided into four seasons: Winter Spring Summer Fall
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Microsoft . . . . . .Certification . . . . . . Exams . . . .
Identify the season when each of the following holidays occurs: Christmas Fourth of July Labor Day Flag Day Memorial Day Washington’s Birthday Thanksgiving Easter
The correct answer is: Winter Christmas Washington’s Birthday Spring Flag Day Memorial Day Easter Summer Fourth of July Labor Day Fall Thanksgiving In this case, all the items in the list were used. However, this may not always be the case. To move an item from the right list to its appropriate location in the tree, you must first select the appropriate tree node by clicking it. Then, you select the item to be moved and click the Add button. If one or more items have been added to a tree node, the node is displayed with a plus sign (+) icon to the left of the node name. You can click this icon to expand the node and view whatever was added. If any item has been added to the wrong tree node, you can remove it by selecting it and clicking the Remove button (see Figure 1.3).
9
10
Chapter . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Figure 1.3 This is how create-a-tree questions appear.
Drag-and-Connect Question Format Questions in the drag-and-connect format present a group of objects and a list of “connections.” To answer the question, you must move the appropriate connections between the objects. This type of question is best described using graphics. Here’s an example:
Question 5 The following objects represent the different states of water:
Use items from the following list to connect the objects so that they are scientifically correct. Sublimates to form Freezes to form
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Microsoft . . . . . .Certification . . . . . . Exams . . . .
Evaporates to form Boils to form Condenses to form Melts to form
The correct answer is:
For this type of question, it’s not necessary to use every object, but each connection can be used multiple times by dragging the answer to multiple locations. Dragging an answer away from its position removes it.
Select-and-Place Question Format Questions in the select-and-place (drag-and-drop) format present a diagram with blank boxes and a list of labels that must be dragged to fill in the blank boxes. To answer the question, you must move the labels to their appropriate positions on the diagram. This type of question is best described using graphics. Here’s an example:
Question 6 Place the items in their proper order, by number, on the following flowchart. Some items may be used more than once, and some items might not be used at all.
11
12
Chapter . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
The correct answer is:
Hot Area This type of question asks you to select one or more areas on a graphic to indicate the correct answer to a question. The hot spots on the graphic will be shaded when you move the mouse over them, and they are marked with an obvious border. To select or deselect an element, just click it. A simple hot-area question might present a screenshot of the Visual Studio .NET interface and ask you to indicate the tab that allows you to retrieve information on particular databases. In that case, you’d click the Server Explorer tab to answer the question.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Microsoft . . . . . .Certification . . . . . . Exams . . . .
Microsoft’s Testing Formats Currently, Microsoft uses four different testing formats: ➤ Case study ➤ Fixed length ➤ Adaptive ➤ Short form
Currently, the 70-310 exam uses the fixed-length format, but you should be aware of the other formats as well. Microsoft revises popular exams from time to time and sometimes changes their format. As mentioned earlier, the case study approach is used with many of the newer Microsoft exams. These exams consist of a set of case studies that you must first analyze to answer questions related to the case studies. Such exams include one or more case studies (tabbed topic areas), each of which is followed by 4 to 10 questions. The question types for exams will be multiple choice, build list and reorder, create a tree, drag and connect, and select and place. Depending on the test topic, some exams are totally case based, whereas others are not at all. Other Microsoft exams employ advanced testing capabilities that may not be immediately apparent. Although the questions that appear are primarily multiple choice, the logic in fixed-length tests, which use a fixed sequence of questions, is more complex than that in older Microsoft tests. Some questions employ a sophisticated user interface (which Microsoft calls a simulation) to test your knowledge of particular software and systems in a simulated “live” environment that behaves just like the original. The Testing Innovations article at http://www.microsoft.com/TRAINCERT/mcpexams/faq/innovations.asp includes a downloadable series of demonstrations and examples. For some exams, Microsoft has turned to a well-known technique called adaptive testing to establish a test-taker’s level of knowledge and product competence. Adaptive exams look the same as fixed-length exams, but they determine the level of difficulty at which an individual test-taker can correctly answer questions. Test-takers with differing levels of knowledge or ability see different sets of questions; individuals with a high level of knowledge or ability are presented with a smaller set of more difficult questions, whereas individuals with a lower level of knowledge or ability are presented with a larger set of easier questions. Two individuals may answer the same percentage of
13
14
Chapter . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
questions correctly, but the test-taker with a higher knowledge or ability level scores higher because his or her questions are weighted more heavily. Also, lower-level test-takers may answer more questions than moreknowledgeable colleagues. This explains why adaptive tests use ranges of values to define the number of questions and the amount of time needed to complete the tests. Adaptive tests work by evaluating the test-taker’s most recent answer. A correct answer leads to a more difficult question and also raises the test software’s estimate of the test-taker’s knowledge and ability level. An incorrect answer leads to a less difficult question and also lowers the test software’s estimate of the test-taker’s knowledge and ability level. This process continues until the test targets the test-taker’s true ability level. The exam ends when the test-taker’s level of accuracy meets a statistically acceptable value (in other words, when his or her performance demonstrates an acceptable level of knowledge and ability) or when the maximum number of items has been presented (in which case, the test-taker is almost certain to fail). Microsoft has also introduced a short-form test for its most popular tests. This test consists of 25 to 30 questions, with a time limit of exactly 60 minutes. This type of exam is similar to a fixed-length test because it allows readers to jump ahead or return to earlier questions and to cycle through the questions until the test is done. Microsoft does not use adaptive logic in this test; it claims that statistical analysis of the question pool is such that the 25 to 30 questions delivered during a short-form exam conclusively measure a test-taker’s knowledge of the subject matter in much the same way as an adaptive test. The short-form test is like a “greatest hits exam” version (that is, the most important questions are covered) of an adaptive exam on the same topic. Some of the Microsoft exams may contain a combination of adaptive and fixed-length questions.
Because you won’t know in which form the Microsoft exam may be, you should be prepared for an adaptive exam instead of a fixed-length or a shortform exam. The penalties for answering incorrectly are built in to the test itself on an adaptive exam, whereas the layout remains the same for a fixed-length or short-form test, no matter how many questions you answer incorrectly. Most likely, you’ll see a fixed-length exam for 70-310. But be prepared, just in case!
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Microsoft . . . . . .Certification . . . . . . Exams . . . .
The biggest difference between adaptive tests and fixed-length and short-form tests is that you can mark and revisit questions on fixed-length and short-form tests after you’ve read them. On an adaptive test, you must answer the question when it is presented and cannot go back to that question later.
Strategies for Different Testing Formats Before you choose a test-taking strategy, you must determine what type of test it is—case study, fixed length, short form, or adaptive: ➤ Case study tests consist of a tabbed window that allows you to navigate
easily through the sections of the case. ➤ Fixed-length tests consist of 50 to 70 questions with a check box for
each question. You can return to these questions if you want. ➤ Short-form tests have 25 to 30 questions with a check box for each ques-
tion. You can return to these questions if you want. ➤ Adaptive tests are identified in the introductory material of the test.
Questions have no check boxes and can be visited (and answered) only once. Some tests contain a variety of testing formats. For example, a test may start with a set of adaptive questions, followed by fixed-length questions. As I mentioned earlier, the initial release of the 70-310 exam is fixed length, so you should concentrate on strategies for that type of exam. You’ll be able to tell for sure whether you are taking an adaptive, fixed-length, or short-form test by the first question. Fixed-length and short-form tests include a check box that allows you to mark the question for later review. Adaptive test questions include no such check box and can be visited (and answered) only once.
Case Study Exam Strategy Though you won’t find this kind of format for the 70-310 test, you might find the test-taking strategies beneficial, and if you ever take a case study exam, you’ll want to review this section. Most test-takers find that the case study type of exam is the most difficult to master. When it comes to studying for a case study test, your best bet is to approach each case study as a standalone test. The biggest challenge you’ll encounter is that you’ll feel you won’t have enough time to get through all the cases presented.
15
16
Chapter . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Each case provides a lot of material you’ll need to read and study before you can effectively answer the questions that follow. The trick to taking a case study exam is to first scan the case study to get the highlights. Make sure you read the overview section of the case so that you understand the context of the problem at hand. Then, quickly move on and scan the questions. As you are scanning the questions, make mental notes to yourself or notes on your paper so that you’ll remember which sections of the case study you should focus on. Some case studies may provide a fair amount of extra information that you don’t really need to answer the questions. The goal with this scanning approach is to avoid having to study and analyze material that is not completely relevant.
When studying a case, read the tabbed information carefully. It is important to answer each and every question. You will be able to toggle back and forth from case to questions, and from question to question, within a case testlet. However, after you leave the case and move on, you might not be able to return to it. I suggest that you take notes while reading useful information to help you when you tackle the test questions. It’s hard to go wrong with this strategy when taking any kind of Microsoft certification test.
Fixed-Length and Short-Form Exam Strategy A well-known principle when taking a fixed-length or short-form exam is first to read through the entire exam from start to finish. Answer only those questions that you feel absolutely sure you know. On subsequent passes, you can dive into complex questions more deeply, knowing how many such questions you have left and the amount of time remaining. There’s at least one potential benefit to reading the exam over completely before answering the trickier questions: Sometimes, information supplied in later questions sheds more light on earlier questions. At other times, information you read in later questions may jog your memory about facts, figures, or behaviors that help you answer earlier questions. Either way, you’ll come out ahead if you answer only those questions on the first pass that you’re absolutely confident about.
Fortunately, the Microsoft exam software for fixed-length and short-form tests makes the multiple-visit approach easy to implement. At the top-left corner of each question is a check box that permits you to mark that question for a later visit.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Microsoft . . . . . .Certification . . . . . . Exams . . . . Marking questions makes later review easier, but you can return to any question by clicking the Forward or Back button repeatedly. Of course, on an adaptive exam, this isn’t possible.
Here are some question-handling strategies that apply to fixed-length and short-form tests. Use them if you have the chance: ➤ When returning to a question after your initial read-through, read every
word again; otherwise, your mind can miss important details. Sometimes, revisiting a question after turning your attention elsewhere lets you see something you missed, but the strong tendency is to see what you’ve seen before. Try to avoid that tendency at all costs. ➤ If you return to a question more than twice, try to articulate to yourself
what you don’t understand about the question, why answers don’t appear to make sense, or what appears to be missing. If you chew on the subject awhile, your subconscious may provide the missing details, or you may notice a “trick” that points to the right answer. As you work your way through the exam, another counter that Microsoft provides comes in handy—the number of questions completed and questions outstanding. For fixed-length and short-form tests, it’s wise to budget your time by making sure you’ve completed roughly one-quarter of the questions one-quarter of the way through the exam period, and three-quarters of the questions three-quarters of the way through. If you’re not finished when only 5 minutes remain, use that time to guess your way through any remaining questions. Remember, guessing is potentially more valuable than not answering. Blank answers are always wrong, but a guess may turn out to be right. If you don’t have a clue about any of the remaining questions, pick answers at random or choose all A’s, B’s, and so on. Questions left unanswered are counted as answered incorrectly, so a guess is better than nothing at all. At the very end of your exam period, you’re better off guessing than leaving questions unanswered.
17
18
Chapter . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Adaptive Exam Strategy This type of exam format will not appear in the 70-310 exam; however, an overview of how to approach adaptive exams might benefit you when taking a future version of the 70-310 exam or if you ever need to take an adaptive exam. If there’s one principle that applies to taking an adaptive test, it’s “Get it right the first time.” You cannot elect to skip a question and move on to the next one when taking an adaptive test, because the testing software uses your answer to the current question to select whatever question it plans to present next. You also cannot return to a question because the software gives you only one chance to answer the question. You can, however, take notes as you work through the test. Sometimes, information supplied in earlier questions may help you answer later questions. Also, when you answer a question correctly, you are presented with a more difficult question next, to help the software gauge your level of skill and ability. When you answer a question incorrectly, you are presented with a less difficult question, and the software lowers its current estimate of your skill and ability. This continues until the program settles into a reasonably accurate estimate of what you know and can do. The good news is that if you know the material, you’ll probably finish most adaptive tests in 30 minutes or so. The bad news is that you must really know the material well to do your best on an adaptive test. That’s because some questions are so convoluted, complex, or hard to follow that you’re bound to miss one or two, at a minimum. Therefore, the more you know, the better you’ll do on an adaptive test, even accounting for the occasionally strange or unfathomable questions that appear on these exams. Because you can’t always tell in advance whether a test is fixed length, short form, adaptive, or a combination of these, you should prepare for the exam as if it were adaptive. That way, you will be prepared to pass, no matter what kind of test you take. If the test turns out to be fixed length or short form, remember the tips from the preceding section, which will help you improve on what you could do on an adaptive test.
If you encounter a question on an adaptive test that you can’t answer, you must guess an answer quickly. (However, you may suffer for your guess on the next question if you guess correctly, because the software will give you a more difficult question next!)
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Microsoft . . . . . .Certification . . . . . . Exams . . . .
Question-Handling Strategies For those questions that have only one right answer, usually two or three of the answers will be obviously incorrect, and two of the answers will be plausible. Unless the answer leaps out at you (if it does, reread the question to look for a trick; sometimes those are the ones you’re most likely to get wrong), begin the process of answering by eliminating those answers that are most obviously wrong. At least one answer out of the possible choices for a question can usually be eliminated immediately because it matches one of these conditions: ➤ The answer does not apply to the situation. ➤ The answer describes a nonexistent issue, an invalid option, or an imagi-
nary state. After you eliminate all answers that are obviously wrong, you can apply your retained knowledge to eliminate further answers. Look for items that sound correct but refer to actions, commands, or features that are not present or not available in the situation the question describes. If you’re still faced with a blind guess among two or more potentially correct answers, reread the question. Try to picture how each of the possible remaining answers would alter the situation. Be especially sensitive to terminology; sometimes the choice of words (“remove” instead of “disable”) can make the difference between a right answer and a wrong one. You should guess at an answer only after you’ve exhausted your ability to eliminate answers and are still unclear about which of the remaining possibilities is correct. An unanswered question offers you no points, but guessing gives you at least some chance of getting a question right; just don’t be too hasty when making a blind guess. If you’re taking a fixed-length or a short-form test, you can wait until the last round of reviewing marked questions (just as you’re about to run out of time or unanswered questions) before you start making guesses. You will usually have the same option within each case study testlet (but once you leave a testlet, you may not be allowed to return to it). If you’re taking an adaptive test, you’ll have to guess to move on to the next question if you can’t figure out an answer some other way. Either way, guessing should be your technique of last resort!
Numerous questions assume that the default behavior of a particular utility is in effect. If you know the defaults and understand what they mean, this knowledge will help you cut through many Gordian knots. Simple “final”
19
20
Chapter . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
actions may be critical as well. If a utility must be restarted before proposed changes take effect, a correct answer may require this step as well.
Mastering the Inner Game In the final analysis, knowledge gives confidence, and confidence breeds success. If you study the materials in this book carefully and review all the practice questions at the end of each chapter, you should become aware of those areas where additional learning and study are required. After you’ve worked your way through the book, take the practice exams in the back of the book. Taking these tests provides a reality check and helps you identify areas to study further. Make sure you follow up and review materials related to the questions you miss on the practice exams before scheduling a real exam. Don’t schedule your exam appointment until after you’ve thoroughly studied the material and feel comfortable with the whole scope of the practice exams. You should score 80% or better on one of the practice exams before proceeding to the real thing (otherwise, obtain some additional practice tests so you can keep trying until you hit this magic number). If you take a practice exam and don’t get at least 80% of the questions correct, keep practicing. Microsoft provides links to practice exam providers and also selfassessment exams at http://www.microsoft.com/traincert/mcpexams/prepare/.
Armed with the information in this book and with the determination to augment your knowledge, you should be able to pass the certification exam. However, you need to work at it, or you’ll spend the exam fee more than once before you finally pass. If you prepare seriously, you should do well. The next section covers other sources you can use to prepare for the Microsoft certification exams.
Additional Resources A good source of information about Microsoft certification exams comes from Microsoft itself. Because its products and technologies—and the exams that go with them—change frequently, the best place to go for exam-related information is online.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Microsoft . . . . . .Certification . . . . . . Exams . . . .
If you haven’t already visited the Microsoft Certified Professional site, do so right now. The MCP home page resides at http://www.microsoft.com/ traincert/default.asp (see Figure 1.4).
Figure 1.4 The Microsoft Certified Professional Training and Certification home page.
Coping with Change on the Web Sooner or later, all the information I’ve shared with you about the Microsoft Certified Professional pages and the other Web-based resources mentioned throughout the rest of this book will go stale or be replaced by newer information. In some cases, the URLs you find here may lead you to their replacements; in other cases, the URLs will go nowhere, leaving you with the dreaded “404 File not found” error message. When that happens, don’t give up. There’s always a way to find what you want on the Web if you’re willing to invest some time and energy. Most large or complex Web sites (such as the Microsoft site) offer a search engine. On all of Microsoft’s Web pages, a Search button appears along the top edge of the page. As long as you can get to the Microsoft site (it should stay at www.microsoft.com for a long time), you can use this tool to help you find what you need. The more focused you can make a search request, the more likely the results will include information you can use. For example, you can search for the string “training and certification”
21
22
Chapter . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . to produce a lot of data about the subject in general, but if you’re looking for the preparation guide for Exam 70-310, “Developing XML Web Services and Server Components with Microsoft Visual Basic .NET and the Microsoft .NET Framework,” you’ll be more likely to get there quickly if you use a search string similar to the following: “Exam 70-310” AND “preparation guide”
Likewise, if you want to find the Training and Certification downloads, try a search string such as this: “training and certification” AND “download page”
Finally, feel free to use general search tools—such as www.google.com, www.altavista.com, and www.excite.com—to look for related information. Although Microsoft offers great information about its certification exams online, there are plenty of third-party sources of information and assistance that need not follow Microsoft’s party line. Therefore, if you can’t find something immediately, intensify your search.
2 Creating and Manipulating DataSets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terms you’ll need to understand: ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓
Attribute Ad hoc query DataSet DataSet schema Element Identity Key Metadata Nested relationship
✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓
One-to-many relationship Osql Parameter Simple type SQL-92 SQL Query Analyzer Stored procedure Strongly typed DataSet Transact-SQL (T-SQL)
Techniques you’ll need to master: ✓ Creating a DataSet schema by dragging and dropping a table from Server Explorer to a Visual Basic .NET application ✓ Using the schema designer to edit a DataSet schema ✓ Using the schema designer to create a relationship between two tables in a DataSet schema
✓ Creating a strongly typed DataSet from a DataSet schema ✓ Writing code that refers to data in a strongly typed DataSet ✓ Constructing and interpreting simple Transact-SQL statements, including SELECT, INSERT, UPDATE, and DELETE
24
Chapter . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
The exam presumes that you already have a working knowledge of ADO.NET. (If you need a refresher course, refer to Appendix A, “ADO.NET Basics.”) The core object of ADO.NET is the DataSet, which provides a complete in-memory relational database. To pass the exam, you’ll need to know how to manipulate the schema of a DataSet, as well as how to instantiate a strongly typed DataSet from a schema. You’ll also need to know the basics of Structured Query Language (SQL). Any databases referred to on the exam will most likely use Microsoft SQL Server to store their data. Be sure you know how to select and alter data from a SQL Server database.
Manipulating a DataSet Schema A DataSet schema is an XML file that describes the structure of a DataSet. You can work with such files as raw XML, but if you have Visual Studio .NET, there’s a better way. Visual Studio .NET includes a specialized XML designer that provides a visual representation of DataSet schema files. The XML designer is also integrated with the database support in Server Explorer. You can add items to a DataSet schema file by dragging and dropping them from Server Explorer. To use the XML designer in Visual Studio .NET with a DataSet schema file, you’ll need to create a new Visual Studio .NET project to host the file. After you’ve done that, you can perform many design tasks, including the creation of new schemas and editing of existing schemas.
Creating a DataSet Schema Visual Studio .NET allows you to create a DataSet schema “from scratch” without reference to an existing DataSet or to a table stored on a database server. To do this, add a new DataSet item from the Local Project items category. The new DataSet schema file will open in a visual designer with a set of tools appropriate for creating new metadata, as shown in Figure 2.1. In the next section, you learn how to add information to the schema to help dictate the layout of the DataSet that it defines.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating . . . . .and . . Manipulating . . . . . . . DataSets . . . . .
Figure 2.1 The DataSet schema designer with an empty schema loaded.
Elements and Attributes Like other XML files, DataSet schema files are made up of XML elements. You can think of an element as a unit of information. In a DataSet, elements often map to columns in a database. To add an element to a schema, select the Element tool in the Toolbox and drag it to the schema designer. This will create an element named element1. You can rename the element by typing over the name. Drag another element and drop it on top of the first element to create a nested element. The designer assumes that the new element will be a complex element—that is, one that contains other elements. To change the new element to a simple element, select a data type from the drop-down list to the right of the element. Figure 2.2 shows a pair of elements in the designer. They’ve both been renamed from their defaults, and the inner element (CustomerID) has been defined as a string.
Figure 2.2 An element with a simple nested element.
25
26
Chapter . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
As you work in the designer, you’re actually creating an XML file. At any time, you can use the XML tab at the bottom of the designer to see the raw XML. Here’s the XML that corresponds to the schema shown in Figure 2.2:
You should understand how to create schema files and be moderately familiar with their XML representation. However, there’s no need to memorize the complete XML syntax that Visual Studio .NET uses for these files.
You can also use the XML designer to add attributes to a DataSet schema. Attributes provide an alternative way to represent columns within a DataSet. To add an attribute, select the Attribute tool in the Toolbox. Drag the attribute from the Toolbox and drop it on top of an element in the schema. This will create an attribute named attribute1. You can rename the attribute by typing over the name. You’ll see that the attribute is assigned the string data type by default. Attributes cannot be used for complex data types. Given that you can represent columns by either elements or attributes within a DataSet schema file, how do you decide which representation to use? Here are some points to consider: ➤ If you need to exchange the schema file with other applications, you
must be sure that it is compatible with those applications. Microsoft Access, for example, can import a schema defined using elements but not one defined using attributes.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating . . . . .and . . Manipulating . . . . . . . DataSets . . . . . ➤ If your DataSet requires columns that are defined using a custom data
type, you must use elements for those columns. Attributes are restricted to the built-in data types defined by the World Wide Web Consortium (W3C). ➤ To represent a child table in a hierarchy, you must use an element. Visual Studio .NET always uses elements to represent database columns when you use it to create a DataSet schema.
Using Server Explorer with the XML Designer You can also create DataSet schemas quickly by using the Server Explorer, which allows you to interact directly with SQL Server and other databases. By default, the Server Explorer window in Visual Studio .NET is displayed as a small vertical tab to the left of the Toolbox. When you hover the mouse over this tab, the Server Explorer will slide out to cover the Toolbox. To work with DataSet schema files, you’ll use the Data Connection node in Server Explorer and its children. To start working with those objects, you’ll need to add a data connection to the Server Explorer tree. Here’s how to create a data connection to a SQL Server: 1. Open Server Explorer by hovering your mouse over its tab. 2. Right-click the Data Connections node and then select Add
Connection. This will open the Data Link Properties dialog box. 3. Fill in the connection information for your data source. The dialog box
will default to using the Microsoft OLE DB Provider for SQL Server, but you can change that on the Provider tab if you prefer. As an example, for a SQL Server data connection (the only kind I’ll be using in this book), you must select the server name from the drop-down list, fill in your username and password, and then select the database from the second drop-down list. You can use the Test Connection button to make sure you’ve successfully completed these steps. 4. Click OK to create the data connection. For ease in working with the
code in this chapter, you should create at least one data connection based on an instance of the SQL Server Northwind sample database.
27
28
Chapter . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
If SQL Server is located on the same computer where you’re running Visual Basic .NET code, you can use the special name (local) to refer to the server in place of a machine name.
Visual Studio .NET remembers your data connections across sessions and projects. Any data connection you’ve created will appear in Server Explorer in all your projects unless you right-click the data connection and choose Delete. After you’ve created a data connection, you can use objects from that data connection in a DataSet schema design. For example, you can expand the Data Connection tree to show a server, then a database, and then the tables within the database. Drag tables from Server Explorer to the schema designer to bring them into the schema. Figure 2.3 shows the schema I’ve been working with after adding two tables from the Northwind sample database using this process. As you can see, there’s no problem in combining handbuilt tables with tables created by dragging and dropping.
Figure 2.3 A DataSet schema with three tables and a simple type.
You can also create schema elements by dragging a view, a stored procedure, a function, or a set of columns from Server Explorer to the DataSet schema designer.
Manipulating DataSet Relationships As an in-memory representation of a database, the DataSet object retains the notion of relations between tables. As you would expect, this means that a DataSet schema can also store information on keys and relationships in the DataSet it represents.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating . . . . .and . . Manipulating . . . . . . . DataSets . . . . .
Adding Keys to a DataSet Schema The DataSet schema designer allows you to create two types of keys. You can identify a field or a set of fields as the primary key for a table, or you can identify a field or a set of fields as making up a unique key. To create a key in the designer, select the Key tool in the Toolbox. Drag the key from the Toolbox and drop it on an element that represents a column. This will open the Edit Key dialog box. Select the fields you wish to use for the key and type a name for the key. To create a primary key, check the DataSet Primary Key check box. If you don’t check this check box, the result will be a unique key but not a primary key. You can create one primary key and as many unique keys as you like for each table in the DataSet schema designer. The primary key identifies the field (or combination of fields) that uniquely specifies an individual row in the table. Unique keys identify other fields or combinations of fields that cannot be repeated in different records of the same table. To delete a primary key or a unique key in the DataSet schema designer, you must first click in the row containing the key to select the row. Then you can right-click that row and select Delete Key.
One-to-Many Relationships One way to relate two tables in a DataSet schema is to identify common key columns and create a relationship between the tables using those columns. This is similar to the way relational database products handle relationships. To create a relationship in the schema designer, follow these steps: 1. Open a schema that contains the two tables you want to relate. 2. Select the Relation tool in the Toolbox. Use this tool to drag a rela-
tionship from the Toolbox and drop it on the child table. For example, to relate one customer to many orders, you would drop the relation on the Orders table. This will open the Edit Relation dialog box (see Figure 2.4). 3. Name the relationship. Select the parent table (for example,
Customers) as the parent element and then select the child table (for example, Orders) as the child element. Select the key and key fields to use. Leave all other options at their default values.
29
30
Chapter . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Figure 2.4 Creating a relationship in the schema designer.
4. Click OK to create the relationship. The designer will draw a relation-
ship object and connecting lines between the two tables. You can also specify a number of optional behaviors in the Edit Relation dialog box. You can create a relationship that is only used as a constraint, and you can exercise control over the behavior of child records when a parent record is updated or deleted.
Nested Relationships Although one-to-many relationships are the only kind you’ll find in a typical relational database, the DataSet schema designer also supports nested relationships. In a nested relationship, the child table is stored as a complex data type within the parent table. To create a nested relationship, select a child table in the schema designer. Drag and drop the child table on top of its parent table. This will create a relationship between the two tables. Because there are two different ways to relate tables in a DataSet schema, you’ll have to choose between the two. Here are some points to help you decide whether to use one-to-many or nested relationships in your DataSet schemas: ➤ One-to-many relationships more directly represent the way data is
stored in a relational database. If your data is primarily stored in a database, this provides the most natural mapping.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating . . . . .and . . Manipulating . . . . . . . DataSets . . . . . ➤ Nested relationships are more natural to represent in XML. If your data
is not stored in a relational database, nested relationships provide a cleaner and more succinct XML representation of the connections between tables. ➤ If you require interoperability with other XML applications, nested rela-
tionships are more likely to be correctly interpreted.
Creating and Using Strongly Typed DataSets The best way to understand strongly typed DataSet objects is to see what you can do with one syntactically. Suppose that you have a normal DataSet, and you’ve extracted a DataTable object named dt from this DataSet. Then you can refer to a value in the DataTable with any of these syntaxes: dt.Rows(0).Item(0) dt.Rows(0)(0) dt.Rows(0).Item(“ColumnName”) dt.Rows(0)(“ColumnName”) dt.Rows(0)!ColumnName
All these syntaxes have one thing in common: They’re all late bound. That is, .NET doesn’t know until runtime that “ColumnName” is a valid column name in the DataTable. By contrast, in a strongly typed DataSet, the columns actually become properties of the row. With a strongly typed DataSet, an early-bound version of the data-retrieval code becomes available: dt.Rows(0).ColumnName
In addition to being faster than the late-bound syntax, this syntax also has the benefit that column and table names show up in the applicable IntelliSense lists.
Using the Component Designer to Create a Strongly Typed DataSet One way to create a strongly typed DataSet is to derive it directly from a table or other data-bearing object in a database. Follow these steps to use this technique:
31
32
Chapter . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1. Expand the Server Explorer tree view to show a data connection to
your database. Drill into the Tables folder within this database. 2. Drag an Employees table from Server Explorer and drop it on a Visual
Basic .NET form. This will add a SqlConnection object named SqlConnection1 and a SqlDataAdapter object named SqlDataAdapter1 to the component tray of the form. 3. Select the SqlDataAdapter object. Click the Generate DataSet hyper-
link at the bottom of the Properties window. This will open the Generate DataSet dialog box. Name the new DataSet object and select the check box to add the DataSet object to the designer. Click OK. 4. You’ll see a new object, with the extension .xsd, appear in the Solution
Explorer. This is a DataSet schema file that describes the new strongly typed DataSet. Click the Show All Files button on the Solution Explorer toolbar. Expand the dsEmployees.xsd node to see the corresponding .vb file. This is a class file that can be instantiated to produce the strongly typed DataSet. In addition to the new objects in Solution Explorer, this example will also add a new component to the component tray underneath the form. This is an instance of the class defined in dsEmployees.vb.
Creating a Strongly Typed DataSet from a DataSet Schema You can also create a strongly typed DataSet from a DataSet schema file— more precisely, if you’ve created a DataSet schema in your Visual Basic .NET project. Visual Basic .NET will automatically create a strongly typed DataSet class that matches the structure defined in the schema. Because you edit the schema, Visual Basic .NET will keep the DataSet class synchronized with your edits. For example, suppose you’ve created a schema named Customers.xsd. If you click the Show All Files toolbar button, you’ll find two files as children of the Customers.xsd DataSet schema file: ➤ Customers.vb—This file is the class definition for a strongly typed
DataSet based on the DataSet schema you’ve been working with. ➤ Customers.xsx—This file contains information on the layout of objects
within the DataSet schema designer window.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating . . . . .and . . Manipulating . . . . . . . DataSets . . . . .
Using a Strongly Typed DataSet Once you’ve built a strongly typed DataSet, you can treat the tables within the DataSet as properties of the DataSet, and you can treat the columns as properties of their tables. For example, if you have built a strongly typed DataSet named dsEmployees and have instantiated an object named dsEmployees1 from this DataSet, you could iterate through all the rows in the DataSet with this code: Private Sub Form1_Load( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Dim EmpRow As dsEmployees.EmployeesRow SqlDataAdapter1.Fill(DsEmployees1, “Employees”) For Each EmpRow In DsEmployees1.Employees lbEmployees.Items.Add( _ EmpRow.FirstName & “ “ & EmpRow.LastName) Next End Sub
Notice as you type this code that the IntelliSense feature fills in the names of tables and columns for you. A strongly typed DataSet class inherits from the base DataSet class, so it has all the methods and properties of the DataSet. The strong typing gives you the benefits of design-time IntelliSense and type checking. It also makes your code easier to read. Given the ease with which Visual Studio .NET can create strongly typed DataSet classes, you should plan to use them whenever possible.
Accessing and Manipulating SQL Server Data You’ll need to understand Transact-SQL (T-SQL) to pass the exam. T-SQL is Microsoft’s implementation of SQL (Structured Query Language), which is defined by a standard from the American National Standards Institute (ANSI). You can submit T-SQL to a SQL Server database for processing in two ways. First, you can write ad hoc queries, SQL statements that are executed directly. Second, you can write stored procedures, SQL statements that are stored on the server as a named object. The .NET Framework includes facilities for running both ad hoc queries and stored procedures.
33
34
Chapter . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Using Ad Hoc Queries Ad hoc T-SQL queries provide an extremely flexible way to retrieve data from a SQL Server database or to make changes to that database. You should know the four basic types of T-SQL statements: ➤
SELECT
statements allow you to retrieve data stored in the database.
➤
INSERT
statements allow you to add new data to the database.
➤
UPDATE
statements allow you to modify data already in the database.
➤
DELETE
statements allow you to delete data from the database. You’ll usually see SQL keywords (such as SELECT, INSERT, UPDATE, and DELETE) formatted entirely in uppercase. I follow that convention in this book, but uppercase formatting isn’t required by SQL Server. You might see these same keywords in mixed case or lowercase on an exam. As far as SQL Server is concerned, there’s no difference between SELECT, Select, and select.
Running Queries There are many ways to send queries to SQL Server, including the use of the osql and SQL Query Analyzer utilities that are shipped with SQL Server. But for simple SELECT queries, it’s just as easy to build your own application in Visual Basic .NET. Here’s how: 1. Add a new form to your Visual Basic .NET project. 2. Open Server Explorer. 3. Expand the tree under Data Connections to show a SQL Server data
connection that points to the Northwind sample database. Drag and drop the data connection onto the form to create a SqlConnection1 object on the form. This object represents a connection to SQL Server. 4. Add a TextBox control named
txtQuery, a Button control named and a DataGrid control named dgResults to the form. Set the Multiline property of the TextBox to True. Set the CaptionVisible property of the DataGrid to False. Arrange the controls as shown in Figure 2.5.
btnExecute,
5. Double-click the Button control to open the form’s module. Enter two
statements at the top of the module: Imports System.Data Imports System.Data.SqlClient
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating . . . . .and . . Manipulating . . . . . . . DataSets . . . . . 6. Enter the following code to execute the query when you click the
Button control: Private Sub btnExecute_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnExecute.Click ‘ Create a SqlCommand to represent the query Dim cmd As SqlCommand = _ SqlConnection1.CreateCommand cmd.CommandType = CommandType.Text cmd.CommandText = txtQuery.Text ‘ Create a SqlDataAdapter to talk to the database Dim da As SqlDataAdapter = New SqlDataAdapter() da.SelectCommand = cmd ‘ Create a DataSet to hold the results Dim ds As DataSet = New DataSet() ‘ Fill the DataSet da.Fill(ds, “Results”) ‘ And bind it to the DataGrid dgResults.DataSource = ds dgResults.DataMember = “Results” End Sub
7. Set the form as the startup object for the project. 8. Run the project. Enter a query in the text box, such as the following: SELECT * FROM Employees
9. Click the button to run the code, retrieving the results to the
DataGrid, as shown in Figure 2.5.
Figure 2.5 Running an ad hoc query from a custom form.
You can learn about the ADO.NET objects that this example uses in Appendix A.
The SELECT Statement The basic SQL statement is the SELECT statement.
35
36
Chapter . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Just reading the descriptions here is no substitute for actually practicing with T-SQL. You’re sure to see some SQL statements on the exam.
The SELECT statement is used to create a resultset. In skeleton form, a SELECT looks like this: SELECT field_list FROM table_list WHERE where_clause GROUP BY group_by_clause HAVING having_clause ORDER BY sort_clause
Each of those lines of code is called a clause. The SELECT and FROM clauses are required, and the rest are optional. Here’s an example of a SQL statement containing only the required clauses: SELECT OrderID, CustomerID FROM Orders
The resultset for this statement contains the values of the OrderID and CustomerID fields from every record in the Orders table. The asterisk (*) character is a shortcut to refer to all columns in the source: SELECT * FROM Orders
You’re also not limited to fields from a single table. For instance, you might try retrieving information from both the Customers and Orders tables with this query: SELECT OrderID, Customers.CustomerID FROM Orders, Customers
Note that Customers.CustomerID is what’s known as a fully qualified name, meaning both the table name and the field name are specified. This is necessary because both the Customers table and the Orders table contain fields named CustomerID, and you need to tell SQL Server which one you want to display. If you try the previous query, though, you’ll get more than 75,000 records back—many more than the number of orders in the database! That’s because the query as written, although it includes all the proper tables, doesn’t tell SQL Server how to relate those tables. This sort of query is called a cross-product query. SQL Server constructs the resultset by including one row in the output for each row in each combination of input table rows. That is, there’s an output row for the first order and
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating . . . . .and . . Manipulating . . . . . . . DataSets . . . . .
the first customer, for the first order and the second customer, and so on. A more useful query, of course, matches each order with the corresponding customer. That’s the job of the INNER JOIN keyword. INNER JOIN tells SQL Server how to match two tables. Here’s how the syntax looks for a fixed version of the original query: SELECT OrderID, Customers.CustomerID FROM Orders INNER JOIN Customers ON Orders.CustomerID = Customers.CustomerID
This rewrite tells SQL Server to look at each row in the Orders table and match it with all rows in the Customers table where the CustomerID of the order equals the CustomerID of the customer. Because CustomerIDs are unique in the Customers table, this is tantamount to including only a single row for each order in the resultset. The INNER JOIN keyword can appear more than once in a query for more than two tables to join. For example, here’s a query to show EmployeeIDs along with OrderIDs and CustomerIDs: SELECT Orders.OrderID, Customers.CustomerID, Employees.EmployeeID FROM Employees INNER JOIN (Customers INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID) ON Employees.EmployeeID = Orders.EmployeeID
Note the use of parentheses to specify the order in which the joins should be performed. What if you only want to see some of the rows in the table? That’s where the WHERE clause comes into the picture. You can think of a WHERE clause as making a simple, yes-or-no decision for each row of data in the original table, deciding whether to include that row in the resultset. The simplest form of the WHERE clause checks for the exact contents of a field. For example, SELECT * FROM Orders WHERE ShipCountry = ‘Brazil’
looks at every row in the Orders table and determines whether the ShipCountry field contains the exact value Brazil. If so, the row is included in the results. If not, it’s discarded. However, WHERE clauses need not be exact. This is also a valid SQL statement: SELECT * FROM Orders WHERE Freight > 50
37
38
Chapter . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
In this case, you’ll get all the rows in which the amount in the Freight field is greater than 50. Note, by the way, that Brazil goes in quotation marks, whereas 50 doesn’t. That’s simply a syntax matter: Text and date data need quotation marks, but numeric columns don’t. You’re free to combine multiple tests in a single WHERE clause. For example, SELECT * FROM Orders WHERE ShipCountry = ‘Brazil’ AND Freight > 50 AND OrderDate 10 GROUP BY ProductID ORDER BY Sum(Quantity) DESC
This has the same effect as the first query, except that it will just ignore any row in the Order Details table that has a quantity of 10 or under. Second, you can limit the results by filtering the totals with a HAVING clause: SELECT ProductID, Sum(Quantity) AS TotalSales FROM [Order Details] GROUP BY ProductID
41
42
Chapter . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . HAVING Sum(Quantity) > 1000 ORDER BY Sum(Quantity) DESC
A HAVING clause filters the results rather than the input. That is, the last query will sum everything from the Order Details table and then show you rows in which the total is greater than 1,000. You can also combine the two types of filtering, as shown here: SELECT ProductID, Sum(Quantity) AS TotalSales FROM [Order Details] WHERE Quantity > 10 GROUP BY ProductID HAVING Sum(Quantity) > 1000 ORDER BY Sum(Quantity) DESC
This searches the source table for rows in which the quantity is greater than 10 and then only keeps those rows in which the total is more than 1,000. Note that WHERE and HAVING go in two different places in the SQL statement. The order of clauses is fixed, not optional.
The INSERT Statement The purpose of the INSERT statement is to add a row or multiple rows to a table through executing a SQL statement. In its simplest form, the insert query lists a target table and a set of values to insert. For example, this query adds a new row to the Order Details table: INSERT INTO [Order Details] VALUES (10248, 1, 12.00, 5, 0)
This simple form of the statement has two drawbacks. First, knowing which field is getting which piece of data is difficult. The values are inserted into the table fields in the order that the fields show up in Design view, but you must remember (in this example) that the quantity is the fourth field. Second, if you use this format, you must supply a value for every field. This is a problem when you want the default value for a field or when a field can’t have data inserted into it (for example, an identity field whose values are automatically generated by SQL Server). To get around these problems, a second format explicitly lists the fields for the target table: INSERT INTO [Order Details] (OrderID, ProductID, UnitPrice, Quantity, Discount) VALUES (10248, 2, 12.00, 5, 0)
Here, the first set of parentheses holds a column list, and the second set holds the values to insert. If a field has a default value, can be null, or is an identity field, you can leave it out of the field list:
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating . . . . .and . . Manipulating . . . . . . . DataSets . . . . . INSERT INTO Products (ProductName, SupplierID, CategoryID) VALUES (‘Turnips’, 25, 7)
This works even though no value is specified for most of the fields in the Products table. Also, you can rearrange the field list as long as you rearrange the value list to match: INSERT INTO Products (SupplierID, ProductName, CategoryID) VALUES (20, ‘Lettuce’, 7)
The insert query isn’t limited to inserting a single record. A second format inserts the results of a SELECT statement into the target table. For example, this query will insert a product from every supplier into the Products table: INSERT INTO Products (SupplierID, ProductName, CategoryID ) SELECT SupplierID, ‘Trout’, 8 FROM Suppliers
This works by building the results of the SELECT statement and then putting each row returned by SELECT into the target table. Of course, the columns still need to match up properly.
The UPDATE Statement As you can probably guess, the purpose of an update query is to update data. For example, you could update a field in a record in Northwind with this query: UPDATE Customers SET ContactName = ‘Maria Anderson’ WHERE CustomerID = ‘ALFKI’
In this query, the UPDATE keyword introduces an update query. The SET keyword tells SQL Server what to update. Here, it’s setting a field equal to a literal value. The WHERE clause tells SQL Server which row in the table to update. You’re not limited to updating a single record. If the WHERE clause selects multiple records, they’ll all be updated: UPDATE Customers SET Country = ‘United States’ WHERE Country = ‘USA’
You can even update every row in a table by leaving out the WHERE clause: UPDATE Products SET Discontinued = 0
43
44
Chapter . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
This will update every row in the Products table, even those in which the Discontinued field already has the value False. You can also update more than one field at a time with an update query: UPDATE Customers SET ContactName = ‘Maria Anders’, City = ‘Berlin’ WHERE CustomerID = ‘ALFKI’
And you can update with the result of an expression: UPDATE Products SET UnitPrice = UnitPrice * 1.1
If only it were so simple to raise prices in real life! Finally, you can update based on joined tables: UPDATE Products SET Discontinued = 1 FROM Suppliers INNER JOIN Products ON Suppliers.SupplierID = Products.SupplierID WHERE Suppliers.Country = ‘Italy’
This has the effect of discontinuing all the products imported from Italy.
The DELETE Statement The DELETE statement removes data from a table. The rule for constructing a delete query is simple: Construct a select query to select the records you want to delete and then change the SELECT keyword to DELETE. Remove any * identifier from the SELECT clause as well. That’s it! To avoid destroying existing data, I’ll use another query to set the stage. The SELECT INTO statement is used to create a new table. For example, this statement creates a table named BadCustomers with all the data from the existing Customers table: SELECT * INTO BadCustomers FROM Customers
Here’s a select query to select a single row from the new table: SELECT * FROM BadCustomers WHERE CustomerID = ‘GODOS’
Now change the SELECT
*
clause to DELETE:
DELETE FROM BadCustomers WHERE CustomerID = ‘GODOS’
If you run this query, it will delete the specified row. There’s no need for a WHERE clause if you want to get really extreme: DELETE FROM BadCustomers
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating . . . . .and . . Manipulating . . . . . . . DataSets . . . . .
This statement deletes all the rows from the BadCustomers table.
Using Stored Procedures When you use an ad hoc query to interact with SQL Server, the SQL statements in the query are completely transient. They vanish as soon as you close whatever tool you’ve used to execute the query. By contrast, stored procedures are queries stored permanently on the SQL Server itself. Stored procedures have two main benefits. First, you can save complex SQL statements for future execution so that you don’t have to re-create them from scratch. Second, SQL Server compiles stored procedures so that they run faster than ad hoc queries. You should also know about parameters, which make stored procedures more flexible, and the @@IDENTITY variable, which can supply useful information any time you use a stored procedure to insert data into a table with an identity column.
Creating a Stored Procedure T-SQL includes the CREATE PROCEDURE keyword to create stored procedures. You can run CREATE PROCEDURE statements from any interface that allows you to enter and execute T-SQL. For example, you can execute this statement directly within Visual Studio .NET by following these steps: 1. Open a Visual Basic .NET Windows application in the Visual Studio
.NET IDE. 2. Open Server Explorer. 3. Expand the tree under Data Connections to show a SQL Server data
connection that points to the Northwind sample database and then the Stored Procedures node of the SQL Server. 4. Right-click the Stored Procedures node and select New Stored
Procedure. 5. Replace the boilerplate code in the Stored Procedure designer with
this code: CREATE PROCEDURE procFranceCustomers AS SELECT * FROM Customers WHERE Country = ‘France’
6. Click the Save button to save the stored procedure to the database. 7. Select Database, Run Stored Procedure to run the
CREATE PROCEDURE
statement. This creates the stored procedure in the database.
45
46
Chapter . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8. Now you can execute the new procFranceCustomers stored procedure
from any tool that allows you to execute SQL statements. For example, Figure 2.6 shows the results of executing this stored procedure in the custom form you built earlier in the chapter.
Figure 2.6 The results of running a stored procedure are the same as the results of running the T-SQL statements contained in the stored procedure.
You can see two separate executing steps in this process. Executing the CREATE PROCEDURE statement (which is itself an ad hoc query) is necessary to create the stored procedure. After that has been done, you can execute the stored procedure itself to return results.
Running Stored Procedures from .NET Executing a stored procedure from .NET is very similar to executing an ad hoc query. The difference is that you supply the name of the stored procedure instead of the actual SQL as the CommandText property of a SqlCommand object. For example, this code will execute the stored procedure you just created: Private Sub StepByStep1_17_Load( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ‘ Create a SqlCommand to represent ‘ the stored procedure Dim cmd As SqlCommand = _ SqlConnection1.CreateCommand cmd.CommandType = CommandType.StoredProcedure cmd.CommandText = “procFranceCustomers” ‘ Create a SqlDataAdapter to talk to the database Dim da As SqlDataAdapter = New SqlDataAdapter() da.SelectCommand = cmd ‘ Create a DataSet to hold the results Dim ds As DataSet = New DataSet() ‘ Fill the DataSet da.Fill(ds, “Customers”) End Sub
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating . . . . .and . . Manipulating . . . . . . . DataSets . . . . .
Stored procedures are not limited to containing SELECT statements. You can place any SQL statement inside of a stored procedure. For example, you might use the following SQL statement to create a stored procedure to update the Customers table: CREATE PROCEDURE procExpandCountry AS UPDATE Customers SET Country = ‘United States’ WHERE Country = ‘USA’
When your stored procedure doesn’t return a resultset, you need to use a slightly different code structure to execute it: Private Sub btnExecute_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnExecute.Click ‘ Create a SqlCommand to represent ‘ the stored procedure Dim cmd As SqlCommand = _ SqlConnection1.CreateCommand cmd.CommandType = CommandType.StoredProcedure cmd.CommandText = “procExpandCountry” ‘ Open the connection and execute ‘ the stored procedure SqlConnection1.Open() cmd.ExecuteNonQuery() ‘ Close the connection SqlConnection1.Close() MessageBox.Show(“SQL statement was executed.”) End Sub
The ExecuteNonQuery method of the SqlCommand object can be used to execute any ad hoc query or stored procedure that doesn’t return any results. When you call the methods of the SqlDataAdapter object, the .NET Framework will automatically open and close the associated SqlConnection object as necessary. For any other operation (such as using the SqlCommand.ExecuteNonQuery method), you must explicitly call the SqlConnection.Open and SqlConnection.Close methods in your code.
Using Parameters in Stored Procedures The examples you’ve seen so far don’t begin to tap the real power of stored procedures. SQL Server supports parameterized stored procedures, which allow you to pass information to the stored procedure at runtime. (You can think of these as the T-SQL analogue of Visual Basic .NET functions.) For example, this SQL statement defines a stored procedure that returns the total sales for a particular customer, with the CustomerID specified at runtime: CREATE PROC procCustomerSales @CustomerID char(5), @TotalSales money OUTPUT
47
48
Chapter . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . AS SELECT @TotalSales = SUM(Quantity * UnitPrice) FROM ((Customers INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID) INNER JOIN [Order Details] ON Orders.OrderID = [Order Details].OrderID) WHERE Customers.CustomerID = @CustomerID
In this SQL statement, both @CustomerID and @TotalSales are variables (called parameters in T-SQL). To use the stored procedure, you must supply a value for the @CustomerID parameter. The @TotalSales parameter is marked as an OUTPUT parameter; it returns a value from the stored procedure to the calling code. In the .NET Framework, the SqlCommand object has a collection of parameters to let you manage parameterized stored procedures. You can set parameter values through this collection in code: Private Sub btnGetTotalSales_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnGetTotalSales.Click ‘ Create a SqlCommand to represent ‘ the stored procedure Dim cmd As SqlCommand = _ SqlConnection1.CreateCommand cmd.CommandType = CommandType.StoredProcedure cmd.CommandText = “procCustomerSales” ‘ Add the input parameter and set its value cmd.Parameters.Add(New SqlParameter( _ “@CustomerID”, SqlDbType.Text, 5)) cmd.Parameters(“@CustomerID”).Value = _ txtCustomerID.Text ‘ Add the output parameter and set its direction cmd.Parameters.Add(New SqlParameter( _ “@TotalSales”, SqlDbType.Money)) cmd.Parameters(“@TotalSales”).Direction = _ ParameterDirection.Output ‘ Execute the stored procedure and ‘ display the formatted results SqlConnection1.Open() cmd.ExecuteNonQuery() txtTotalSales.Text = String.Format(“{0:c}”, _ cmd.Parameters(“@TotalSales”).Value) SqlConnection1.Close() End Sub
In ADO.NET, parameters are represented by SqlParameter objects. This code uses two different forms of the constructor for SqlParameters. The first takes the parameter name, the parameter data type, and the size of the parameter; the second omits the parameter size (because the money type has a fixed size). The code works by setting the Value property of the @CustomerID parameter, executing the SqlCommand object, and then retrieving the Value property of the @TotalSales parameter.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating . . . . .and . . Manipulating . . . . . . . DataSets . . . . .
The @@IDENTITY Variable A SQL Server table can have a single identity column. An identity column is a column whose value is assigned by SQL Server itself whenever you add a new row to the table. The purpose of the identity column is to guarantee that each row in the table has a unique primary key. If you’re working with a table that contains an identity column, you’ll often want to add a new row to the table and then immediately retrieve the value of the identity column for the new row. SQL Server provides a variable named @@IDENTITY for just this purpose. The @@IDENTITY variable returns the most recently assigned identity column value. For example, you might create a stored procedure to insert a new row in a table and return the value of the identity column so that your code can continue to work with the new row: CREATE PROC procInsertShipper @CompanyName nvarchar(40), @ShipperID int OUTPUT AS INSERT INTO Shippers (CompanyName) VALUES (@CompanyName) SELECT @ShipperID = @@IDENTITY
This stored procedure contains two SQL statements. The first inserts a row into the Shippers table, and the second retrieves the value of the identity column for the new row. From code, you can retrieve the return value to a variable: Private Sub btnAddShipper_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnAddShipper.Click ‘ Create a SqlCommand to represent ‘ the stored procedure Dim cmd As SqlCommand = _ SqlConnection1.CreateCommand cmd.CommandType = CommandType.StoredProcedure cmd.CommandText = “procInsertShipper” ‘ Add the input parameter and set its value cmd.Parameters.Add(New SqlParameter( _ “@CompanyName”, SqlDbType.VarChar, 40)) cmd.Parameters(“@CompanyName”).Value = _ txtCompanyName.Text ‘ Add the output parameter and set its direction cmd.Parameters.Add(New SqlParameter( _ “@ShipperID”, SqlDbType.Int)) cmd.Parameters(“@ShipperID”).Direction = _ ParameterDirection.Output ‘ Execute the stored procedure and ‘ display the result SqlConnection1.Open() cmd.ExecuteNonQuery() MessageBox.Show(cmd.Parameters( _ “@ShipperID”).Value) SqlConnection1.Close() End Sub
49
50
Chapter . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exam Prep Questions Question 1 Your SQL Server database contains a table named Products. This table has columns named ProductID, ProductName, and ProductType. ProductID is the primary key of the table. You want to see a list of each product type, together with the number of products of that type. Which SQL statement should you use? ❍ A. SELECT COUNT(ProductType), COUNT(ProductID) FROM Products GROUP BY ProductType ❍ B. SELECT ProductType, COUNT(ProductID) FROM Products GROUP BY ProductType ❍ C. SELECT COUNT(ProductType), ProductID FROM Products GROUP BY ProductID ❍ D. SELECT ProductType, ProductID, COUNT(ProductID) FROM Products
Answer B is correct. The GROUP BY clause instructs SQL Server to return one row for each product type, and the COUNT() function will count the unique values that go into that row. Answer A is incorrect because it doesn’t return the product type, only the number of product types. Answer C is incorrect because it is grouped by product ID and therefore will return one row for each product. Answer D is incorrect because it does not include a GROUP BY clause.
Question 2 You are using a SQL INSERT statement to insert new records in a table named Customers. The Customers table has the following columns: CustomerID—integer, identity, no default value, cannot be null CustomerName—varchar(50), no default value, cannot be null CompanyContact—varchar(50), no default value, can be null CompanyCountry—varchar(25), default value ‘USA’, cannot be null Which column’s value must you explicitly specify in the SQL statement? ❍ A. CustomerID ❍ B. CustomerName ❍ C. CompanyContact ❍ D. CompanyCountry
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating . . . . .and . . Manipulating . . . . . . . DataSets . . . . .
Answer B is correct. You must specify values for all non-nullable columns that do not have a default value. Answer A is incorrect because the identity property will supply a default value. Answer C is incorrect because the CompanyContact column can be null. Answer D is incorrect because the column has a default value that will be used if you do not specify a different value.
Question 3 Your application contains a DataSet schema file that represents courses and classrooms. Each course is assigned a unique course ID, and each classroom is identified by a unique room number. Each course is taught in precisely one classroom, and each classroom is used for many courses. Courses and Classrooms are two separate XML elements joined by an XML relation. Both the Courses and Classrooms elements contain RoomNumber elements. How should those elements be identified? ❍ A. RoomNumber should be marked as a primary key in the Courses element and as a unique key in the Classrooms element. ❍ B. RoomNumber should be marked as a primary key in the Classrooms element and not marked as a key in the Courses element. ❍ D. RoomNumber should be marked as a primary key in the Classrooms element and as a unique key in the Courses element. ❍ D. RoomNumber should be marked as a primary key in the Classrooms element and as a primary key in the Courses element.
Answer B is correct. Marking the RoomNumber element as a primary key in the Classrooms element ensures that no two classrooms will share the same room number. Because more than one course can use the same classroom, RoomNumber should not be marked as a key at all in the Courses element. Answers A and D are incorrect because marking RoomNumber as a primary key in the Courses element would prevent two courses from sharing the same room. Answer C is incorrect because marking RoomNumber as a unique key in the Courses element would also prevent two courses from sharing the same room.
51
52
Chapter . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 4 You are building an XML schema file for an application that will retrieve data from a Web application that uses XML as its native format. The information you will retrieve includes a list of customers and a list of orders. Each customer has zero or more orders associated with it. You’ve already created a table to represent the customers within the schema file. How should you add the orders to this file? ❍ A. Add orders as an attribute to the Customers table. ❍ B. Add orders as a separate table. Use a nested relationship between the Orders table and the Customers table. ❍ C. Add orders as a separate table. Use a one-to-many relationship between the Orders table and the Customers table. ❍ D. Add orders as a simple type. Add a row using this simple type to the Customers table.
Answer B is correct. Because the native format of the data is XML, a nested relationship is more appropriate than a one-to-many relationship. Answer A is incorrect because an attribute can only represent one piece of information, not a complex type such as orders. Answer C is incorrect because it uses a one-to-many relationship rather than a nested relationship. Answer D is incorrect because a simple type can only represent one piece of information, not a complex type such as orders.
Question 5 You are designing an application that will work with student course registration information stored in a SQL Server database. Which of the following tasks are good candidates for implementation with a stored procedure? [Select all correct answers.] ❑ A. Retrieving a list of all students and student IDs from the database ❑ B. Developing an ad hoc report where the user can select the information to be displayed ❑ C. Inserting a new course registration into the database ❑ D. Allowing the administrator to run one-time queries against the database
Answers A and C are correct. Stored procedures are suitable for tasks that can be expressed as SQL statements that do not change or as SQL statements with parameters that can be specified at runtime. Stored procedures do not work well for ad hoc or interactive applications, where the query to be executed is not known in advance. Therefore, answers B and D are incorrect.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating . . . . .and . . Manipulating . . . . . . . DataSets . . . . .
Question 6 Your SQL Server database contains a table, Products, with the following structure: ProductID—int, identity ProductName—varchar(50) ProductPrice—money You wish to create a stored procedure that accepts as inputs the ProductName and ProductPrice, inserts a new row in the table, and returns the identity value assigned to that row in a parameter. Which SQL statement should you use? ❍ A. CREATE PROCEDURE procInsertProduct @ProductName varchar(50), @ProductPrice money, @ProductID int OUTPUT AS INSERT INTO Products (ProductName, ProductPrice) VALUES (@ProductName, @ProductPrice) SELECT @ProductID = @@IDENTITY
❍ B. CREATE PROCEDURE procInsertProduct @ProductName varchar(50), @ProductPrice money, @ProductID int AS INSERT INTO Products (ProductName, ProductPrice) VALUES (@ProductName, @ProductPrice) SELECT @ProductID = @@IDENTITY
❍ C. CREATE PROCEDURE procInsertProduct @ProductName varchar(50), @ProductPrice money, @ProductID int OUTPUT AS INSERT INTO Products (ProductID, ProductName, ProductPrice) VALUES (@ProductID, @ProductName, @ProductPrice) SELECT @ProductID = @@IDENTITY
❍ D. CREATE PROCEDURE procInsertProduct @ProductName varchar(50), @ProductPrice money, @ProductID int OUTPUT AS INSERT INTO Products (ProductName, ProductPrice) VALUES (@ProductName, @ProductPrice) SELECT @@IDENTITY
53
54
Chapter . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Answer A is correct. It contains the correct parameters and only inserts values into columns that can accept values. Answer B is incorrect because the @ProductID parameter is not marked as an output parameter. Answer C is incorrect because you cannot insert values into an identity column. Answer D is incorrect because it does not assign the @@IDENTITY value to the output parameter.
Question 7 You are using a table named TempData in your SQL Server database to store intermediate results during a long calculation. At the start of the calculation, you must remove all the data from this table, without removing the table itself. Which SQL statement can you use for this purpose? ❍ A. DELETE FROM TempData WHERE * ❍ B. DELETE * FROM TempData ❍ C. DELETE FROM TempData ❍ D. DELETE TempData
Answer C is correct. To delete all rows from a SQL Server table, you must use the DELETE FROM tablename syntax. Answer B is acceptable syntax for Jet SQL, but not for SQL Server’s T-SQL dialect. Answers A and D are syntactically incorrect and will return an error.
Question 8 You have created a DataSet schema file named Orders.xsd in a Visual Basic .NET Windows application. Which of the following will Visual Studio automatically create for you? ❍ A. A stored procedure named procInsertOrders ❍ B. A SqlDataAdapter class named OrdersAdapter.vb ❍ C. A strongly typed DataSet class named Orders.vb ❍ D. A form named Orders.vb
Answer C is correct. As you work with a DataSet schema file, Visual Studio .NET automatically creates and updates a corresponding strongly typed DataSet class. Answers A, B, and D are incorrect; if you require a stored procedure, a SqlDataAdapter, or a form, you must create them by other means.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating . . . . .and . . Manipulating . . . . . . . DataSets . . . . .
Question 9 You are working with a SQL Server database that contains two tables, Customers and Orders. The Customers table contains columns named CustomerID and CustomerName. CustomerID is the primary key of the Customers table. The Orders table contains columns named OrderID, CustomerID, and OrderDate. OrderID is the primary key of the Orders table, and CustomerID is a foreign key that is related to the CustomerID column in the Customers table. You want to run a query that retrieves all OrderIDs and dates for customers whose CustomerName starts with S. Which of these SQL statements should you use? ❍ A. SELECT Orders.OrderID, Orders.OrderDate FROM Customers, Orders WHERE CustomerName LIKE ‘S%’ ❍ B. SELECT Orders.OrderID, Orders.OrderDate FROM Customers INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID WHERE CustomerName LIKE ‘S_’ ❍ C. SELECT * FROM Customers INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID WHERE CustomerName LIKE ‘S%’ ❍ D. SELECT Orders.OrderID, Orders.OrderDate FROM Customers INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID WHERE CustomerName LIKE ‘S%’
Answer D is correct. It specifies the proper joins and wildcards to retrieve the desired information. Answer A is incorrect because it does not specify how the Customers and Orders tables are related. Answer B is incorrect because the underscore wildcard only matches a single character. Answer C is incorrect because SELECT * cannot be used when there are two columns with the same name (in this case, CustomerID).
55
56
Chapter . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Need to Know More? Delaney, Kalen. Inside SQL Server 2000. Microsoft Press, 2000. DeLoveh, David et al. Effective Visual Studio .NET. Wrox, 2002. Gunderloy, Mike. ADO and ADO.NET Programming. Sybex, 2002. SQL Server Books Online, installed as part of SQL Server 2000. World Wide Web Consortium: http://www.w3c.org/.
3 Accessing and Manipulating XML Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terms you’ll need to understand: ✓ DiffGram ✓ Document Object Model (DOM) ✓ Document Type Definition (DTD) ✓ Valid XML ✓ Well-formed XML ✓ XPath
Techniques you’ll need to master: ✓ Retrieving information from XML files by using the Document Object Model, XmlReader class, XmlDocument class, and XmlNode class ✓ Synchronizing DataSet data with XML via the XmlDataDocument class ✓ Executing XML queries with XPath and the XPathNavigator class ✓ Validating XML against XML Schema Design (XSD) and Document Type Definition (DTD) files ✓ Generating XML from SQL Server databases ✓ Updating SQL Server databases with DiffGrams
58
Chapter . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
You can’t use the .NET Framework effectively unless you’re familiar with XML. XML is pervasive in .NET, and it’s especially important for the distributed applications covered on the 70-310 exam. The System.Xml namespace contains classes to parse, validate, and manipulate XML. You can read and write XML, use XPath to navigate through an XML document, or check to see whether a particular document is valid XML by using the objects in this namespace. In this chapter, I’ve assumed that you’re already familiar with the basics of XML, such as elements and attributes. If you need a refresher course on XML basics, refer to Appendix B, “XML Standards and Syntax.”
Accessing an XML File In this section, you’ll learn how to extract information from an XML file. I’ll start by showing you how you can use the XmlReader object to move through an XML file, extracting information as you go. Then you’ll see how other objects, including the XmlNode and XmlDocument objects, provide a more structured view of an XML file. I’ll work with a very simple XML file named Books.xml that represents three books a computer bookstore might stock. Here’s the raw XML file: Gunderloy, Mike Exam 70-306 Training Guide Que Wildermuth, Shawn Pragmatic ADO.NET Addison-Wesley Burton, Kevin .NET Common Language Runtime Unleashed Sams
Understanding the DOM The Document Object Model, or DOM, is an Internet standard for representing the information contained in an HTML or XML document as a tree of nodes. Like many other Internet standards, the DOM is an official standard
. . . . . . . . . . . . . . . . . . . . . . . . . . . .Accessing . . . . . and . . .Manipulating . . . . . . .XML . . .Data . .
of the World Wide Web Consortium, better known as the W3C. You can find it at www.w3.org/DOM. In its simplest form, the DOM defines an XML document as consisting as a tree of nodes. The root element in the XML file becomes the root node of the tree, and other elements become child nodes. The DOM provides the standard for constructing this tree, including a classification for individual nodes and rules for which nodes can have children. In the DOM, attributes are not represented as nodes within the tree. Rather, attributes are considered to be properties of their parent elements. You’ll see later in the chapter that this is reflected in the classes provided by the .NET Framework for reading XML files.
Using an XmlReader Object The XmlReader class is designed to provide forward-only, read-only access to an XML file. This class treats an XML file similar to the way a cursor treats a resultset from a database. At any given time, there is one current node within the XML file, represented by a pointer that you can move around within the file. The class implements a Read method that returns the next XML node to the calling application. The XmlReader class has many other members, as shown in Table 3.1. Table 3.1 Important Members of the XmlReader Class Member
Type
Description
Depth
Property
The depth of the current node in the XML document
EOF
Property
A Boolean property that is True when the current node pointer is at the end of the XML file
GetAttribute
Method
Gets the value of an attribute
HasAttributes
Property
True when the current node contains attributes
HasValue
Property
True when the current node is a type that has a Value property
IsEmptyElement
Property
True when the current node represents an empty XML element
IsStartElement
Method
Determines whether the current node is a start tag
Item
Property
An indexed collection of attributes for the current node (if any) (continued)
59
60
Chapter . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Table 3.1 Important Members of the XmlReader Class (continued) Member
Type
Description
MoveToElement
Method
Moves to the element containing the current attribute
MoveToFirstAttribute
Method
Moves to the first attribute of the current element
MoveToNextAttribute
Method
Moves to the next attribute
Name
Property
The qualified name of the current node
NodeType
Property
The type of the current node
Read
Method
Reads the next node from the XML file
Skip
Method
Skips the children of the current element
Value
Property
The value of the current node
The XmlReader class is a purely abstract class. That is, this class is marked with the MustInherit modifier; you cannot create an instance of XmlReader in your own application. Generally, you’ll use the XmlTextReader class instead. The XmlTextReader class implements XmlReader for use with text streams. Here’s how you might use this class to dump the nodes of an XML file to a ListBox control: Private Sub btnReadXml_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnReadXML.Click Dim intI As Integer Dim intJ As Integer Dim strNode As String ‘ Create a new XmlTextReader on the file Dim xtr As XmlTextReader = _ New XmlTextReader(“Books.xml”) ‘ Walk through the entire XML file Do While xtr.Read If (xtr.NodeType = XmlNodeType.Element) Or _ (xtr.NodeType = XmlNodeType.Text) Then strNode = “” For intI = 1 To xtr.Depth strNode &= “ “ Next strNode = strNode & xtr.Name & “ “ strNode &= xtr.NodeType.ToString If xtr.HasValue Then strNode = strNode & “: “ & xtr.Value End If lbNodes.Items.Add(strNode) ‘ Now add the attributes, if any If xtr.HasAttributes Then While xtr.MoveToNextAttribute strNode = “” For intI = 1 To xtr.Depth strNode &= “ “ Next strNode = strNode & xtr.Name & “ “ strNode &= xtr.NodeType.ToString
. . . . . . . . . . . . . . . . . . . . . . . . . . . .Accessing . . . . . and . . .Manipulating . . . . . . .XML . . .Data . . If xtr.HasValue Then strNode = strNode & “: “ & _ xtr.Value End If lbNodes.Items.Add(strNode) End While End If End If Loop ‘ Clean up xtr.Close() End Sub
Figure 3.1 shows the view of the sample Books.xml file produced by this code.
Figure 3.1 An XML file translated into schematic form by an XmlTextReader object. This and other examples in this chapter assume that the XML file is located in the bin folder of your Visual Basic .NET project.
The DOM includes nodes for everything in the XML file, including the XML declaration and any whitespace (such as the line feeds and carriage returns that separate lines of the files). On the other hand, the node tree doesn’t include XML attributes, though you can retrieve them from the parent elements. However, the DOM and the XmlTextReader are flexible enough that you can customize their work as you like. Note the use of the NodeType property and the MoveToNextAttribute method in this example to display just the elements, text nodes, and attributes from the file.
61
62
Chapter . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Alternatively, you can retrieve attributes by using the Item property of the XmlTextReader. If the current node represents an element in the XML file, the following code will retrieve the value of the first attribute of the element: xtr.Items(0)
This code will retrieve the value of an attribute named Page: xtr.Item(“Page”)
The XMLNode Class The code you saw in the previous example deals with nodes as part of a stream of information returned by the XmlTextReader object. But the .NET Framework also includes another class, XmlNode, that can be used to represent an individual node from the DOM representation of an XML document. If you instantiate an XmlNode object to represent a particular portion of an XML document, you can alter the properties of the object and then write the changes back to the original file. The DOM provides two-way access to the underlying XML in this case. In addition to XmlNode, the System.Xml namespace also contains a set of classes that represent particular types of nodes: XmlAttribute, XmlComment, XmlElement, and so on. These classes all inherit from the XmlNode class.
The XmlNode class has a rich interface of properties and methods. You can retrieve or set information about the entity represented by an XmlNode object, or you can use its methods to navigate the DOM. Table 3.2 shows the important members of the XmlNode class. Table 3.2 Important Members of the XmlNode Class Member
Type
Description
AppendChild
Method
Adds a new child node to the end of this node’s list of children
Attributes
Property
Returns the attributes of the node as an XmlAttributeCollection
ChildNodes
Property
Returns all child nodes of this node
CloneNode
Method
Creates a duplicate of this node
FirstChild
Property
Returns the first child node of this node
HasChildNodes
Property
True if this node has any children
InnerText
Property
The value of the node and all its children (continued)
. . . . . . . . . . . . . . . . . . . . . . . . . . . .Accessing . . . . . and . . .Manipulating . . . . . . .XML . . .Data . . Table 3.2 Important Members of the XmlNode Class (continued) Member
Type
Description
InnerXml
Property
The markup representing only the children of this node
InsertAfter
Method
Inserts a new node after this node
InsertBefore
Method
Inserts a new node before this node
LastChild
Property
Returns the last child node of this node
Name
Property
The name of the node
NextSibling
Property
Returns the next child of this node’s parent node
NodeType
Property
The type of this node
OuterXml
Property
The markup representing this node and its children
OwnerDocument
Property
The XmlDocument object that contains this node
ParentNode
Property
Returns the parent of this node
PrependChild
Method
Adds a new child node to the beginning of this node’s list of children
PreviousSibling
Property
Returns the previous child of this node’s parent node
RemoveAll
Method
Removes all children of this node
RemoveChild
Method
Removes a specified child of this node
ReplaceChild
Method
Replaces a child of this node with a new node
SelectNodes
Method
Selects a group of nodes matching an XPath expression
SelectSingleNode
Method
Selects the first node matching an XPath expression
WriteContentTo
Method
Writes all children of this node to an XmlWriter object
WriteTo
Method
Writes this node to an XmlWriter
The XmlDocument Class You can’t directly create an XmlNode object that represents an entity from a particular XML document. Instead, you can retrieve XmlNode objects from an XmlDocument object. The XmlDocument object represents an entire XML document. By combining the XmlNode and XmlDocument objects, you can navigate through the DOM representation of an XML document. For example, you can recursively dump the contents of an XML file to a ListBox control with this code: Private Sub btnReadXML_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnReadXML.Click Dim intI As Integer Dim intJ As Integer Dim strNode As String ‘ Create a new XmlTextReader on the file Dim xtr As XmlTextReader = _ New XmlTextReader(“Books.xml”)
63
64
Chapter . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ‘ Load the XML file to an XmlDocument xtr.WhitespaceHandling = WhitespaceHandling.None Dim xd As XmlDocument = New XmlDocument() xd.Load(xtr) ‘ Get the document root Dim xnodRoot As XmlNode = xd.DocumentElement ‘ Walk the tree and display it Dim xnodWorking As XmlNode If xnodRoot.HasChildNodes Then xnodWorking = xnodRoot.FirstChild While Not IsNothing(xnodWorking) AddChildren(xnodWorking, 0) xnodWorking = xnodWorking.NextSibling End While End If ‘ Clean up xtr.Close() End Sub Private Sub AddChildren(ByVal xnod As XmlNode, _ ByVal Depth As Integer) ‘ Add this node to the listbox Dim strNode As String Dim intI As Integer Dim intJ As Integer Dim atts As XmlAttributeCollection ‘ Only process Text and Element nodes If (xnod.NodeType = XmlNodeType.Element) Or _ (xnod.NodeType = XmlNodeType.Text) Then strNode = “” For intI = 1 To Depth strNode &= “ “ Next strNode = strNode & xnod.Name & “ “ strNode &= xnod.NodeType.ToString strNode = strNode & “: “ & xnod.Value lbNodes.Items.Add(strNode) ‘ Now add the attributes, if any atts = xnod.Attributes If Not atts Is Nothing Then For intJ = 0 To atts.Count - 1 strNode = “” For intI = 1 To Depth + 1 strNode &= “ “ Next strNode = strNode & _ atts(intJ).Name & “ “ strNode &= atts(intJ).NodeType.ToString strNode = strNode & “: “ & _ atts(intJ).Value lbNodes.Items.Add(strNode) Next End If ‘ And recursively walk ‘ the children of this node Dim xnodworking As XmlNode If xnod.HasChildNodes Then xnodworking = xnod.FirstChild While Not IsNothing(xnodworking) AddChildren(xnodworking, Depth + 1) xnodworking = xnodworking.NextSibling
. . . . . . . . . . . . . . . . . . . . . . . . . . . .Accessing . . . . . and . . .Manipulating . . . . . . .XML . . .Data . . End While End If End If End Sub
The XmlDocument class includes a number of other useful members. Table 3.3 lists the most important of these. Table 3.3 Important Members of the XmlDocument Class Member
Type
Description
CreateAttribute
Method
Creates an attribute node
CreateElement
Method
Creates an element node
CreateNode
Method
Creates an XmlNode object
DocumentElement
Property
Returns the root XmlNode for this document
DocumentType
Property
Returns the node containing the DTD declaration for this document, if it has one
ImportNode
Method
Imports a node from another XML document
Load
Method
Loads an XML document into the XmlDocument
LoadXml
Method
Loads the XmlDocument from a string of XML data
NodeChanged
Event
Fires after the value of a node has been changed
NodeChanging
Event
Fires when the value of a node is about to be changed
NodeInserted
Event
Fires when a new node has been inserted
NodeInserting
Event
Fires when a new node is about to be inserted
NodeRemoved
Event
Fires when a node has been removed
NodeRemoving
Event
Fires when a node is about to be removed
PreserveWhitespace Property
True if whitespace in the document should be preserved when loading or saving the XML
Save
Method
Saves the XmlDocument as a file or stream
WriteTo
Method
Saves the XmlDocument to an XmlWriter
The XmlDataDocument Class The System.Xml namespace also includes the capability to automatically synchronize a DataSet with an equivalent XML file. The XmlDocument class is useful for working with XML via the DOM, but it’s not a dataenabled class. To bring the DataSet class into the picture, you need to use an XmlDataDocument class, which inherits from the XmlDocument class. Table 3.4 shows the additional members the XmlDataDocument class adds to the XmlDocument class.
65
66
Chapter . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Table 3.4 Additional Members of the XmlDataDocument Class Member
Type
Description
DataSet
Property
Retrieves a DataSet representing the data in the XmlDataDocument
GetElementFromRow
Method
Retrieves an XmlElement representing a specified DataRow
GetRowFromElement
Method
Retrieves a DataRow representing a specified XmlElement
Load
Method
Loads the XmlDataDocument and synchronizes it with a DataSet
The XmlDataDocument class allows you to exploit the connections between XML documents and DataSets. You can do this by synchronizing the XmlDataDocument (and hence the XML document that it represents) with a particular DataSet. You can start the synchronization process with any of the following objects: ➤ An XmlDataDocument ➤ A full DataSet ➤ A schema-only DataSet
If you have an XML file in an XmlDataDocument object, you can retrieve a DataSet object from its DataSet property. Here’s how you might load a DataSet using this technique: ‘ Create a new XmlTextReader on a file Dim xtr As XmlTextReader = _ New XmlTextReader(“Books.xml”) ‘ Create an object to synchronize Dim xdd As XmlDataDocument = New XmlDataDocument() ‘ Retrieve the associated DataSet Dim ds As DataSet = xdd.DataSet ‘ Initialize the DataSet by reading the schema ‘ from the XML document ds.ReadXmlSchema(xtr) ‘ Reset the XmlTextReader xtr.Close() xtr = New XmlTextReader(“Books.xml”) ‘ Tell it to ignore whitespace xtr.WhitespaceHandling = WhitespaceHandling.None ‘ Load the synchronized object xdd.Load(xtr)
This code performs some extra setup to make sure the DataSet can hold the data from the XmlDataDocument. Even when you’re creating the DataSet from the XmlDataDocument, you must still explicitly create the schema of the DataSet before it will contain data. That’s because in this technique, you
. . . . . . . . . . . . . . . . . . . . . . . . . . . .Accessing . . . . . and . . .Manipulating . . . . . . .XML . . .Data . .
can also use a DataSet that represents only a portion of the XmlDataDocument. In this case, the code takes advantage of the ReadXmlSchema method of the DataSet object to automatically construct a schema that matches the XML document. Because the XmlTextReader object is designed for forward-only use, the code closes and reopens this object after reading the schema so that it can also be used to read the data. When you use the ReadXmlSchema method of the DataSet object to construct an XML schema for the DataSet, both elements and attributes within the XML document become DataColumn objects in the DataSet.
A second way to end up with a DataSet synchronized to an XmlDataDocument is to start with a DataSet. To use this technique, you simply pass the DataSet (which you have already filled with data) to the XmlDataDocument object’s constructor: ‘ Fill the DataSet SqlDataAdapter1.Fill(DsCustomers, “Customers”) ‘ Retrieve the associated document Dim xdd As XmlDataDocument = _ New XmlDataDocument(DsCustomers)
The third method to synchronize the two objects is to follow a three-step recipe: 1. Create a new DataSet with the proper schema to match an XML docu-
ment, but no data. 2. Create the XmlDataDocument from the DataSet. 3. Load the XML document into the XmlDataDocument.
One way to manage this is to use an XML schema file. An XML schema file describes the format of an XML file. For example, here’s an XML schema description of Books.xml:
67
68
Chapter . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Given this schema file, with a name such as Books.xsd, you can construct the corresponding DataSet by calling the ReadXmlSchema method of a DataSet object and from there create the corresponding XmlDataDocument: ‘ Create a dataset with the desired schema Dim ds As DataSet = New DataSet() ds.ReadXmlSchema(“Books.xsd”) ‘ Create a matching document Dim xd As XmlDataDocument = _ New XmlDataDocument(ds) ‘ Load the XML xd.Load(“Books.xml”)
The advantage to using this technique is that you don’t have to represent the entire XML document in the DataSet schema; the schema only needs to include the XML elements you want to work with. For example, in this case the DataSet does not contain the Publisher column, even though the XmlDataDocument includes that column (as you can verify by inspecting the information in the ListBox control).
Understanding XPath To pass the exam, you should also have a basic knowledge of XPath. You can think of XPath as being a query language, conceptually similar to SQL. Just as SQL allows you to select a set of information from a table or group of tables, XPath allows you to select a set of nodes from the DOM representation of an XML document. By writing an appropriate XPath expression, you can select particular elements or attributes within an XML document.
The XPath Language XPath starts with the notion of current context. The current context defines the set of nodes that will be inspected by an XPath query. In general, there are four choices to specify the current context for an XPath query: ➤
./—Uses
the current node as the current context
➤ /—Uses the root of the XML document as the current context
. . . . . . . . . . . . . . . . . . . . . . . . . . . .Accessing . . . . . and . . .Manipulating . . . . . . .XML . . .Data . . ➤
.//—Uses
➤
//—Uses
the entire XML hierarchy starting with the current node as the current context the entire XML document as the current context
To identify a set of elements using XPath, you use the path down the tree structure to those elements, separating tags by forward slashes. For example, this XPath expression selects all the Author elements in the Books.xml file: /Books/Book/Author
You can also select all the Author elements without worrying about the full path to get to them by using this expression: //Author
You can use an asterisk (*) as a wildcard at any level of the tree. So, for example, the following expression selects all the Author nodes that are grandchildren of the Books node: /Books/*/Author
XPath expressions select a set of elements, not a single element. Of course, the set might only have a single member, or no members at all. In the context of the XmlDocument object, an XPath expression can be used to select a set of XmlNode objects to operate on later. To identify a set of attributes, you trace the path down the tree to the attributes, just as you do with elements. The only difference is that attribute names must be prefixed with the @ character. For example, this XPath expression selects all the Pages attributes from Book elements in the Books.xml file: //Book/@Pages
Of course, in the Books.xml file, only Book elements have a Pages attribute. So in this particular context, the following XPath expression is equivalent to the previous one: //@Pages
You can select multiple attributes with the @* operator. To select all attributes of Book elements anywhere in the XML, use this expression: //Book/@*
XPath also offers a predicate language to allow you to specify smaller groups of nodes or even individual nodes in the XML tree. You might think of this as a filtering capability similar to a SQL WHERE clause. One thing you can do
69
70
Chapter . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
is specify the exact value of the node you’d like to work with. To find all Publisher nodes with the value “Que,” you could use the following XPath expression: /Books/Book/Publisher[.=”Que”]
Here, the dot operator stands for the current node. Alternatively, you can find all books published by Que: /Books/Book[./Publisher=”Que”]
Note that there is no forward slash between an element and a filtering expression in XPath. Of course, you can filter on attributes as well as elements. You can also use operators and Boolean expressions within filtering specifications. For example, you might want to find books that have 1,000 or more pages: /Books/Book[./@Pages>=1000]
Because the current node is the default context, you can simplify this expression a little bit: /Books/Book[@Pages>=1000]
XPath also supports a selection of filtering functions. For example, to find books whose title starts with A, you could use this XPath expression: /Books/Book[starts-with(Title,”A”)]
Table 3.5 lists some additional XPath functions. Table 3.5 Selected XPath Functions Function
Description
concat
Concatenates strings
contains
Determines whether one string contains another
count
Counts the number of nodes in an expression
last
The last element in a collection
normalize-space
Removes whitespace from a string
not
Negates its argument
number
Converts its argument to a number
position
The ordinal of a node within its parent
starts-with
Determines whether one string starts with another
string-length
Returns the number of characters in a string
substring
Returns a substring from a string
. . . . . . . . . . . . . . . . . . . . . . . . . . . .Accessing . . . . . and . . .Manipulating . . . . . . .XML . . .Data . .
Square brackets are also used to indicate indexing. Collections are indexed starting at one. To return the first Book node, you’d use this expression: /Books/Book[1]
To return the first author in the XML file (knowing that authors are children of books in this file), regardless of the book, you’d use this expression: (/Books/Book/Author)[1]
The parentheses are necessary because the square brackets have a higher operator precedence than the path operators. Without the brackets, the expression would return the first author of every book in the file. There’s also the last() function, which you can use to return the last element in a collection, without needing to know how many elements are in the collection: /Books/Book[last()]
Another useful operator is the vertical bar, which is used to form the union of two sets of nodes. This expression returns all the authors for books published by Addison-Wesley or Que: /Books/Book[./Publisher=”Addison-Wesley”]/Author| /Books/Book[./Publisher=”Que”]/Author
One way to see XPath in action is to use the SelectNodes method of the XmlDocument object. Here’s how you could load the Books.xml file and select nodes matching a particular XPath expression: ‘ Load the Books.xml file Dim xtr As XmlTextReader = _ New XmlTextReader(“Books.xml”) xtr.WhitespaceHandling = WhitespaceHandling.None Dim xd As XmlDocument = _ New XmlDocument() xd.Load(xtr) ‘ Retrieve nodes to match the expression Dim xnl As XmlNodeList = _ xd.DocumentElement.SelectNodes(“//Books/Book/Title”)
The SelectNodes method of the XmlDocument takes an XPath expression and evaluates that expression over the document. The resulting nodes are returned in an XmlNodeList object, which is just a collection of XML nodes.
Using the XPathNavigator Class You’ve seen how you can use the XmlReader class to move through an XML document. But the XmlReader allows only forward-only, read-only access to the document. The System.Xml.XPath namespace contains another set of
71
72
Chapter . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
navigation classes. In particular, the XPathNavigator class provides you with read-only, random access to XML documents. You can perform two distinct tasks with an XPathNavigator object: ➤ Selecting a set of nodes with an XPath expression ➤ Navigating the DOM representation of the XML document
Selecting Nodes with XPath To use the XPathNavigator class, you should start with an XmlDocument, XmlDataDocument, or XPathDocument object. In particular, if you’re mainly interested in XPath operations, you should use the XPathDocument class. The XPathDocument class provides a representation of the structure of an XML document that is optimized for query operations. You can construct an XPathDocument object from a URI (including a local filename), a stream, or a reader containing XML. The XPathDocument object has a single method of interest, CreateNavigator (you’ll also find this method on the XmlDocument and XmlDataDocument objects). This method returns an XPathNavigator object that can perform operations with the XML document represented by the XPathDocument object. Table 3.6 lists the important members of the XPathNavigator object. Table 3.6 Important Members of the XPathNavigator Class Member
Type
Description
Clone
Method
Creates a duplicate of this object with the current state
ComparePosition
Method
Compares two XPathNavigator objects to determine whether they have the same current node
Compile
Method
Compiles an XPath expression for faster execution
Evaluate
Method
Evaluates an XPath expression
HasAttributes
Property
Indicates whether the current node has any attributes
HasChildren
Property
Indicates whether the current node has any children
IsEmptyElement
Property
Indicates whether the current node is an empty element
Matches
Method
Determines whether the current node matches an XSLT (Extensible Stylesheet Language Transform) pattern
MoveToFirst
Method
Moves to the first sibling of the current node (continued)
. . . . . . . . . . . . . . . . . . . . . . . . . . . .Accessing . . . . . and . . .Manipulating . . . . . . .XML . . .Data . . Table 3.6 Important Members of the XPathNavigator Class (continued) Member
Type
MoveToFirstAttribute Method
Description Moves to the first attribute of the current node
MoveToFirstChild
Method
Moves to the first child of the current node
MoveToNext
Method
Moves to the next sibling of the current node
MoveToNextAttribute Method
Moves to the next attribute of the current node
MoveToParent
Moves to the parent of the current node
Method
MoveToPrevious
Method
Moves to the previous sibling of the current node
MoveToRoot
Method
Moves to the root node of the DOM
Name
Property
The qualified name of the current node
Select
Method
Selects a set of nodes using an XPath expression
Value
Property
The value of the current node
Unlike the XmlReader class, the XPathNavigator class implements methods such as MovePrevious and MoveParent that can move backward in the DOM. The XPathNavigator class provides random access to the entire XML document.
Like the XmlReader class, the XPathNavigator class maintains a pointer to a current node in the DOM at all times. But the XPathNavigator brings additional capabilities to working with the DOM. For example, you can use this class to execute an XPath query by calling its Select method: ‘ Load the Books.xml file Dim xpd As XPathDocument = _ New XPathDocument(“Books.xml”) ‘ Get the associated navigator Dim xpn As XPathNavigator = _ xpd.CreateNavigator() ‘ Retrieve nodes to match the expression Dim xpni As XPathNodeIterator = _ xpn.Select(“//Books/Book/Title”) ‘ And dump the results lbNodes.Items.Clear() While xpni.MoveNext lbNodes.Items.Add( _ xpni.Current.NodeType.ToString _ & “: “ & xpni.Current.Name & “ = “ & _ xpni.Current.Value) End While
The Select method of the XPathNavigator class returns an XPathNodeIterator object, which lets you visit each member of the selected set of nodes in turn.
73
74
Chapter . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Navigating Nodes with XPath You can also use the XPathNavigator object to move around in the DOM. To see how this works, try following these steps: 1. Open a Visual Basic .NET Windows Application project and add a
new form to the project. 2. Add four Button controls (btnParent,
btnPrevious, btnNext, and btnChild) and a ListBox control named lbNodes to the form.
3. Double-click the Button control to open the form’s module. Add this
line of code at the top of the module: Imports System.Xml.XPath
4. Add code to load an XML document when you load the form: Dim xpd As XPathDocument Dim xpn As XPathNavigator Private Sub StepByStep2_9_Load( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ‘ Load the Books.xml file xpd = New XPathDocument(“Books.xml”) ‘ Get the associated navigator xpn = xpd.CreateNavigator() xpn.MoveToRoot() ListNode() End Sub Private Sub ListNode() ‘ Dump the current node to the listbox lbNodes.Items.Add( _ xpn.NodeType.ToString _ & “: “ & xpn.Name & “ = “ & _ xpn.Value) End Sub
5. Add code to handle events from the Button controls: Private Sub btnParent_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnParent.Click ‘ Move to the parent of the current node If xpn.MoveToParent() Then ListNode() Else lbNodes.Items.Add(“No parent node”) End If End Sub Private Sub btnPrevious_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnPrevious.Click
. . . . . . . . . . . . . . . . . . . . . . . . . . . .Accessing . . . . . and . . .Manipulating . . . . . . .XML . . .Data . . ‘ Move to the previous sibling of the current node If xpn.MoveToPrevious() Then ListNode() Else lbNodes.Items.Add(“No previous node”) End If End Sub Private Sub btnNext_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnNext.Click ‘ Move to the next sibling of the current node If xpn.MoveToNext() Then ListNode() Else lbNodes.Items.Add(“No next node”) End If End Sub Private Sub btnChild_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnChild.Click ‘ Move to the first child of the current node If xpn.MoveToFirstChild() Then ListNode() Else lbNodes.Items.Add(“No child node”) End If End Sub
6. Set the form as the startup form for the project. 7. Run the project and then experiment with the buttons. You’ll find that
you can move around in the DOM, as shown in Figure 3.2.
Figure 3.2 Exploring an XML document with the XPathNavigator.
The XPathNavigator class does not throw an error if you try to move to a nonexistent node. Instead, it returns False from the method call, and the current node remains unchanged.
75
76
Chapter . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Generating and Using XSD Schemas In Chapter 2, “Creating and Manipulating DataSets,” you learned how to create an XSD schema in the Visual Studio .NET user interface by dragging and dropping XML elements from the Toolbox. This method is useful when you need to create a schema from scratch. But there will be times when you want to create a schema to match an existing object. In this section, you’ll learn about the methods that are available to programmatically generate XSD schemas.
Generating an XSD Schema One obvious source for an XML schema is an XML file. An XML file can contain explicit schema information (in the form of an embedded schema), or it can contain implicit schema information in its structure. Here’s a sample file, Products.xml, that contains embedded schema information:
. . . . . . . . . . . . . . . . . . . . . . . . . . . .Accessing . . . . . and . . .Manipulating . . . . . . .XML . . .Data . . 1 Chai
If the file contains explicit schema information, you can use the DataSet object to read that information and create the corresponding schema as a separate file, as shown here: ‘ Load the XML file with inline schema info Dim xtr As XmlTextReader = _ New XmlTextReader(“Products.xml”) ‘ Read the schema (only) into a DataSet Dim ds As DataSet = New DataSet() ds.ReadXmlSchema(xtr) ‘ Write the schema out as a separate stream Dim sw As StringWriter = New StringWriter() ds.WriteXmlSchema(sw) txtSchema.Text = sw.ToString()
The DataSet object must have the capability to read an XML schema so that it can construct a matching data structure in memory. The .NET Framework designers thoughtfully exposed this capability to you through the ReadXmlSchema and WriteXmlSchema methods of the DataSet object. But what if the file does not contain explicit schema information? It turns out that you can still use the DataSet object because this object also has the capability to infer an XML schema based on the data in an XML file. For example, here’s how to use the DataSet object to infer a schema for the Books.xml file: ‘ Load an XML file with no schema information Dim xtr As XmlTextReader = _ New XmlTextReader(“Books.xml”) ‘ Read the schema (only) into a DataSet Dim ds As DataSet = New DataSet() Dim ns As String() ds.InferXmlSchema(xtr, ns) ‘ Write the schema out as a separate stream Dim sw As StringWriter = New StringWriter() ds.WriteXmlSchema(sw) txtSchema.Text = sw.ToString()
You have at least four ways to obtain XSD files for your applications: ➤ You can use a file generated by an external application such as Microsoft
SQL Server or Microsoft Access.
77
78
Chapter . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ➤ You can create your own schema files from scratch using the techniques
you learned in Chapter 2. ➤ You can extract inline schema information from an XML file using the
DataSet.ReadXmlSchema method. ➤ You can infer schema information from an XML file using the
DataSet.InferXmlSchema method.
Using an XSD Schema The prime use of a schema file is to validate the corresponding XML file. Although any XML file that conforms to the syntactical rules for XML is well-formed, this does not automatically make the file valid. A valid XML file is one whose structure conforms to a specification. This specification can be in the form of an XML schema or a Document Type Definition (DTD), for example. Any valid XML file is well-formed, but not every well-formed XML file is valid. The .NET Framework provides good support for validating XML files. To validate an XML document, you can use the XmlValidatingReader class. This class provides an additional layer between the XmlReader and the XmlDocument. The extra layer validates the document as it is read in to the XmlDocument object. To use the XmlValidatingReader object to validate an XML document with an inline schema, you should supply a handler for any validation errors, as in this code sample: Private Sub ValidateIt() ‘ Load a document with an inline schema Dim xtr As XmlTextReader = _ New XmlTextReader(“Products.xml”) ‘ Prepare to validate it Dim xvr As XmlValidatingReader = _ New XmlValidatingReader(xtr) xvr.ValidationType = ValidationType.Schema ‘ Tell the validator what to do with errors AddHandler xvr.ValidationEventHandler, _ AddressOf ValidationHandler ‘ Load the document, thus validating Dim xd As XmlDocument = _ New XmlDocument() xd.Load(xvr) End Sub Private Sub ValidationHandler( _ ByVal sender As Object, _ ByVal e As ValidationEventArgs) ‘ Dump any validation errors to the UI MessageBox.Show(e.Message) End Sub
. . . . . . . . . . . . . . . . . . . . . . . . . . . .Accessing . . . . . and . . .Manipulating . . . . . . .XML . . .Data . .
An inline schema cannot contain an entry for the root element of the document, so even when the document is otherwise valid, you’ll get an error from that node. The XmlValidatingReader class is constructed so that it does not stop on validation errors. Rather, it continues processing the file but raises an event for each error. This enables your code to decide how to handle errors while still filling the XmlDocument object. You can also validate an XML file against an external schema. To do this, you can load the schema and the XML file separately and tell the XmlValidatingReader class to compare one to the other: Private Sub ValidateIt() ‘ Load a document with an external schema Dim xtr As XmlTextReader = _ New XmlTextReader(“Books.xml”) ‘ Prepare to validate it Dim xvr As XmlValidatingReader = _ New XmlValidatingReader(xtr) xvr.ValidationType = ValidationType.Schema ‘ Tell the validator what to do with errors AddHandler xvr.ValidationEventHandler, _ AddressOf ValidationHandler ‘ Load the schema Dim xsc As XmlSchemaCollection = _ New XmlSchemaCollection() xsc.Add(“xsdBooks”, “Books.xsd”) ‘ Tell the validator which schema to use xvr.Schemas.Add(xsc) ‘ Load the document, thus validating Dim xd As XmlDocument = _ New XmlDocument() xd.Load(xvr) End Sub Private Sub ValidationHandler( _ ByVal sender As Object, _ ByVal e As ValidationEventArgs) ‘ Dump any validation errors to the UI MessageBox.Show(e.Message) End Sub
Schema files are not the only way to describe the structure of an XML file. An older standard for specifying structure is the Document Type Definition, or DTD. DTDs are part of the Standard Generalized Markup Language (SGML) standard, from which both HTML and XML derive. A DTD file lists the elements that may appear in an XML file, as in this example (Books.dtd): Book (Author, Title, Publisher) > Book Pages CDATA #REQUIRED> Author (#PCDATA)> Title (#PCDATA)> Publisher (#PCDATA)>
79
80
Chapter . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
To use a DTD file as the schema for an XML file, you include a DOCTYPE node in the XML file: Delaney, Kalen Inside Microsoft SQL Server 2000 Microsoft Press Gunderloy. Michael ADO and ADO.NET Programming Sybex Cooper, James W. Visual Basic Design Patterns Addison Wesley
The XmlValidatingReader class can validate an XML document for conformance with a DTD, as in the following sample code: Private Sub ValidateIt() ‘ Load a document with an external schema Dim xtr As XmlTextReader = _ New XmlTextReader(“Books.xml”) ‘ Prepare to validate it Dim xvr As XmlValidatingReader = _ New XmlValidatingReader(xtr) xvr.ValidationType = ValidationType.DTD ‘ Tell the validator what to do with errors AddHandler xvr.ValidationEventHandler, _ AddressOf ValidationHandler ‘ Load the document, thus validating Dim xd As XmlDocument = _ New XmlDocument() xd.Load(xvr) End Sub Private Sub ValidationHandler( _ ByVal sender As Object, _ ByVal e As ValidationEventArgs) ‘ Dump any validation errors to the UI MessageBox.Show(e.Message) End Sub
The only difference between validating against a schema file and validating against a DTD is in the constant chosen for the ValidationType property of the XmlValidatingReader.
. . . . . . . . . . . . . . . . . . . . . . . . . . . .Accessing . . . . . and . . .Manipulating . . . . . . .XML . . .Data . .
Using XML with SQL Server Over the past several releases, Microsoft SQL Server has become increasingly integrated with XML. In the current release, you can generate XML with SQL statements, using Microsoft T-SQL extensions to the SQL standard query language. You can also update SQL Server tables by sending properly formed XML messages, called DiffGrams, to a SQL Server database. In this section, you learn the basics of interacting with SQL Server via XML.
Generating XML with SQL Statements SQL Server allows you to retrieve the results of any query as XML rather than as a SQL resultset. To do this, you use the Microsoft-specific FOR XML clause. You can use a variety of options in the FOR XML clause to customize the XML that SQL Server generates. The first option is FOR XML RAW. When you use raw mode with FOR XML, SQL Server returns one element (always named row) for each row of the resultset, with the individual columns represented as attributes. For example, consider this query: SELECT Customers.CustomerID, Customers.CompanyName, Orders.OrderID, Orders.OrderDate FROM Customers INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID WHERE Country = ‘Brazil’ AND OrderDate BETWEEN ‘1997-03-15’ AND ‘1997-04-15’ FOR XML RAW
If you execute this query (for example, using SQL Query Analyzer) in the Northwind sample database, you’ll get back these results:
SQL Query Analyzer returns XML results as one long string. I’ve reformatted these results for easier display on the printed page. If you have trouble seeing all the results in SQL Query Analyzer, select Tools, Options, Results and increase the Maximum Characters Per Column setting.
81
82
Chapter . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
The second variant of the FOR XML clause is FOR XML AUTO. When you use auto mode with FOR XML, nested tables in the returned data are represented as nested elements in the XML. Columns are still represented as attributes. For example, here’s a query that uses FOR XML AUTO: SELECT Customers.CustomerID, Customers.CompanyName, Orders.OrderID, Orders.OrderDate FROM Customers INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID WHERE Country = ‘Brazil’ AND OrderDate BETWEEN ‘1997-03-15’ AND ‘1997-04-15’ FOR XML AUTO
Here’s the corresponding returned data:
Note that in this output, the Orders element is nested within the Customers element for each order. If there were multiple orders for a single customer, the Orders element would repeat as many times as necessary. There’s a second variant of FOR XML AUTO. You can include the ELEMENTS option to represent columns as elements rather than as attributes. Here’s a query that uses this option: SELECT Customers.CustomerID, Customers.CompanyName, Orders.OrderID, Orders.OrderDate FROM Customers INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID WHERE Country = ‘Brazil’ AND OrderDate BETWEEN ‘1997-03-15’ AND ‘1997-04-15’ FOR XML AUTO, ELEMENTS
Here’s the corresponding output: RICAR Ricardo Adocicados
. . . . . . . . . . . . . . . . . . . . . . . . . . . .Accessing . . . . . and . . .Manipulating . . . . . . .XML . . .Data . . 10481 1997-03-20T00:00:00 QUEEN Queen Cozinha 10487 1997-03-26T00:00:00 COMMI Comércio Mineiro 10494 1997-04-02T00:00:00 TRADH Tradiçaõ Hipermercados 10496 1997-04-04T00:00:00
The final variant of FOR XML is FOR XML EXPLICIT. In explicit mode, you must construct your query so as to create a resultset with the first column named Tag and the second column named Parent. These columns create a self-join in the results that is used to determine the hierarchy of the created XML file. Here’s a relatively simple query in explicit mode: SELECT 1 AS Tag, NULL AS Parent, Customers.CustomerID AS [Customer!1!CustomerID], Customers.CompanyName AS [Customer!1!CompanyName], NULL AS [Order!2!OrderID], NULL AS [Order!2!OrderDate] FROM Customers WHERE COUNTRY = ‘Brazil’ UNION ALL SELECT 2, 1, Customers.CustomerID, Customers.CompanyName, Orders.OrderID, Orders.OrderDate FROM Customers INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID WHERE Country = ‘Brazil’ AND OrderDate BETWEEN ‘1997-03-15’ AND ‘1997-04-15’ ORDER BY [Customer!1!CustomerID], [Order!2!OrderID] FOR XML EXPLICIT
The resulting XML from this query is as follows:
Note that in this case, even customers without orders in the specified time period are included because the first half of the query retrieves all customers from Brazil. Explicit mode allows you the finest control over the generated XML, but it’s also the most complex mode to use in practice. You should stick to raw or auto mode whenever possible. Finally, you can generate schema information as part of a SQL Server query by including the XMLDATA option in the query. You can do this in any of the FOR XML modes. For example, here’s a query you saw earlier in this section with the XMLDATA option added: SELECT Customers.CustomerID, Customers.CompanyName, Orders.OrderID, Orders.OrderDate FROM Customers INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID WHERE Country = ‘Brazil’ AND OrderDate BETWEEN ‘1997-03-15’ AND ‘1997-04-15’ FOR XML AUTO, ELEMENTS, XMLDATA
The resulting XML is as follows:
. . . . . . . . . . . . . . . . . . . . . . . . . . . .Accessing . . . . . and . . .Manipulating . . . . . . .XML . . .Data . . \ RICAR Ricardo Adocicados 10481 1997-03-20T00:00:00 QUEEN Queen Cozinha 10487 1997-03-26T00:00:00 COMMI Comércio Mineiro 10494 1997-04-02T00:00:00 TRADH Tradiçaõ Hipermercados 10496 1997-04-04T00:00:00
Using ExecuteXmlReader ADO.NET provides a means to integrate SQL Server’s XML capabilities with the .NET Framework classes. The ExecuteXmlReader method of the SqlCommand object allows you to retrieve an XmlReader directly from a SQL statement, provided that the SQL statement uses the FOR XML clause. Here’s an example: Dim cmd As SqlCommand = _ SqlConnection1.CreateCommand
85
86
Chapter . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ‘ Create a command to retrieve XML cmd.CommandType = CommandType.Text cmd.CommandText = _ “SELECT Customers.CustomerID, “ & “Customers.CompanyName,” & _ “Orders.OrderID, Orders.OrderDate “FROM Customers INNER JOIN Orders “ON Customers.CustomerID = “ & _ “Orders.CustomerID “ & _ “WHERE Country = ‘Brazil’ AND “ & “OrderDate BETWEEN ‘1997-03-15’ “ “AND ‘1997-04-15’ “ & _ “FOR XML AUTO, ELEMENTS” SqlConnection1.Open() ‘ Read the XML into an XmlReader Dim xr As XmlReader = _ cmd.ExecuteXmlReader() ‘ Dump the contents of the reader Dim strNode As String Dim intI As Integer Do While xr.Read
_ “ & _ “ & _
_ & _
‘ Do something with the nodes here Loop xr.Close() SqlConnection1.Close()
Updating SQL Server Data by Using XML You can also update SQL Server data by using special XML messages called DiffGrams. You can think of a DiffGram as a before-and-after snapshot of a part of a SQL Server table. The .NET Framework uses DiffGrams internally as a means of serializing changes in a DataSet. For example, if you pass the changes in a DataSet from one tier to another, the .NET Framework will use a DiffGram to send the changes. You can also use DiffGrams yourself to update data in a SQL Server. However, before you can do so, you’ll need to install the SQLXML managed classes, an interface between SQL Server and .NET.
Installing SQLXML Although SQL Server 2000 includes some XML support (for example, the FOR XML syntax is built in to the product), there have been many advances in XML since that version of SQL Server was released. Microsoft has kept SQL Server in tune with these advances by issuing a series of free upgrade packages with the general name of SQLXML. As of this writing, the current release of SQLXML is SQLXML 3.0 SP1. To install SQLXML, you need to download the current release directly from Microsoft’s Web site. You can always find the current release by starting at the SQLXML home page, http://msdn.microsoft.com/sqlxml.
. . . . . . . . . . . . . . . . . . . . . . . . . . . .Accessing . . . . . and . . .Manipulating . . . . . . .XML . . .Data . .
Using DiffGrams After you’ve installed SQLXML, you can use the SqlXmlCommand object to execute a DiffGram. A DiffGram is an XML file that includes changes to a DataSet. Here’s a small example: ALFKI Maria Anderson ALFKI Maria Anders
In this case, the first part of the XML file lists a row in the Customers table and indicates that it has been modified. The second part of the DiffGram contains the original data from the SQL Server table. SQL Server can use this data to find the row to be modified. In addition to the DiffGram, you’ll also need a schema file that maps the element names in the DiffGram back to tables and columns in the SQL Server database. The sql:relation attribute in the schema file indicates the table mapping, whereas the sql:field attributes indicate the field mappings.
87
88
Chapter . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Given these two pieces, you can use SQLXML to apply the DiffGram to a database with code such as this: Private Sub ApplyDiffGram() ‘ Connect to the SQL Server database Dim sxc As SqlXmlCommand = _ New SqlXmlCommand(“Provider=SQLOLEDB;” & _ “Server=(local);database=Northwind;” & _ “Integrated Security=SSPI”) ‘ Set up the DiffGram sxc.CommandType = SqlXmlCommandType.DiffGram sxc.SchemaPath = “diffgram.xsd” sxc.CommandStream = _ New FileStream(“diffgram.xml”, FileMode.Open) ‘ And execute it sxc.ExecuteNonQuery() MessageBox.Show(“Database was updated!”) End Sub
DiffGrams can insert or delete data as well as modify data. For an insertion, the DiffGram will contain the data for the new row and no old data. For a deletion, the DiffGram will contain the row to be deleted but no new row.
. . . . . . . . . . . . . . . . . . . . . . . . . . . .Accessing . . . . . and . . .Manipulating . . . . . . .XML . . .Data . .
Exam Prep Questions Question 1 Your SQL Server database contains employee timesheet information. You want to retrieve some of this information into an XML document. You decide to use the FOR XML T-SQL statement to retrieve the information. Your application requires the EmployeeName and EmployeeNumber database columns to be presented as XML elements. Which clause can you use in your SQL statement? ❍ A. FOR XML AUTO ❍ B. FOR XML RAW ❍ C. FOR XML EXPLICIT ❍ D. FOR XML AUTO, XMLDATA
Answer C is correct. FOR XML EXPLICIT maps columns to elements. Answers A and D are incorrect because the AUTO mode of the FOR XML clause maps columns to attributes rather than elements, unless you include the ELEMENTS modifier. Answer B is incorrect because the RAW mode of the FOR XML clause also maps columns to attributes. The EXPLICIT mode can map columns to elements.
Question 2 You have loaded an XML file that represents orders from a trading partner and are using an XPathNavigator class to navigate through the file. The current node of the XPathNavigator is an node that is empty—that is, this node does not contain any child nodes. Your code calls the MoveFirstChild method of the XPathNavigator object. What is the result? ❍ A. No error occurs. The node remains the current node. ❍ B. No error occurs. The root node of the document becomes the current node. ❍ C. A runtime error is thrown. The root node of the document becomes the current node. ❍ D. A runtime error is thrown. The node remains the current node.
Answer A is correct. The XPathNavigator ignores attempts to move to a nonexistent node. Answers B and C are incorrect because the current node remains unchanged when you try to move to a nonexistent node. Answers C and D are incorrect because no error is thrown when you try to move to a nonexistent node.
89
90
Chapter . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 3 Which of the following operations requires you to have an XML schema file? ❍ A. Updating a SQL Server database by sending a DiffGram through the SQLXML managed classes ❍ B. Writing an XML file to disk with the XmlTextWriter class ❍ C. Validating an XML file with the XmlValidatingReader class ❍ D. Performing an XPath query with the XPathNavigator class
Answer A is correct. The SQLXML managed classes require a schema file to match the DiffGram information to columns in the database. Answer B is incorrect because writing an XML file does not require a schema. Answer C is incorrect because you can validate an XML file against non-schema information such as a DTD. Answer D is incorrect because the XPathNavigator class does not use schema information to perform queries.
Question 4 You have an XML file with the following structure: ... ... ... ... ... ... ...
You want to retrieve all the nodes from this file with the best performance. How should you proceed? ❍ A. Read the XML file into an XmlDataDocument object. Retrieve a DataSet object from the DataSet property of the XmlDataDocument object. Create a DataView object within the DataSet object to return the required nodes. ❍ B. Read the XML file into an XPathDocument object. Use the CreateNavigator method of the XPathDocument object to return an XPathNavigator object. Use an XPath expression with the Select method of the XPathNavigator object to return the required nodes.
. . . . . . . . . . . . . . . . . . . . . . . . . . . .Accessing . . . . . and . . .Manipulating . . . . . . .XML . . .Data . . ❍ C. Read the XML file into an XmlDocument object. Use the CreateNavigator method of the XmlDocument object to return an XPathNavigator object. Use an XPath expression with the Select method of the XPathNavigator object to return the required nodes. ❍ D. Read the XML file into an XPathDocument object. Use the CreateNavigator method of the XPathDocument object to return an XPathNavigator object. Use the Move methods of the XPathNavigator object to move through the document, accumulating the required nodes as you go.
Answer B is correct. The XPathDocument class is optimized to perform XPath operations quickly. Answer A is incorrect because the DataSet object adds unnecessary overhead in this scenario. Answer C is incorrect because the XmlDocument object is not designed to support fast XPath queries. Answer D is incorrect because querying for the required nodes is faster than visiting all the nodes.
Question 5 Your application contains an XML file, Employees.xml, with the following content: John Farrel Melanie Runnion
Your application also contains a form with a Button control named btnProcess and a ListBox control named lbNodes. The event handler for the Button control has this code: Private Sub btnProcess_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnProcess.Click Dim xtr As XmlTextReader = _ New XmlTextReader(“Employees.xml”) Do While xtr.Read If (xtr.NodeType = _
91
92
Chapter . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
XmlNodeType.Attribute) _ Or (xtr.NodeType = _ XmlNodeType.Element) _ Or (xtr.NodeType = _ XmlNodeType.Text) Then If xtr.HasValue Then lbnodes.Items.Add( _ xtr.Value) End If End If Loop xtr.Close() End Sub
What will be the contents of the ListBox control after you click the Button control? ❍ A. 4 7
❍ B. 4 John Farrel 7 Melanie Runnion
❍ C. John Farrel Melanie Runnion
❍ D. Employees Employee 4 EmployeeName John Farrel Employee 7 EmployeeName Melanie Runnion
Answer C is correct. The Value property refers only to the actual data within XML elements. Answers A and B are incorrect because XML attributes are not treated as nodes within the DOM. Answer D is incorrect because it includes element names, which are not treated as values.
. . . . . . . . . . . . . . . . . . . . . . . . . . . .Accessing . . . . . and . . .Manipulating . . . . . . .XML . . .Data . .
Question 6 Your application loads an XML file selected by the user and then allows him to move through the XML file. You need to allow the user to move up to the parent node, over to the next node, or down to the first child node, by selecting choices on the user interface. Which object can you use to implement this requirement? ❍ A. XPathNavigator ❍ B. XmlReader ❍ C. XPathExpression ❍ D. XmlDataDocument
Answer A is correct. The XPathNavigator class provides random navigation through an XML document. Answer B is incorrect because the XmlReader class provides forward-only access to the XML document. Answer C is incorrect because the XPathExpression class represents a single XPath expression, not an XML document. Answer D is incorrect because the XmlDataDocument class is used to synchronize an XML document and a DataSet but does not provide random access to the XML document.
Question 7 You load an XML file of employee information into an XmlDataDocument object and then retrieve the DataSet from that object. The name of the first employee as stored in the XML file is “James Doe.” In the DataSet, you change the value of the EmployeeName column of the first employee to “John Doe.” After that, in the XmlDataDocument object, you change the value of the corresponding Node to “James Doe Jr.” Finally, you call the AcceptChanges method of the DataSet object. What is the value of the first EmployeeName in the XmlDataDocument after taking these actions? ❍ A. James Doe. ❍ B. John Doe. ❍ C. James Doe Jr. ❍ D. The value is undefined because an error occurs.
Answer C is correct. The XmlDataDocument object and its corresponding DataSet object present two views of the exact same data, so changes to either one affect the other. Answer A is incorrect because the original value has been changed twice. Answer B is incorrect because the DataSet change gets overwritten by the XmlDataDocument change. Answer D is incorrect because you can make as many changes as you like without throwing an error.
93
94
Chapter . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 8 One of your company’s suppliers has delivered a new parts list to you in the form of an XML file without an inline schema. You’d like to create an XML schema file that corresponds to this XML file. How can you do this with the least effort? ❍ A. Import the XML file to a SQL Server database and then use drag and drop from the Server Explorer to the schema designer within Visual Studio .NET. ❍ B. Use the schema designer within Visual Studio .NET to create the schema file by dragging and dropping elements, attributes, keys, and relations. ❍ C. Use the DataSet.ReadXmlSchema method to create the schema information from the XML file. ❍ D. Use the DataSet.InferXmlSchema method to create the schema information from the XML file.
Answer D is correct. The InferXmlSchema method can create a schema file based on the elements and attributes within an XML file. Answers A and B are incorrect because building a schema for an existing file within Visual Studio .NET is more work than letting the DataSet class do it for you. Answer C is incorrect because the ReadXmlSchema method requires embedded schema information.
Question 9 Which of these operations can you perform by sending a DiffGram to SQL Server? [Select all correct answers.] ❑ A. Add new data to a table ❑ B. Delete existing data from a table ❑ C. Execute a stored procedure ❑ D. Update the index on a table
Answers A and B are correct. The DiffGram format is designed to carry information on data changes. You can add new data, delete existing data, or modify existing data with a DiffGram. Answers C and D are incorrect because the DiffGram format doesn’t carry any information on stored procedures or indexes.
. . . . . . . . . . . . . . . . . . . . . . . . . . . .Accessing . . . . . and . . .Manipulating . . . . . . .XML . . .Data . .
Need to Know More? Griffin, John. XML and SQL Server. New Riders, 2002. Gunderloy, Mike. ADO and ADO.NET Programming. Sybex, 2002. Simpson, John E. XPath and XPointer. O’Reilly, 2002. SQL Server Books Online, installed as part of SQL Server 2000. XML.com: http://www.xml.com/. XMLFiles.com DTD Tutorial: http://www.xmlfiles.com/dtd/.
95
4 .NET Remoting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terms you’ll need to understand: ✓ Application domain ✓ Asynchronous call ✓ Channel ✓ Marshalling ✓ Proxy ✓ Synchronous call ✓ Remoting ✓ Runtime host
Techniques you’ll need to master: ✓ Creating a .NET Remoting object ✓ Consuming a .NET Remoting object ✓ Choosing between client-activated and server-activated components ✓ Selecting appropriate channel protocols and formatters ✓ Configuring IIS as an activation agent ✓ Configuring remoting on the client and the server
98
Chapter . . . . .4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
The .NET Framework allows you to create distributed applications in various ways. Two approaches for distributed applications are .NET Remoting and ASP.NET Web services. I’ll discuss .NET Remoting in this chapter and cover ASP.NET Web services in the next two chapters. Remoting gives you a way to invoke an object on another computer via a local proxy object, and it’s well supported in .NET.
Developing Distributed Applications Using the .NET Framework The .NET Framework supplies three namespaces for distributed applications: ➤ The System.Net Namespace—Provides low-level classes that you can use to
“roll your own” distributed protocols ➤ The System.Runtime.Remoting Namespace—Enables communication
between objects in different application domains, whether they are on the same computer or not ➤ The System.Web.Services Namespace—Enables objects in different applica-
tion domains to exchange messages using standard protocols such as HTTP (Hypertext Transfer Protocol) and SOAP (Simple Object Access Protocol) The functionalities offered by .NET Remoting and ASP.NET Web services appear very similar to each other. In fact, ASP.NET Web services are actually built on the .NET Remoting infrastructure. Keep the following in mind when choosing between the two: ➤ You should choose .NET Remoting when both the endpoints (client and
server) of a distributed application are under your control. ➤ You should choose ASP.NET Web services when one of the endpoints
of a distributed application is not under your control.
.NET Remoting Architecture Remoting takes an indirect approach to application domain communication by creating proxy objects, as shown in Figure 4.1. The client and server communicate using the following steps:
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NET . . .Remoting . . . . .
Client Object
Server Object
Proxy
Remoting System
Client Application Domain
Channel
Remoting System
Server Application Domain
Figure 4.1 In this simplified view of .NET Remoting, note that the client and server communicate indirectly through a proxy object.
1. When a client object wants to create an instance of the server object,
the remoting system at the client side instead creates a proxy of the server object. The proxy object lives at the client but behaves just like the remote object; this leaves the client with the impression that the server object is in the client’s process. 2. When the client object calls a method on the server object, the proxy
passes the call information to the remoting system on the client. This remoting system in turn sends the call over the channel to the remoting system on the server. 3. The remoting system on the server receives the call information and,
on the basis of it, invokes the method on the actual object on the server (creating the object if necessary). 4. The remoting system on the server collects all the results of the
method invocation and passes them through the channel to the remoting system on the client. 5. The remoting system at the client receives the response of the server
and returns the results to the client object through the proxy.
99
100 Chapter 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Object Marshalling There are two types of remotable objects: ➤ Marshal-by-value (MBV) objects—These objects are copied and passed out
of the server application domain to the client application domain. ➤ Marshal-by-reference (MBR) objects—These objects are accessed on the
client side using a proxy. The client just holds a reference to these objects.
Marshal-by-Value Objects MBV objects reside on the server. However, when the client invokes a method on the MBV object, the MBV object is serialized, transferred over the network, and restored on the client as an exact copy of the server-side object. The method is then invoked directly on the client. When this happens, the MBV object is no longer a remote object. Any method calls to the object do not require any proxy object or marshalling because the object is locally available. An MBV object can be created by declaring a class with the Serializable attribute. Here’s an example: ‘ Define an MBV remoting object _ Public Class MyMBVObject ‘ Implementation details End Class
Marshal-by-Reference Objects MBR objects are remote objects. They always reside on the server, and all methods invoked on these objects are executed at the server side. The client communicates with the MBR object on the server using a local proxy object that holds the reference to the MBR object. An MBR object can be created by deriving System.MarshalByRefObject class. Here’s an example: ‘ Define an MBR remoting object Public Class MyMBRObject Inherits MarshalByRefObject ‘ Implementation details End Class
from
the
101 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NET . . .Remoting . . . . .
Channels When a client calls a method on a remote object, the details of the method call are transported to the remote object through a channel. The channel object at the receiving end of a channel (the server) listens to a particular protocol using the specified port number, whereas the channel object at the sending end of the channel (the client) sends information to the receiving end using the protocol and port number specified by the channel object on the receiving end. The .NET Framework provides implementations for HTTP and TCP (Transmission Control Protocol) channels. If you want to use a different protocol, you can define your own channel by implementing the IChannelReceiver and IChannelSender interfaces.
Formatters Formatters are the objects used to encode and serialize data into messages before they are transmitted over a channel. The .NET Framework packages two formatter classes for common scenarios—the BinaryFormatter class and the SoapFormatter class. If you want to use a different formatter, you can define your own formatter class by implementing the IFormatter interface. SOAP (Simple Object Access Protocol) is a relatively straightforward, XMLbased protocol for exchanging types and messages between applications. SOAP formatting is an ideal way of communicating between applications that use incompatible architectures. However, SOAP is very verbose. SOAP messages require more bytes to represent data than the equivalent binary messages. Unlike SOAP, the binary format used by the .NET Framework is proprietary and can be understood only within .NET applications. However, as compared to SOAP, the binary format of representing messages is very compact and efficient.
The Relationship Between Channels and Formatters The HTTP channel uses the SOAP formatter as its default formatter. The TCP channel uses the binary formatter as its default formatter.
102 Chapter 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
However, channels are configurable. You can configure the HTTP channel to use the binary formatter or a custom formatter instead of the SOAP formatter. Similarly, the TCP channel can be configured to use the SOAP formatter or a custom formatter instead of the binary formatter. Figure 4.2 compares the various combinations of channels and formatters on a scale of efficiency and compatibility. Channel
Formatter
TCP
Binary
TCP
SOAP
HTTP
Binary
HTTP
SOAP
Efficiency
Interoperability
Figure 4.2 A TCP channel with a binary formatter provides maximum efficiency, whereas an HTTP channel with a SOAP formatter provides maximum interoperability.
Remote Object Activation Only MBR objects can be activated remotely. No remote activation is needed in the case of MBV objects because the MBV object itself is transferred to the client side. There are two types of MBR objects: server-activated objects (SAOs) and client-activated objects (CAOs). Server-activated objects are those remote objects whose lifetime is directly controlled by the server. The remote object is only instantiated (or activated) on the server when the client calls a method on the proxy object. SAOs can be used in SingleCall activation mode or Singleton activation mode. In the SingleCall activation mode, an object is instantiated for the sole purpose of responding to just one client request. After the request is fulfilled, the .NET Remoting framework deletes the object and reclaims its memory. SingleCall objects are inherently stateless. They are a good solution when the overhead of creating the object is not significant, state is not required, and the server needs to support a large number of requests for the object. Because SingleCall objects are stateless, it does not matter which server processes requests for such objects. For this reason, SingleCall activation is ideally suited for load-balanced environments.
103 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NET . . .Remoting . . . . .
In the Singleton activation mode, at most there will be one instance of the remote object, regardless of the number of clients accessing it. Singleton objects are stateful, but the state is globally shared by all its clients. Singleton objects are a good solution when the overhead of creating the object is substantial, state is required, or clients need to share state. Client-activated objects are those remote objects whose lifetime is directly controlled by the client. Client-activated objects are instantiated on the server as soon as the client requests the object to be created. Unlike an SAO, a CAO does not delay the object creation until the first method is called on the object. An instance of a CAO serves only the client responsible for its creation, and the CAO doesn’t get discarded with each request. For this reason, a CAO can maintain state with each client that it is serving, but unlike the Singleton SAO, different CAOs cannot share a common state. CAOs are a good solution when clients need to maintain private state or want complete control over the object. For example, you might implement a remote object that represents a shopping cart on a Web site as a CAO so that each instance of the object has its own private state. Figure 4.3 shows some of the tradeoffs in choosing an activation type. Activation Type
Flexibility
Scalability
SingleCall Server Activation Singleton Server Activation Client Activation
Figure 4.3 SingleCall server activation offers maximum scalability, whereas client activation offers maximum flexibility.
Lifetime Leases A lifetime lease is the period of time that a particular object can be active in memory before the .NET Framework deletes it and reclaims its memory. Both Singleton SAO and CAO use lifetime leases to determine how long they should continue to exist. A lifetime lease is represented using an object that implements the ILease interface defined in the System.Runtime.Remoting.Lifetime namespace.
104 Chapter 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Simply speaking, the lease works as follows: ➤ When an object is created, its lifetime lease (CurrentLeaseTime) is set
using the value of the InitialLeaseTime property (which is 5 minutes by default). ➤ Whenever the object receives a call, its CurrentLeaseTime is reset to
the time specified by the value of the RenewOnCallTime property (which is 2 minutes by default). ➤ The client can also renew a lease for a remote object by directly calling
the ILease.Renew() method. ➤ When the value of CurrentLeaseTime reaches 0, the .NET Framework
contacts any sponsors registered with the lease to check whether they are ready to sponsor renewing the object’s lease. ➤ If the sponsor does not renew the object or the server cannot contact the
sponsor within the duration specified by the SponsorshipTimeout property, the object is marked for garbage collection.
Applying .NET Remoting Although you won’t have to write code for the exam, you should be familiar with the basic code architecture for various remoting tasks. In particular, you should know how to create a remotable class and how to create both serveractivated and client-activated objects from the class.
Creating a Remotable Class Creating a remotable class is simple. All you need to do is to inherit a class from the MarshalByRefObject class. A simple remotable class in a class library might look like this: Public Class RandomNumber Inherits MarshalByRefObject Private r As System.Random Public Sub New() r = New System.Random() End Sub Public Function NextRandom(ByVal Max As Integer) As Integer NextRandom = r.Next(Max) End Function End Class
105 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NET . . .Remoting . . . . .
If you’d like to follow along with the examples, create this class in a class library named RemotableClass and compile it.
Creating a Server-Activated Object A remotable class is usually connected with the remoting framework through a separate server program. The server program needs to take these steps: 1. Create a server channel that listens on a particular port to the incom-
ing object-activation requests from other application domains. 2. Register the channel with the remoting framework. This tells the
framework which requests should be directed to this particular server. 3. Register the remotable class with the remoting framework. This tells
the framework which classes this particular server can create for remote clients. Normally, you’ll use an existing Windows service, such as Internet Information Services (IIS), or a new Windows service to host remoting objects. But you can also use a simple Windows Forms or console application for this purpose.
Registering a Remotable Class As a Server-Activated Object Using the SingleCall Activation Mode Follow these steps to create a server that exposes the RandomNumber class as a SingleCall SAO: 1. Add a new Visual Basic .NET Console application named
RandomSingleCall to the solution. 2. Add references to the RemotableClass class library and to
System.Runtime.Remoting. 3. Replace the code in the default module of the new project: Imports Imports Imports Imports
RemotableClass System.Runtime.Remoting System.Runtime.Remoting.Channels System.Runtime.Remoting.Channels.Tcp
Module SingleCallServer Public Sub Main() ‘ Create and Register a TCP server channel ‘ that listens on port 50001 Dim channel As TcpServerChannel = _ New TcpServerChannel(50001) ChannelServices.RegisterChannel(channel)
106 Chapter 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ‘ Register the service that publishes ‘ RandomNumber for remote access in SingleCall mode RemotingConfiguration. _ RegisterWellKnownServiceType( _ GetType(RemotableClass.RandomNumber), “RandomNumber”, _ WellKnownObjectMode.SingleCall) ‘ Keep the server loaded Console.WriteLine(“Started server in the “ & _ “SingleCall mode”) Console.WriteLine(“Press to terminate “ & _ “server...”) Console.ReadLine() End Sub End Module
4. Right-click the project in the Solution Explorer and select Properties.
Change the Startup object to SingleCallServer. 5. Build the project. If a remoting application will run entirely on your company’s network, you can safely use a port in the private port range of 49152 through 65535—provided, of course, that the port number you choose is not used by any other internal application. In case you are distributing the application, you should get a port number registered with the Internet Assigned Numbers Authority (IANA). You can see a list of already assigned port numbers at www.iana.org/assignments/port-numbers.
Instantiating and Invoking a Server-Activated Object At this stage, you have a remotable object as well as a remoting server ready. Now it’s time for a remoting client. In overview, a remoting client must take these steps: 1. Create and register a client channel that is used by the remoting
framework to send messages to the remoting server. 2. Register the remotable class as a valid type in the client’s application
domain. 3. Instantiate the SAO on the server. You can only instantiate an SAO at the client side using its default constructor.
Here’s a remoting client that works with the simple SingleClass server you just created:
107 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NET . . .Remoting . . . . . 1. Add a new Visual Basic .NET Windows Application named
ClientSingleCall to the solution. 2. Add references to the RemotableClass class library and to
System.Runtime.Remoting. 3. Add a TextBox control named
txtMax, a Button control named and a Label control named lblRandom to the default form in the project. btnGetRandom,
4. Add the following directives to the form’s module: Imports Imports Imports Imports
System.Runtime.Remoting System.Runtime.Remoting.Channels System.Runtime.Remoting.Channels.Tcp RemotableClass
5. Enter this code to handle events on the form: Dim r As RandomNumber Private Sub Form1_Load( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ‘ Register a TCP client channel Dim channel As TcpClientChannel = _ New TcpClientChannel() ChannelServices.RegisterChannel(channel) ‘ Register the remote class as a valid ‘ type in the client’s application domain RemotingConfiguration. _ RegisterWellKnownClientType( _ GetType(RandomNumber), _ “tcp://localhost:50001/RandomNumber”) ‘ Instantiate the remote class r = New RandomNumber() End Sub Private Sub btnGetRandom_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnGetRandom.Click ‘ Call a method on the remote class lblRandom.Text = _ r.NextRandom(Convert.ToInt32(txtMax.Text)) End Sub
6. Right-click the name of the solution in the Solution Explorer window
and select Properties. This opens the Solution Property Pages dialog box. In the dialog box, select the Multiple Startup Projects radio button, select the action Start for RandomSingleCall and ClientSingleCall, and set the action to None for any other projects in the solution. Make sure that RandomSingleCall is placed above
108 Chapter 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ClientSingleCall. If it isn’t already there, click the Move Up and Move Down buttons to get the right order. 7. Build the project. Select Debug, Start to run the project. You should
see a command window displaying a message that the server is started in the SingleCall mode. 8. Shortly afterward, you’ll see a Windows Form for the client program.
Enter a number in the text box and click the Get Random button. The client invokes a method on the remote object and displays the results.
Registering a Remotable Class As a Server-Activated Object Using the Singleton Activation Mode The same remotable object can be activated in different modes without making any changes to the remotable object itself. In the case of SAO, the choice of activation mode is totally with the server. In fact, you only need to change one line of code in the server to register the remotable object as a Singleton object rather than a SingleCall object. The affected line is shown here in bold: Public Sub Main() ‘ Create and Register a TCP server channel ‘ that listens on port 50001 Dim channel As TcpServerChannel = _ New TcpServerChannel(50001) ChannelServices.RegisterChannel(channel) ‘ Register the service that publishes ‘ RandomNumber for remote access in Singleton mode RemotingConfiguration. _ RegisterWellKnownServiceType( _ GetType(RemotableClass.RandomNumber), “RandomNumber”, _ WellKnownObjectMode.Singleton) ‘ Keep the server loaded Console.WriteLine(“Started server in the “ & _ “Singleton mode”) Console.WriteLine(“Press to terminate “ & _ “server...”) Console.ReadLine() End Sub
Creating a Client-Activated Object When exposing a remotable class as a CAO, no changes are required to be made on the remotable class. Instead, you modify the client and the server, changing their interactions with the remoting system.
109 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NET . . .Remoting . . . . .
You’ll have to take the following steps to register a remotable class as a CAO on the server: 1. Create a server channel that listens on a particular port to the incom-
ing object-activation requests from other application domains. 2. Register the channel with the remoting framework. 3. Register the remotable class with the remoting framework. For a
client-activated object, this registration is performed using the RegisterActivatedServiceType() method of the RemotingConfiguration class. Putting the pieces together, here’s how to register the RandomNumber class as a CAO: Public Sub Main() ‘ Create and Register a TCP server channel ‘ that listens on port 50001 Dim channel As TcpServerChannel = _ New TcpServerChannel(50001) ChannelServices.RegisterChannel(channel) ‘ Register the service that publishes ‘ RandomNumber for remote access as a CAO RemotingConfiguration. _ RegisterActivatedServiceType( _ GetType(RandomNumber)) ‘ Keep the server loaded Console.WriteLine(“Started server in the “ & _ “Client activation mode”) Console.WriteLine(“Press to terminate “ & _ “server...”) Console.ReadLine() End Sub
To instantiate and invoke a client-activated object, the remoting client needs to take the following steps: 1. Create and register a client channel used by the remoting framework
to send messages to the remoting server. 2. Register the remotable class as a valid type in the client’s application
domain. This registration is performed using the RegisterActivatedClientType() method of the RemotingConfiguration class. 3. Instantiate the CAO on the server using the desired constructor.
110 Chapter 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . You can instantiate a CAO at the client side using any of its available constructors.
The client code for using the CAO version of the RandomNumber object looks like this: Dim r As RandomNumber Private Sub Form1_Load( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ‘ Register a TCP client channel Dim channel As TcpClientChannel = _ New TcpClientChannel() ChannelServices.RegisterChannel(channel) ‘ Register the remote class as a valid ‘ type in the client’s application domain RemotingConfiguration. _ RegisterActivatedClientType( _ GetType(RandomNumber), “tcp://localhost:50001”) ‘ Instantiate the remote class r = New RandomNumber() End Sub Private Sub btnGetRandom_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnGetRandom.Click ‘ Call a method on the remote class lblRandom.Text = _ r.NextRandom(Convert.ToInt32(txtMax.Text)) End Sub
Using Configuration Files to Configure the Remoting Framework In all the examples so far, I have written code to register the channel and remote object with the remoting framework. This approach to specifying settings is also known as programmatic configuration. Alternatively, you can store the remoting settings in an XML-based configuration file instead of in the code file. Any changes made to the configuration file can be automatically picked up by the program when it executes the next time. The general format of a remoting configuration file is as follows:
111 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NET . . .Remoting . . . . .
A particular configuration file for the RandomNumber object might look like this:
112 Chapter 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
With this file saved as RandomServer.exe.config to the same folder as the executable file for the server (normally the bin folder underneath the server project), the server code could be simplified as follows: Sub Main() ‘ Load remoting configuration RemotingConfiguration.Configure( _ “RandomServer.exe.config”) Console.WriteLine(“Started server”) Console.WriteLine(“Press to terminate “ & _ “server...”) Console.ReadLine() End Sub
The configuration of a remoting client is quite similar to that of a remoting server. However, you’d configure the element of the configuration file instead of the element.
Using IIS As an Activation Agent Rather than run a separate console application to host a remotable object, you may want to use IIS as an activation agent. Using IIS as an activation agent offers the following advantages: ➤ You need not write a separate server program to register the remotable
classes. ➤ You need not worry about finding an available port for your server
application. You can just host the remotable object, and IIS automatically uses the port 80. ➤ IIS can provide other functionality, such as authentication and Secure
Sockets Layer (SSL). The following list specifies what you need to do in order to host a remotable class in IIS: ➤ Place the assembly containing the remotable objects into the \bin direc-
tory of an IIS Web application or place the assembly in the Global Assembly Cache (GAC) on the IIS computer. ➤ Configure the remoting settings by placing the
configuration section into the Web.config file for the Web application. ➤ You should not specify a channel. IIS already listens on port 80.
Specifying a port for a channel causes exceptions to be thrown when new IIS worker processes are started.
113 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NET . . .Remoting . . . . . ➤ The well-known object URI (Uniform Resource Indicator) must end
with the extension .rem or .soap because these are the two extensions registered with both IIS (via the aspnet_isapi.dll) and the remoting system (in machine.config). When creating IIS-hosted remote objects, you cannot specify constructor parameters. Therefore, activating CAO is not possible using IIS.
IIS Activation only supports the HTTP channel. The default formatting is SOAP, but IIS also supports binary and other custom formatting.
Here’s how you can use IIS as an activation agent for the RandomNumber class: 1. Add a new Empty Web Project named RandomWeb to the solution. 2. Add a reference to the RemotableClass project. 3. Add a Web Configuration File to the project. Open the Web.config
file and add the following element inside the element: ...
4. IIS is now hosting RemotableClass.RandomNumber, the remotable
class, as a server-activated object using the Singleton activation mode.
114 Chapter 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
On the client side, you’d invoke the server for the RandomNumber class over the HTTP channel: Private Sub Form1_Load( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ‘ Register a Http client channel Dim channel As HttpClientChannel = _ New HttpClientChannel() ChannelServices.RegisterChannel(channel) ‘ Register the remote class as a valid ‘ type in the client’s application domain RemotingConfiguration. _ RegisterActivatedClientType( _ GetType(RandomNumber), _ “http://localhost/RandomWeb/RandomNumber.rem”) ‘ Instantiate the remote class r = New RandomNumber() End Sub
115 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NET . . .Remoting . . . . .
Exam Prep Questions Question 1 You have designed a remotable class named InvoiceDetails. You now want to register this class with the remoting system in such a way that the client program should be able to remotely instantiate objects of this class and invoke methods on it. You want there to be only one instance of this class on the server, no matter how many clients connect. Which of the following code snippets fulfills your requirement? ❍ A. RemotingConfiguration. _ RegisterWellKnownServiceType( _ GetType(InvoiceDetails), _ “InvoiceDetails”, _ WellKnownObjectMode.SingleCall)
❍ B. RemotingConfiguration. _ RegisterWellKnownServiceType( GetType(InvoiceDetails), _ “InvoiceDetails”, _ WellKnownObjectMode.Singleton)
_
❍ C. RemotingConfiguration. _ RegisterActivatedServiceType( GetType(InvoiceDetails), _ “InvoiceDetails”)
_
❍ D. RemotingConfiguration. _ RegisterWellKnownClientType( _ GetType(InvoiceDetails), _ “InvoiceDetails”)
Answer B is correct. To share a single object among all client instances, you need a Singleton SAO. To register an SAO, you use the RegisterWellKnownServiceType method. The Singleton object mode flag is necessary to create a Singleton object. Answer A is incorrect because it creates a SingleCall object, which means that the server will instantiate one object for every client request. Answer C is incorrect because the RegisterActivatedServiceType method creates a CAO. Answer D is incorrect because the RegisterWellKnownClientType method is used on the client, not on the server.
116 Chapter 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 2 You are designing a distributed application and want to limit clients of a particular remotable object by requiring a Secure Sockets Layer (SSL) login. Which channels should you use within the System.Remoting framework to achieve this objective? [Select two.] ❑ A. HttpChannel ❑ B. HttpServerChannel ❑ C. TcpChannel ❑ D. TcpServerChannel
Answers A and B are correct. In this case, the client and the server both need to use HTTP for communications, because SSL runs over HTTP. This requires HttpChannel on the client and HttpServerChannel on the server. Answers C and D are incorrect because the TcpChannel and TcpServerChannel classes do not offer any security.
Question 3 You have created a class that you want to make available to client applications via the .NET Remoting framework. The class must use Windows integrated authentication to ensure that only authenticated users instantiate it. How can you meet these requirements while writing as little code as possible? ❍ A. Create a Windows service and use it to host the remotable class. ❍ B. Use Internet Information Services (IIS) as a remoting host. ❍ C. Use a console application as a remoting host. ❍ D. Use a Windows Forms application to host the remotable class.
Answer B is correct. IIS can act as a remoting host for any remotable class, and it already has Windows integrated authentication built in to it. Instead of writing a custom server, you can simply build an application with the proper configuration file to have IIS host your object. Answers A, C, and D are incorrect because they all require you to write custom code.
117 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NET . . .Remoting . . . . .
Question 4 You are developing an application that will make an object available to remote clients. This remotable object will carry details of the individual client’s credit account. You want the client program to have complete control over the creation and lifetime of these objects. Which method of the RemotingConfiguration class should you use to register the remotable class on the server? ❍ A. RegisterWellKnownServiceType ❍ B. RegisterWellKnownClientType ❍ C. RegisterActivatedServiceType ❍ D. RegisterActivatedClientType
Answer C is correct. The RegisterActivatedServiceType method makes an object available as a CAO, which is necessary to fulfill the requirements. Answer A is incorrect because RegisterWellKnownServiceType is used to create an SAO. Answers B and D are incorrect because the ClientType methods are used on the client, not on the server.
Question 5 Which of these applications are good candidates for implementation via the System.Runtime.Remoting namespace? [Select all correct answers.] ❑ A. An application that uses an object hosted on your corporate Web server in divisional financial reporting throughout your company ❑ B. An application that exposes an Inventory object for use by your company’s trading partners ❑ C. An application that allows your employees to submit orders over the Internet from their laptops, using an object named SalesOrder ❑ D. An application that makes Web server statistics available to customers using a variety of operating systems
Answers A and C are correct. Remoting is appropriate when both of the endpoints (client and server) are under your control. Answers B and D are incorrect because in these applications you do not control the platform or operating system of the client computers, making Web services a better choice.
118 Chapter 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 6 You are designing a remoting application that will be used to provide resource information to representatives of your company around the world. These representatives may need to access the server through a firewall, and many of them will be forced to use extremely slow connections. Which channel and formatter combination should you choose in this scenario? ❍ A. The TCP channel with the binary formatter ❍ B. The HTTP channel with the binary formatter ❍ C. The TCP channel with the SOAP formatter ❍ D. The HTTP channel with the SOAP formatter
Answer B is correct. The easiest way to make connections across a firewall is to use the HTTP channel, which will cross most firewalls. Because the clients are on slow connections, it’s important to minimize the amount of data that must be sent. This requires you to use the efficient binary formatter rather than the more verbose SOAP formatter. Answers A and C are incorrect because they use the TCP channel. Answers C and D are incorrect because they use the SOAP formatter.
Question 7 You have designed a remoting application that uses the TCP channel and the SOAP formatter to deliver a marshal-by-reference object to clients. The application uses a custom Windows service as an activation host on the server. Initial testing reveals that the performance of the application needs to be improved. Which of these changes would be most likely to boost the performance? ❍ A. Replace the TCP channel with the HTTP channel. ❍ B. Replace the custom Windows service with IIS. ❍ C. Replace the SOAP formatter with the binary formatter. ❍ D. Replace the marshal-by-reference object with a marshal-by-value object.
Answer C is correct. The binary formatter requires fewer bytes to represent an object than the SOAP formatter. This means that all calls between client and server will be more efficient and performance will be improved. Answer A is incorrect because changing from one protocol to another is unlikely to result in much performance gain. Answer B is incorrect because switching hosts may make it easier to create the host but won’t affect runtime performance. Answer D is incorrect because moving to a marshal-by-value object will require the entire object to be serialized, resulting in a likely decrease in performance.
119 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NET . . .Remoting . . . . .
Question 8 You are creating a remoting application that will be used to allow your sales representatives to input orders by working with a NewOrder object. Part of the logic of this object on the server assigns an order number to each new order, so you want the state of the object to be shared by all clients. Which architecture should you use for this application? ❍ A. An SAO in SingleCall activation mode ❍ B. An SAO in Singleton activation mode ❍ C. A CAO using the binary formatter ❍ D. A CAO using the SOAP formatter
Answer B is correct. Using a Singleton SAO ensures that state is shared between all clients of the object. Answer A is incorrect because a SingleCall SAO does not preserve state at all. Answers C and D are incorrect because CAOs persist private state rather than shared state.
Question 9 Your application uses IIS as an activation host for a remoting object. Which of these factors can you control with settings in the Web.config file? [Select all correct answers.] ❑ A. The protocol used by clients to instantiate the object ❑ B. The port used by clients to instantiate the object ❑ C. The URI used by clients to instantiate the object ❑ D. The activation mode (Singleton or SingleCall) of the object
Answers C and D are correct. You can specify both the activation mode and the URI for the object in the element of the Web.config file. Answers A and B are incorrect because IIS always uses HTTP over port 80 to supply remoting objects.
120 Chapter 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 10 You are designing a distributed application that will be heavily used on your company’s worldwide intranet. After looking at the potential number of clients, you’ve decided that you will need to deploy the servers for the application in a load-balanced Web farm. You also want to minimize the amount of information transferred over the network in order to properly accommodate locations using slow leased lines. You also want to be able to modify the object easily. Which architecture should you use for this application? ❍ A. An SAO in SingleCall activation mode ❍ B. An SAO in Singleton activation mode ❍ C. A CAO using the binary formatter ❍ D. A CAO using the SOAP formatter
Answer A is correct. To accommodate the load-balancing, you require a stateless object. Only the SingleCall activation mode provides a stateless remotable object. Answer B is incorrect because Singleton mode provides you with a single object that cannot be distributed among multiple servers. Answers C and D are incorrect because CAOs require additional traffic over the network and may make it harder to modify the object code.
121 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NET . . .Remoting . . . . .
Need to Know More? Rammer, Ingo. Advanced .NET Remoting. Apress, 2002. List of assigned port numbers: port-numbers.
http://www.iana.org/assignments/
5 Basic Web Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terms you’ll need to understand: ✓ Web service ✓ SOAP (Simple Object Access Protocol) ✓ Disco ✓ UDDI (Universal Description, Discovery, and Integration) ✓ WSDL (Web Services Description Language) ✓ Web method ✓ Web reference
Techniques you’ll need to master: ✓ Creating a .NET Web service ✓ Enabling discovery of a Web service ✓ Instantiating an object from a Web service ✓ Calling a Web method
124 Chapter 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
You’ve probably already heard quite a bit of hype about Web services in conjunction with .NET. You might also run across a lot of complex and confusing explanations of the architecture of these Web services. But at their most basic level, Web services are simple: They are a means for interacting with objects over the Internet. This makes them a natural extension to .NET remoting, which allows objects to interact across processes.
Understanding Web Services The key to understanding Web services is to know something about the protocols that make them possible: ➤ SOAP ➤ UDDI ➤ Disco ➤ WSDL
These protocols use XML messages transmitted over the HTTP protocol. This has two benefits. First, because Web services messages are formatted as XML, they’re reasonably easy for human beings to read and understand. Second, because those messages are transmitted over the pervasive HTTP protocol, they can normally reach any machine on the Internet without worrying about firewalls. As with many rapidly developing technologies, different companies use different names for Web services. Some prefer the capitalized form “Web Services”; others use the explicit “XML Web Services.” In this book, I’ve gone along with the MCAD exam objectives guide, which calls them “Web services.”
SOAP For Web services to manipulate objects through XML messages, there has to be a way to translate objects (as well as their methods and properties) into XML. This translation method is SOAP, which provides a way to encapsulate object calls as XML sent via HTTP. SOAP messages consist of an envelope and a body, each marked with a specific XML tag. A SOAP request goes from the client to the server, and a SOAP response goes from the server back to the client. The request specifies an object and a method to invoke, and the response includes the return value from the method.
125 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Basic . . .Web . . Services . . . . .
Disco and UDDI Before you can use a Web service, you need to know where to find the service. Handling such requests is the job of several protocols, including Disco and UDDI. These protocols allow you to communicate with a Web server to discover the details of the Web services that are available at that server.
WSDL The other prerequisite for using a Web service is knowledge of the SOAP messages that it can receive and send. You can obtain this knowledge by parsing WSDL files. WSDL stands for Web Services Description Language, a standard by which a Web service can tell clients what messages it accepts and which results it will return. WSDL files define everything about the public interface of a Web service: the data types that it can process, the methods that it exposes, and the URLs through which those methods can be accessed. Although UDDI and WSDL files make it possible to interact with Web services without any prior knowledge, these files are not required for a Web service to function. You can make a Web service available on the Internet without any UDDI or WSDL files. In that case, only clients who already know the expected message formats and location of the Web service will be able to use it.
Invoking Your First Web Service Visual Studio .NET makes it easy to invoke a Web service. Follow these steps to see how it works: Web services come and go, and there’s no guarantee that the one I’m using in this chapter will still be available when you test it. If the Airport Weather Web service isn’t available, one good way to find others is to use your favorite search engine to look for the term “Web service examples.”
1. Create a new Visual Basic .NET Windows Application in the Visual
Studio .NET IDE. 2. Right-click the References folder in Solution Explorer and select Add
Web Reference. This opens the Add Web Reference dialog box. 3. Type
http://live.capescience.com/wsdl/AirportWeather.wsdl into the Address bar of the Add Web Reference dialog box and press Enter. This connects to the Airport Weather Web service and downloads information about it to your computer.
126 Chapter 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4. Click the Add Reference button. 5. Add a new Windows Form to your Visual Basic .NET project. 6. Place a Label control, a TextBox control named
txtCode,
a Button control named btnGetSummary, and a ListBox control named lbResults on the form.
7. Double-click the Button control to open the form’s module. Enter this
code to invoke the Web service when the user clicks the button: Private Sub btnGetSummary_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnGetSummary.Click ‘ Connect to the Web service by declaring ‘ a variable of the appropriate type Dim aw As com.capescience.live.AirportWeather = _ New com.capescience.live.AirportWeather() ‘ Call the Web service to get the summary ‘ for the entered airport Dim ws As com.capescience.live.WeatherSummary = _ aw.getSummary(txtCode.Text) ‘ Display some of the properties ‘ filled in by the Web service With lbResults.Items .Clear() .Add(ws.location) .Add(“Temperature: “ & ws.temp) .Add(“Visibility: “ & ws.visibility) .Add(“Wind: “ & ws.wind) End With End Sub
8. Set the form as the startup object for the project. 9. Run the project and fill in a value, such as KSEA or KLAX, for the air-
port code. Click the button. After a brief pause while the Web service is invoked, you’ll see some information in the ListBox control. This information is delivered from the server where the Web service resides as properties of the WeatherSummary object.
Calling a Web Service Asynchronously Depending on the speed of your Internet connection, you might have noticed that the Web service client application takes a long time to reload when you invoke the Web service. That’s because by default the application
127 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Basic . . .Web . . Services . . . . .
uses synchronous methods to communicate with the Web service, waiting for the SOAP response before allowing any other code to execute. But the proxy classes constructed by .NET include asynchronous methods as well. In the .NET Framework, asynchronous Web service calls are managed by callback functions. When you add a Web reference, the proxy class includes “Begin” and “End” methods for each Web method. For example, if the base Web method is named GetSummary, there will be BeginGetSummary and EndGetSummary methods. The Begin method takes all the same parameters as the underlying Web method, plus two others. The first is the address of a callback function, and the second is an object whose properties should be available in the callback function. When you call the Begin method, the .NET Framework launches the call to the Web service in the background. When the Web method call completes, the callback function will be invoked. Within the callback function you can then retrieve the original object and use the corresponding End method to finish the work of using the Web service.
Creating Web Services Visual Studio .NET also makes it easy to create Web services as a type of ASP.NET project.
Creating a Web Service Project To create a Web service, follow these steps: 1. Create a new project in Visual Studio .NET. Select the ASP.NET Web
Service template and name the new project StringProc. 2. Right-click the Service1.asmx file in Solution Explorer and rename it
Strings.asmx. 3. Click the hyperlink on the Strings.asmx design surface to switch to
code view. Change the class name from Service1 to Strings. Enter this code for the class (don’t alter the code generated by the Web services designer): Imports System.Web.Services _ Public Class Strings Inherits System.Web.Services.WebService Public Function ToUpper( _
128 Chapter 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ByVal inputString As String) _ As String ToUpper = inputString.ToUpper() End Function Public Function ToLower( _ ByVal inputString As String) _ As String ToLower = inputString.ToLower() End Function End Class
4. Save the project. 5. Select Build, Build Solution to create the Web service on the server.
The WebService attribute requires you to supply a value for the Namespace property. This value (http://NetExam.org/StringProc, in this example) is purely arbitrary. It doesn’t have to resolve to any actual Web site. This string is just a unique identifier for your Web service. If you leave the default value instead of changing it, you’ll get a warning from Visual Studio .NET.
Testing the Web Service Project Visual Studio .NET includes built-in tools, hosted on an HTML test page, for testing a Web service project without building any client applications for the Web service. Just start your Web Service project in debug mode to launch the test page shown in Figure 5.1.
Figure 5.1 Testing a Web service in debug mode.
On the test page, the Service Description link will display the WSDL for the Web service. Clicking the name of a method (such as ToUpper, in this case) will open a page that lets you interactively test the method.
129 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Basic . . .Web . . Services . . . . .
Customizing the WebMethod Attribute You’ve seen how easy it is to generate a Web service using Visual Studio .NET, simply by marking published methods with the WebMethod attribute. But there are also a number of ways to customize your Web service by adding properties to that attribute. Table 5.1 shows the properties you can use to customize the WebMethod attribute. Table 5.1 Properties of the WebMethod Attribute Property
Meaning
BufferResponse
If this property is set to True (the default), the entire response is buffered by the server and returned to the client as a single message. If it’s set to False, the response is sent in 16KB chunks.
CacheDuration
Specifies the number of seconds that ASP.NET should cache results. The default is zero, which disables caching.
Description
Supplies a description for the Web method.
EnableSession
If this property is set to True, session state for the Web service is enabled. The default is False.
MessageName
Specifies the name by which the method will be called in SOAP messages. The default is the method name.
TransactionOption
If this property is set to TransactionOption.Required or TransactionsOption.RequiredNew, the Web method is allowed to participate as the root object of a transaction. The default is TransactionOption.Disabled.
You should be cautious about using session state in a Web service. Session state can tie up server resources for an extended period of time. If you use session state with a popular Web service, you will apply heavy demands to RAM on your Web server.
Using Web Services Because Web services aren’t installed on your computer, you need some way to determine the messages that they accept and the services that they provide. The usual term for this process is discovery, which encompasses both finding Web services and determining their interfaces. To discover Web services, you use Disco, UDDI, and WSDL.
130 Chapter 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Discovering Web Services with Disco and UDDI Disco is a Microsoft standard for the creation of discovery documents. A Disco document is kept at a standard location on a Web services server and contains paths and other information for retrieving other useful information, such as the WSDL file that describes a service. This document is used for static discovery. That is, a potential user of your Web service must know the location of the Disco document in order to use it. If you require a Disco document in your Web service, you’ll find that the Add New Item dialog box includes a Static Discovery File item to create one. For Visual Studio .NET projects, you won’t ordinarily want to build a Disco document because such projects are designed to generate discovery information from their base URL. For example, if your Web service is named StringProc, is stored on a server with the name HOURGLASS, and has a base class name of strings.asmx, you can retrieve static discovery information by navigating to http://HOURGLASS/StringProc/strings.asmx?wsdl. UDDI (Universal Description, Discovery, and Integration) is a method for finding services by referring to a central directory. These can be Web services, URLs for information, or any other online resource. UDDI registries are sites that contain information available via UDDI; you can search such a registry to find information about Web services. UDDI thus provides dynamic discovery, allowing you to find Web services even when you do not know their location in advance. UDDI registries come in two forms—public and private. A public UDDI registry is available to all comers via the Internet and serves as a central repository of information about Web and other services for businesses. A private UDDI registry follows the same specifications as a public UDDI registry but is located on an intranet for the use of workers at one particular enterprise. To add your own services to a UDDI registry, you must use the tools provided by that particular registry. For example, you can add your Web service to the Microsoft Test UDDI Registry by visiting http://test. uddi.microsoft.com/default.aspx and filling in a registration form.
Using the Web Services Discovery Tool (disco.exe) When you set a Web reference inside of Visual Studio .NET, the software automatically handles the details of discovery for you. But you can also get
131 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Basic . . .Web . . Services . . . . .
into the details of the process yourself. One of the tools included in the .NET Framework SDK (and also in Visual Studio .NET) is the Web Services Discovery Tool, disco.exe. This is a command-line tool that will assist you in the discovery process. For example, you could use this tool with the Airport Weather Web Service by executing this command: disco http://live.capescience.com/wsdl/AirportWeather.wsdl
The tool contacts the Web service and (in this case) creates two files of results: AirportWeather.wsdl and results.discomap. If the Web service includes a static discovery document, the tool will also retrieve that document. The results.discomap file is an XML file that shows you the name of the other file and the URL from which its contents were retrieved. The AirportWeather.wsdl file is an XML file that contains information on the interface of the Web service.
Creating Proxy Classes with the Web Services Description Language Tool (wsdl.exe) The .NET Framework SDK includes the Web Services Description Language Tool, wsdl.exe. This tool can take a WSDL file and generate a corresponding proxy class that you can use to invoke the Web service. Given the .wsdl file from the Airport Weather Web Service, you could use the tool this way: wsdl /language:VB /out:aw.vb AirportWeather.wsdl
The tool reads the WSDL file and creates a new file named aw.vb, which is a proxy class that will enable your applications to use the Web Service. Here’s some code using this class: Private Sub btnGetSummary_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnGetSummary.Click ‘ Connect to the Web service by declaring ‘ a variable of the appropriate type Dim aw As AirportWeather = _ New AirportWeather() ‘ Call the Web service to get the summary ‘ for the entered airport Dim ws As WeatherSummary = _ aw.getSummary(txtCode.Text)
132 Chapter 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ‘ Display some of the properties ‘ filled in by the Web service With lbResults.Items .Clear() .Add(ws.location) .Add(“Temperature: “ & ws.temp) .Add(“Visibility: “ & ws.visibility) .Add(“Wind: “ & ws.wind) End With End Sub
Table 5.2 shows some of the command-line options you can use with wsdl.exe. You don’t need to memorize this material, but you should be familiar with the overall capabilities of the tool. You can use either the path to a local WSDL or Disco file or the URL of a remote WSDL or Disco file with this tool. Table 5.2 Command-Line Options for wsdl.exe Option
Meaning
/domain:DomainName
The domain name to use when connecting to a server that requires authentication.
/language:LanguageCode
Specifies the language for the generated class. The LanguageCode parameter can be CS (for C#, which is the default), VB (for VB .NET), or JS (for JScript).
/namespace:Namespace
Specifies a namespace for the generated class.
/out:Filename
The filename for the generated output. If this is not specified, the filename will be derived from the Web service name.
/password:Password
The password to use when connecting to a server that requires authentication.
/server
Generates an abstract Web service class based on the input file. By default, the tool generates a client proxy object.
/username:Username
The username to use when connecting to a server that requires authentication.
/?
Displays full help on the tool.
Using Web References As an alternative to using the Web Service Discovery Tool and the Web Service Description Language Tool to create explicit proxy classes, you can simply add a Web reference to your project to enable the project to use the Web service, as you saw earlier in this chapter.
133 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Basic . . .Web . . Services . . . . .
In fact, in the end result there’s no difference between using the tools to create a proxy class and adding a Web reference. That’s because, behind the scenes, the Web reference creates its own proxy class. The major difference between this file and the proxy you generated with the Web Services Description Language Tool is that the auto-generated file uses a namespace based on the name of the Web reference. The major benefit of using a Web reference (as compared to constructing proxy classes with the command-line tools) is that it’s easier to update the proxy classes if the Web service changes. All you need to do in that case is right-click the Web Reference node in Solution Explorer and select Update Web Reference.
134 Chapter 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exam Prep Questions Question 1 Your application calls a Web service that performs complex, time-consuming calculations. Users complain that the user interface of the application freezes while it’s recalculating. What can you do to fix this problem? ❍ A. Add more RAM to the computer. ❍ B. Use asynchronous calls to the Web service. ❍ C. Install a faster CPU in the computer. ❍ D. Upgrade your Internet connection.
Answer B is correct. To increase the perceived speed of an application that invokes a Web service, you can use asynchronous calls, which will allow other work to continue while your application is waiting for Web service results. Answers A, B, and D are incorrect because upgrading your computer won’t have any effect on the time that it takes results to come back from a Web service, which is normally hosted on a remote server.
Question 2 You want to use a Web service that supplies financial information in your Visual Studio .NET application. You know the URL of the WSDL file published by the Web service. What step should you take first? ❍ A. Run the Web Services Description Language Tool. ❍ B. Run the Web Service Discovery Tool. ❍ C. Open the WSDL file in a Web browser. ❍ D. Copy the WSDL file to your client project.
Answer B is correct. The Web Service Discovery Tool will retrieve any available discovery documents for the Web service so you can determine how to call it from your application. Answer A is incorrect because the Web Services Description Language Tool is useful for creating a proxy class, but you won’t need to do that if you’re working within Visual Studio .NET. Answer C is incorrect because there’s no need for you to look at the contents of the file. Answer D is incorrect because the client project does not need a copy of this file.
135 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Basic . . .Web . . Services . . . . .
Question 3 What must you do to make a Web service built with Visual Studio .NET available asynchronously? ❍ A. Use a separate Thread object to handle each Web service request. ❍ B. Just compile the Web service project. ❍ C. Write callback functions in place of the regular Web methods. ❍ D. Use only Sub procedures rather than function procedures as Web methods.
Answer B is correct. You don’t need to do anything special to allow a client to call your Web service asynchronously. The proxy classes built by .NET automatically include proxy code. Answers A, C, and D are incorrect because these changes are unnecessary to meet the requirements of the question.
Question 4 You are invoking a Web service that returns a SqlDataReader object. Your client application is written in Visual Basic .NET, whereas the Web service itself is written in C#. The Web service is outside of your corporate firewall. You receive an “object not found” error when you call the method that returns the SqlDataReader. What could be the problem? ❍ A. The client project and the Web service project must use the same language. ❍ B. Complex objects such as the SqlDataReader cannot cross a firewall. ❍ C. Web services cannot use complex types such as the SqlDataReader. ❍ D. The client project does not contain a reference to the System.Data.SqlClient namespace.
Answer D is correct. For the client project to consume an object, it must include a reference to the library where that object’s type is defined. Answer A is incorrect because Web services allow communication across language and platform barriers. Answer B is incorrect because all Web service objects are converted to SOAP messages, which can cross most firewalls. Answer C is incorrect because a Web service can return objects of any type.
136 Chapter 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 5 You have created a Web service to return inventory information using ASP.NET. One of the methods in your Web service is defined with this code: Public Function Reorder(Quantity As Long) As Boolean ‘ Calculations omitted End Function
Potential consumers of your Web service report that although they can set a reference to the Web service and instantiate the class, the Reorder method is not available. What could be the problem? ❍ A. The class is not marked with the attribute. ❍ B. The Web service is not registered with a UDDI registry. ❍ C. The Reorder method is not marked with the attribute. ❍ D. The Reorder method does not return a String value.
Answer C is correct. A class in a Web service can have many methods, but only those methods marked with the attribute will be available to callers using the class as a Web service. Answer A is incorrect because if the class were not marked with the attribute, callers would be unable to instantiate the class. Answer B is incorrect because UDDI registration is optional. Answer D is incorrect because Web service methods can return any type of data.
Question 6 You have used the Web Services Discovery Tool to retrieve information about a Web service named Financials. Which file will contain the URL for any documentation of the Financials Web service? ❍ A. results.discomap ❍ B. Financials.wsdl ❍ C. disco.exe ❍ D. Financials.disco
Answer D is correct. The disco file contains pointers to any resources made available by the Web service. Answer A is incorrect because the .discomap file is a cross-reference to the other files created by the tool. Answer B is incorrect because the .wsdl file defines the Web service interface but does not document it. Answer C is incorrect because disco.exe is the tool itself.
137 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Basic . . .Web . . Services . . . . .
Question 7 You have created a new Web service that returns information on the historical performance of your company’s stock. What is the easiest way to test the Web service? ❍ A. Write code in a console application to send SOAP requests directly to the server. ❍ B. Run the Web service project and use the test page that it opens in the browser. ❍ C. Cut and paste the code into a Windows application project and then test it in the new project. ❍ D. Have a large number of beta testers use the application and then monitor the server for odd behavior.
Answer B is correct. Running a Web service project in Visual Studio .NET opens a test page that lets you exercise all the public methods it exposes. Answers A and C are incorrect because they require writing custom code to perform the tasks that the test page will do automatically. Answer D is incorrect because a beta test is not normally used to verify the initial application functionality.
Question 8 You have used the Web Services Description Language Tool to create a proxy class for a Web service. When you add the proxy class to your project, you discover that it is coded in the C# language. What must you do to get the proxy class in VB .NET instead of C#? ❍ A. Manually convert the C# code to VB .NET code. ❍ B. Select File, Save As and save the file with the .vb extension. ❍ C. Rerun the tool, specifying the /language:VB option. ❍ D. Rerun the tool, specifying the /namespace:VB option.
Answer C is correct. The /language option lets you specify the coding language for the proxy class created by the tool. Answer A is incorrect because converting the code by hand is unnecessary. Answer B is incorrect because saving a C# file with a .vb extension does not change the language of the file. Answer D is incorrect because specifying the namespace changes object names within the file rather than the language of the file.
138 Chapter 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 9 You are using the Web Services Description Language Tool to create a proxy class for a Web service. The Web service exposes a class named Finances. You already have a Finances class in your application. What should you do to allow both classes to coexist in the same application? ❍ A. Use the /out option of the Web Services Description Language Tool to specify a unique output filename for the new class. ❍ B. Rename the existing class. ❍ C. Use the /namespace option of the Web Services Description Language Tool to specify a unique namespace for the new class. ❍ D. Manually edit the generated proxy class to change the class name it contains.
Answer C is correct. The /namespace option allows you to avoid name collisions with existing code by specifying a unique namespace for the proxy class. Answer A is incorrect because changing the physical filename will not change the logical class name. Answer B is incorrect because naming the existing class will probably break existing code. Answer D is incorrect because manually editing the class is more work than using the switch to create the class correctly in the first place.
139 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Basic . . .Web . . Services . . . . .
Need to Know More? Cerami, Ethan. Web Services Essentials. O’Reilly, 2002. Scribner, Kenn and Mark C. Stiver. Applied Soap: Implementing .NET XML Web Services. Sams, 2001. .NET Framework SDK Documentation: “XML Web Services Created Using ASP.NET and XML Web Service Clients.”
6 Advanced Web Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terms you’ll need to understand: ✓ SOAP request ✓ SOAP response ✓ Serialization ✓ Deserialization ✓ SOAP extension ✓ Asynchronous call ✓ XML wire format
Techniques you’ll need to master: ✓ Creating a SOAP extension ✓ Working with asynchronous Web methods ✓ Controlling the XML wire format for a Web service
142 Chapter 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
To pass the exam, you’ll need to be familiar with three advanced Web service techniques: ➤ SOAP extensions—Enable you to modify the SOAP messages between
the client and server by inserting your own custom code into the message creation process ➤ Asynchronous calls—Enables you to call a Web service without blocking
other code in your client application ➤ Custom wire formatting—Enables you to dictate the formatting of the
SOAP messages used by a Web service (the messages that are sent “over the wire”)
Creating and Using SOAP Extensions To understand how SOAP extensions fit into Web services, it’s helpful to have an understanding of the general Web services architecture. When a Web service client invokes a Web method from a Web service server, the client takes the objects and parameters involved and turns them into an XML message, the SOAP request. This process of converting objects to XML is called serialization. On the server end, the reverse process (called deserialization) is used to turn the XML back into objects. The server then sends back the SOAP response, which goes through a similar process of serialization and deserialization. SOAP extensions allow you to run your own code as part of the serialization or deserialization process. Figure 6.1 shows schematically how SOAP extensions fit into the Web services architecture. In Figure 6.1, the circles show the points at which you can insert a SOAP extension into the Web service architecture. As you can see, SOAP extensions are quite flexible: You can run code in a SOAP extension before or after a serialization or deserialization operation. It’s perfectly possible to have more than one SOAP extension working with a single SOAP message, even at the same point in the processing chain. You’ll see later on that you can configure SOAP extensions with a priority. The SOAP extension with the lowest priority modifies the message first; the SOAP extension with the highest priority modifies the message last.
143 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Advanced . . . . . .Web . . Services . . . . .
Serialize
SOAP Request
Deserialize
Internet or LAN Client
Deserialize
SOAP Response
Serialize
Server
Figure 6.1 Web service communication with SOAP extensions.
Soap extensions can be deployed on the client or on the server, and singly or in pairs. Here are some examples to suggest how particular types of SOAP extensions might fit into the overall Web services picture: ➤ A SOAP extension designed to measure overall server traffic for a Web
service would be deployed only on the server. Clients would never know anything about this SOAP extension. ➤ A SOAP extension designed to translate requests from English measure-
ments to metric measurements, as well as responses from metric measurements to English measurements, could be deployed only on the client. As far as the server knows, it’s still dealing with a client making requests in metric measurements. ➤ A SOAP extension designed to digitally sign messages, as well as to veri-
fy the digital signature on delivery, would need to be deployed on both the client and the server. Each side would sign outgoing messages and verify incoming signatures.
Writing a SOAP Extension Here’s a high-level overview of the tasks that the SOAP extension code must perform: ➤ Derive a new class from the SoapExtension class. ➤ Implement the GetInitializer and Initialize methods to handle startup
chores. ➤ Implement the ChainStream method to intercept the SOAP messages
being serialized and deserialized.
144 Chapter 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ➤ Implement the ProcessMessage method to work with the SOAP mes-
sages. ➤ Derive a new class from the SoapExtensionAttribute class to mark meth-
ods that will use the new extension. The actual code to carry out these tasks is rather complex. Work through the next set of steps to build a Web service that includes a server-side SOAP extension: 1. Create a new Visual Basic ASP.NET Web Service application in the
Visual Studio .NET IDE. Name the new Web service Orders. 2. Right-click the Service1.asmx file in Server Explorer and select
Rename. Change the name of this file to Orders.asmx. 3. Right-click the Orders.asmx file in Server Explorer and select View
Code. Change the name of the class in the class declaration from Service1 to Orders. Change the namespace for the class in the WebService attribute to http://OrderTest.que.com/. 4. Add a new class file to the project. Name the new class Order.vb.
Modify the Order.vb class to contain this code: Public Class Order Private m_OrderID As Integer Private m_Total As Integer Public Sub New() m_Total = 0 End Sub Public Sub New(ByVal OrderID As Integer) m_OrderID = OrderID ‘ Test data ‘ A real implementation would retrieve details ‘ from a database or other store here Dim r As Random = New System.Random() m_Total = r.Next(10, 100) End Sub Public Property OrderID() As Integer Get OrderID = m_OrderID End Get Set(ByVal Value As Integer) m_OrderID = Value End Set End Property Public Property Total() As String Get Total = m_Total End Get Set(ByVal Value As String)
145 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Advanced . . . . . .Web . . Services . . . . . m_Total = Value End Set End Property End Class
5. Add a Web method to the Orders.asmx.vb file to return an Order
object when passed an OrderID from the client: _ Public Function GetOrder(ByVal OrderID As Integer) As Order Dim o As Order = New Order(OrderID) GetOrder = o End Function
6. Add a new class to the project. Name the new class
SoapDisplayExtension.vb. This class will implement a SOAP extension that writes incoming and outgoing messages to a file. 7. Add these directives at the top of the SoapDisplayExtension class: Imports Imports Imports Imports
System.IO System.Text System.Web.Services System.Web.Services.Protocols
8. Add a line of code to make this class a subclass of the SoapExtension
class: Public Class SoapDisplayExtension Inherits SoapExtension
9. Add two variables to the class. These variables will store the original
SOAP message (passed to your SOAP extension as a stream object) and the possibly modified SOAP message from your extension to the next stage of processing: ‘ Variables to hold the original stream ‘ and the stream that we return Private originalStream As Stream Private internalStream As Stream
10. Add code for the GetInitializer and Initialize methods. Although these
methods are not used in this particular example, you still need to implement them because they are marked as MustOverride methods in the base class: ‘ Called the first time the Web service is used ‘ Version called if configured with an attribute Public Overloads Overrides Function GetInitializer( _ ByVal methodInfo As LogicalMethodInfo, _ ByVal attribute As SoapExtensionAttribute) As Object ‘ Not used in this example, but it’s declared ‘ MustOverride in the base class
146 Chapter 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . End Function ‘ Version called if configured with a config file Public Overloads Overrides Function GetInitializer( _ ByVal WebServiceType As Type) As Object ‘ Not used in this example, but it’s declared ‘ MustOverride in the base class End Function ‘ Called each time the Web service is used ‘ And gets passed the data from GetInitializer Public Overrides Sub Initialize( _ ByVal initializer As Object) ‘ Not used in this example, but it’s declared ‘ MustOverride in the base class End Sub
The GetInitializer method is called once when your SOAP extension is first initialized. There are two forms of this method, depending on whether the SOAP extension was configured with an attribute or with a configuration file. You can pass any object you like as the return value from the GetInitializer method. The Initialize method is called once for every SOAP message serialized or deserialized by the Web service. The object passed to the Initialize method is the same object you return from the GetInitializer method. So, for example, you might open a file in the GetInitializer method and pass a FileStream object as the return value from that method to become the input parameter to the Initializer method.
11. Add code to implement the ChainStream method. This method allows
you to intercept the stream that the Web service is working with and to substitute your own stream in its place: ‘ The Chainstream method gives us a chance ‘ to grab the SOAP messages as they go by Public Overrides Function ChainStream( _ ByVal stream As Stream) As Stream ‘ Save the original stream originalStream = stream ‘ Create and return our own in its place internalStream = New MemoryStream() ChainStream = internalStream End Function
If your SOAP extension is called during serialization, the internal variable you returned will contain the SOAP message, and you should copy it to the original variable before you finish processing. If your SOAP extension is called during deserialization, the original variable will contain the SOAP message, and you should copy it to the internal variable before you finish processing. And remember, the client serializes requests and deserializes responses, whereas the server deserializes requests and serializes responses.
12. Add code to handle SOAP messages in the ProcessMessage method.
Note that this method is called in four different situations (before and after serialization and deserialization) and that you can use the passed parameter to determine which stage you’re in:
147 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Advanced . . . . . .Web . . Services . . . . . ‘ The ProcessMessage method is where we do our work Public Overrides Sub ProcessMessage( _ ByVal message As SoapMessage) ‘ Determine the stage and take appropriate action Select Case message.Stage Case SoapMessageStage.BeforeSerialize ‘ About to prepare a SOAP Response Case SoapMessageStage.AfterSerialize ‘ SOAP response is all prepared ‘ Open a log file and write a status line Dim fs As FileStream = _ New FileStream(“c:\temp\Orders.log”, _ FileMode.Append, FileAccess.Write) Dim sw As New StreamWriter(fs) sw.WriteLine(“AfterSerialize”) sw.Flush() ‘ Copy the passed message to the file internalStream.Position = 0 CopyStream(internalStream, fs) fs.Close() ‘ Copy the passed message ‘ to the other stream internalStream.Position = 0 CopyStream(internalStream, originalStream) internalStream.Position = 0 Case SoapMessageStage.BeforeDeserialize ‘ About to handle a SOAP request ‘ Copy the passed message ‘ to the other stream CopyStream(originalStream, internalStream) internalStream.Position = 0 ‘ Open a log file and write a status line Dim fs As FileStream = _ New FileStream(“c:\temp\Orders.log”, _ FileMode.Append, FileAccess.Write) Dim sw As New StreamWriter(fs) sw.WriteLine(“BeforeDeserialize”) sw.Flush() ‘ Copy the passed message to the file CopyStream(internalStream, fs) fs.Close() internalStream.Position = 0 Case SoapMessageStage.AfterDeserialize ‘ SOAP request has been deserialized End Select End Sub ‘ Helper function to copy one stream to another Private Sub CopyStream(ByVal fromStream As Stream, _ ByVal toStream As Stream) Try Dim sr As New StreamReader(fromStream) Dim sw As New StreamWriter(toStream) sw.WriteLine(sr.ReadToEnd()) sw.Flush() Catch ex As Exception End Try End Sub
148 Chapter 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13. Add a new class file to the project. Name the new class
SoapDisplayExtensionAttribute.vb. Modify the SoapDisplayExtensionAttribute.vb class to contain this code: Imports System.Web.Services Imports System.Web.Services.Protocols _ Public Class SoapDisplayExtensionAttribute Inherits SoapExtensionAttribute Private m_Priority As Integer = 1 ‘ Specifies the class of the SOAP ‘ Extension to use with this method Public Overrides ReadOnly Property _ ExtensionType() _ As Type Get ExtensionType = _ GetType(SoapDisplayExtension) End Get End Property ‘ Member to store the extension’s priority Public Overrides Property Priority() As Integer Get Priority = m_Priority End Get Set(ByVal Value As Integer) m_Priority = Value End Set End Property End Class
14. Modify the declaration of the Web method in the Orders.asmx.vb class
to include the SoapDisplayExtensionAttribute. This is what tells the CLR that it should hook your SOAP extension in to this Web method: _ Public Function GetOrder(ByVal OrderID As Integer) As Order Dim o As Order = New Order(OrderID) GetOrder = o End Function
15. Build the project to create the Web service.
Testing the SOAP Extension When a request comes in for the GetOrder method, the Web service sees the SoapDisplayExtension attribute and routes the request and response through the SoapDisplayExtension class. Within that class, the SOAP messages are
149 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Advanced . . . . . .Web . . Services . . . . .
logged to a disk file and then passed on. To test this, you’ll need to build a client project: 1. Create a new Visual Basic .NET Windows Application in the Visual
Studio .NET IDE. 2. Right-click the References folder in Solution Explorer and select Add
Web Reference. This will open the Add Web reference dialog box. Add a Web Reference to http://YourServerName/Orders/Orders.asmx. 3. Place a Button control named
btnGetOrder
on the default form in the
project. 4. Double-click the Button control to open the form’s module. Add this
code to handle the Button’s Click event: Private Sub btnGetOrder_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnGetOrder.Click Dim os As localhost.Orders = New localhost.Orders() Dim o As localhost.Order = os.GetOrder(12) End Sub
5. Run the project and click the button on the form. 6. On the Web server where the Web service is located, open the file
c:\Temp\Orders.log. This file will contain both the incoming SOAP request and the outgoing SOAP response, as saved by the SOAP extension.
Creating Asynchronous Web Methods If you simply call a Web service method from a client program (via a Web service proxy), the call is synchronous. That is, your client application will not process any other commands until the SOAP response comes back from the server. The proxy classes generated by Visual Studio .NET (or by wsdl.exe) also allow you to make asynchronous calls to a Web service. When you make an asynchronous call, the client sends the SOAP request, but it is not blocked waiting for the SOAP response. The Web service server does not require any special configuration to support asynchronous calls. In fact, as far as the server knows, the call is synchronous. All the additional processing is done at the client. The CLR sends the SOAP request and then monitors a system I/O completion port to wait for the SOAP response.
150 Chapter 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
There are two main ways to handle asynchronous calls: via a callback delegate and via a WaitHandle object.
Using a Callback Delegate The first way to handle an asynchronous Web method call is to provide a delegate that the runtime can invoke when the results are returned. In the case of the GetOrder method, the code might look like this: Private Sub Button1_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click ‘ Connect to the Web service Dim os As localhost.Orders = New localhost.Orders() ‘ Create a delegate to handle the callback Dim cb As AsyncCallback = _ New AsyncCallback(AddressOf WebServiceCallback) ‘ Launch the asynchronous call os.BeginGetOrder(12, cb, os) End Sub ‘ Callback to handle the asynchronous return Private Sub WebServiceCallback( _ ByVal ar As IAsyncResult) ‘ Get the returned Web service instance Dim os As localhost.Orders os = ar.AsyncState ‘ Finish the work Dim o As localhost.Order = os.EndGetOrder(ar) End Sub
The callback function for an asynchronous Web method call must have the signature shown in the previous code, taking a single argument of type IAsyncResult. For each Web method, the proxy class will automatically generate corresponding Begin and End methods. The Begin method takes all the arguments of the original method, plus a reference to the Web service object itself (this is necessary because you can have multiple asynchronous calls outstanding at any given time) and the address of the callback method (contained in an AsyncCallback object). When the results of the call are available, the callback method will be invoked. Within the callback method, you can retrieve the original Web service object and then call its End method to get the result of the method call.
Using the WaitHandle Object You can also use a WaitHandle object to manage asynchronous Web method calls. WaitHandle essentially lets you turn the asynchronous process back into a synchronous process, as shown here:
151 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Advanced . . . . . .Web . . Services . . . . . Private Sub Button1_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click ‘ Connect to the Web service Dim os As localhost.Orders = New localhost.Orders() ‘ Create a result object to handle the callback Dim ar As IAsyncResult ‘ Launch the asynchronous call ar = os.BeginGetOrder(1, Nothing, Nothing) ‘ Do some work while waiting for it to return ‘ In this case, just a loop Dim intI As Integer For intI = 1 To 90 Next ‘ Now wait for the method to come back Dim wh As WaitHandle = ar.AsyncWaitHandle wh.WaitOne() Dim o As localhost.Order = os.EndGetOrder(ar) ‘ At this point the method will have completed End Sub
This example doesn’t use a callback function at all. Rather, it uses the BeginGetOrder method to start the asynchronous method call and saves the result from this call as an IAsyncResult object. When I was ready to wait for the results of the call, I retrieved a WaitHandle object from this object’s AsyncWaitHandle property. The WaitOne method of this object causes the thread to pause until the results are ready. If you have multiple outstanding asynchronous Web method calls, you can wait for them all to come back by using the static WaitHandle.WaitAll method or wait for the first one to return by using the static WaitHandle.WaitAny method.
There are two other ways in which you can manage asynchronous Web method calls if you like: ➤ You can use a loop to poll the value of the IAsyncResult.IsCompleted
property. This property will return False while the method is still doing work, and it will return True when the End method is ready to call. ➤ You can simply call the End method in your code when you’re ready to
wait synchronously for the result. This is equivalent to using the WaitHandle.WaitOne method you saw earlier.
152 Chapter 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Controlling XML Wire Format So far in this book, I’ve been treating the SOAP format as if it is completely specified by the SOAP standard. But, in fact, the standard allows a good deal of flexibility in converting objects to XML messages. There are variations in formatting both for the parameters within the body of a SOAP message and for the format of the body itself: ➤ Literal parameter formatting—Formats parameters according to an XSD
schema. This is the default parameter formatting for .NET Web services. ➤ Encoded parameter formatting—Formats parameters according to what are
called the SOAP Section 5 encoding rules. These rules encode data type information directly into the SOAP message. ➤ Document-based body formatting—This is the default .NET body format-
ting. In this method of body formatting, parameters may be broken up into multiple elements inside the message body. Elements may be wrapped within an overall element or placed in the body as bare elements. ➤ RPC-based body formatting—This is sometimes known as SOAP Section 7
formatting. In this style of body formatting, all parameters are contained within a single element in the body of the SOAP message. This format is based on the Remote Procedure Call (RPC) standard. Given these choices, you have three different legal combinations: ➤ Document-based body formatting with literal parameter formatting (the
.NET default) ➤ Document-based body formatting with encoded parameter formatting ➤ RPC-based body formatting with encoded parameter formatting
These formatting choices control the XML wire format of the messages—so called because the resulting messages travel “over the wire” between client and server. You can apply attributes indicating these choices to both Web methods and to the proxy classes that call those methods. It should be obvious that you must match such choices: If the Web method is using encoded parameter formatting, any proxy class calling that method must also use encoded parameter formatting.
153 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Advanced . . . . . .Web . . Services . . . . .
Finally, you can also use attributes to change details about the SOAP message, such as the names used for XML elements representing parameters. Why would you make these changes? If you’re working in a purely .NET world, you probably wouldn’t. But there might come a time when you need to write code that interoperates with Web services developed under other environments or with clients that can’t use the .NET defaults. In those cases, it’s helpful to be able to fine-tune the XML that your code can accept to match the XML sent and received by less-flexible components. To demonstrate the effect of various attributes, I’ll use a simple Web service class with a supporting class: < WebService(Namespace:=”http://weather.que.com/”)> _ Public Class Weather Public Function Store( _ ByVal Station As String, _ ByVal Wind As WindObservation) As Boolean ‘ Here a full implementation would store ‘ the data in the database ‘ Return True to indicate success Store = True End Function Public Function GetLatest( _ ByVal Station As String) As WindObservation ‘ Simulate retrieving the most ‘ recent observation from the database Dim w As WindObservation = New WindObservation() w.Direction = “NNW” w.Speed = 14 GetLatest = w End Function End Class Public Class WindObservation Public Direction As String Public Speed As Integer End Class
Using Literal Parameter Formatting Literal parameter formatting is the default for Web services created with Visual Studio .NET. But if you like, you can use attributes to specify this default explicitly. Such a Web service could be declared this way: _ Public Class Weather
154 Chapter 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
With literal parameter formatting, a SOAP request looks like this: AAA N 5
And here’s the corresponding SOAP response: true
As you can see, literal parameter formatting keeps things very simple. Starting from the outside in, here’s what you’ll find in these messages: 1. The
soap:Envelope element, which includes the namespace declarations that identify this as a SOAP message.
2. The
soap:Body element, which identifies the application-specific body of the SOAP message.
3. The top-level application-specific element (Store or
StoreResponse). These elements specify the namespace of the Web service itself (http://weather.que.com), indicating that all the contained elements will be from this namespace.
4. Elements representing the actual parameters of the messages. Note
that the complex parameter Wind is handled by creating nested XML elements for each of its properties.
155 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Advanced . . . . . .Web . . Services . . . . .
Literal parameter formatting does not insert any information about data types into the SOAP messages. It assumes that your code will know how to handle the data that it sends and receives.
Using Encoded Parameter Formatting Encoded parameter formatting inserts additional information into the SOAP messages to conform with Section 5 of the SOAP specification. To specify this formatting, you’d modify the Web service declaration this way: _ Public Class Weather
A SOAP request for this style looks like this: AAA N 5
And here’s the corresponding SOAP response:
156 Chapter 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . true
Note that encoded parameter formatting is somewhat more complex than literal parameter formatting. The soap:Envelope element includes additional namespaces to allow each parameter to be explicitly marked with its data type. Elements specific to this Web service (such as the method name or the parameter names) are each explicitly marked with the tns namespace indicator. The complex data element Wind is handled by a reference to a separate XML element outside of the tns:Store element. Encoded parameter formatting conforms more closely to the SOAP standard than literal parameter formatting and therefore might be helpful when interoperability with Web service components defined outside of the .NET Framework is a consideration. However, this standards compliance comes at the cost of additional message size. Table 6.1 shows how the request and response sizes compare between literal and encoded parameter formatting in this simple example. Table 6.1 Comparison of Literal and Encoded Parameter Formatting SOAP Message
Literal Size
Encoded Size
Increase
Request
368 bytes
705 bytes
92%
Response
341 bytes
538 bytes
58%
Using RPC-Style Body Formatting Another major decision to make about SOAP message formatting is whether to use document-style or RPC-style (SOAP Section 7) body formatting. So far, all the SOAP messages you’ve seen have used document-style body formatting. For RPC-style formatting, the declaration changes to this: _ Public Class Weather
Here’s the SOAP request to this class: AAA N 5
And here’s the corresponding SOAP response: true
If you compare these messages to the ones from the encoded parameter formatting example, you’ll discover that they’re identical! What’s going on here? The answer is that the document style of body formatting is more flexible than the RPC style. When you use RPC style, you can’t make any further choices about how to encode the parameters within the body. With document style, though, you can supply additional options to the SoapDocumentService attribute. I’ll cover those in the next section. If you select an RPC-style message body, the parameters within that body will automatically be encoded according to the SOAP Section 5 rules.
158 Chapter 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Wrapped and Bare Parameters In both RPC-style body formatting and the default document body formatting, all the parameters within the SOAP message are contained within a single XML element identified with the name of the Web method. This is referred to as the wrapped parameter style. If you’re using document body formatting, you can specify the bare parameter style as an alternative: _ Public Class Weather
Now the SOAP request changes as follows: AAA N 5
And the corresponding SOAP response becomes this: true
Compared to the default wrapped formatting, you’ll see that the bare parameter formatting makes the parameter elements direct children of the soap:Body element, rather than wrapping them in a single element that represents the entire Web method. You can also apply bare parameter formatting to encoded parameters with similar results.
159 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Advanced . . . . . .Web . . Services . . . . .
Using the XmlElement Attribute The last level of customization of which you should be aware involves the XmlElement attribute. This attribute allows you to specify the low-level XML formatting details for individual messages and parameters. For example, you might modify a WebMethod declaration this way: Public Function Store( _ _ ByVal Station As String, _ _ ByVal Wind As WindObservation) As Boolean
Ordinarily, the parameter names within a SOAP message exactly match the parameter names in the VB .NET code for the corresponding Web method. This example uses the XmlElement attribute to override the default naming in several cases. In addition to the element names, you can control other aspects of the generated XML with properties of the XmlElement attribute. For example, you can force the element to include a namespace qualifier with the Form property:
Table 6.2 shows the properties of the XmlElement attribute that you can set. Table 6.2 Properties of the XmlElement Attribute Property
Description
DataType
XSD data type to use for the element.
ElementName
Name of the element. This is the default property.
Form
Indicates whether to use a namespace qualifier with the element name.
IsNullable
Indicates whether to include an element in the XML for null values.
Namespace
Namespace of the element.
Type
Native data type of the element.
160 Chapter 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exam Prep Questions Question 1 Your code is making asynchronous calls to two different Web methods. You then execute other code until you arrive at a point where you require results from one or the other of the asynchronous calls. You can proceed with further processing as soon as either result is available. How should your code wait for the results of the asynchronous calls? ❍ A. Use a separate WaitHandle.WaitOne call for each method. ❍ B. Use a separate callback delegate function for each method. ❍ C. Use a WaitHandle.WaitAny call, specifying both methods. ❍ D. Use a WaitHandle.WaitAll call, specifying both methods.
Answer C is correct. The WaitHandle.WaitAny call will suspend processing until one or the other method returns a result, which is what is required in this case. Answers A and D are incorrect because either of those alternatives will suspend processing until both methods have returned results. Answer B is incorrect because using callback delegate functions will not suspend processing at all.
Question 2 You have created a Web method named GetOrders with the following declaration: Public Function GetOrders ( _ strCompanyName As String) As Integer
Your corporate standards call for using Hungarian naming (with the str prefix) for variables. However, the developer of the client application that will call this Web method insists on using the name CompanyName (without a prefix) for the parameter. How should you fix this problem? ❍ A. Rewrite your code to use CompanyName as the parameter name. ❍ B. Use the SoapDocumentMethod attribute to specify the bare parameter style for this method. ❍ C. Use the XmlElement attribute to rename the parameter in the SOAP messages. ❍ D. Use the SoapDocumentMethod attribute with Use:=Literal to specify literal encoding for this method.
161 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Advanced . . . . . .Web . . Services . . . . .
Answer C is correct. To rename a parameter in a Web method call, you can use the XmlElement attribute. Answer A is incorrect because you shouldn’t violate your company standards if you don’t have to. Answers B and D are incorrect because the parameter style and encoding will not change the name of a parameter.
Question 3 You have developed a SOAP extension that will encrypt messages on the server and then decrypt them on the client, and vice versa. You plan to use this extension for both requests and responses. Which of these processing stages would be an appropriate place to call this extension? [Select two.] ❑ A. BeforeSerialize on the server ❑ B. AfterSerialize on the client ❑ C. BeforeDeserialize on the server ❑ D. AfterDeserialize on the client
Answers B and C are correct. This SOAP extension must be called after an object has been converted to XML (AfterSerialize) and before the encrypted XML can be converted to an object (BeforeDeserialize). Answer A is incorrect because if you encrypt the object before serialization, it won’t be possible to deserialize it. Answer D is incorrect because the message will need to be decrypted before it can be deserialized.
Question 4 You are developing a SOAP extension that will track the IP address of incoming requests to a server. These results will be written to a file for later analysis. The filename should be specified in a configuration file, and it will not change while the Web service is running. In which method should you read the name of the file where the results will be stored? ❍ A. GetInitializer ❍ B. Initialize ❍ C. ChainStream ❍ D. ProcessMessage
Answer A is correct. The GetInitializer method is called once when the SOAP extension is loaded, and it’s the appropriate place to perform one-time initialization tasks. Answer B is incorrect because the Initialize method is called for each SOAP message. Answer C is incorrect because the
162 Chapter 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ChainStream method is used to intercept the message stream, and answer D is incorrect because the ProcessMessage method is used to perform the actual work of the SOAP extension.
Question 5 Your code is making asynchronous calls to two different Web methods. You want other processing in your code to continue while these methods execute. When either asynchronous call is finished, you want to process its results and then continue with other code while waiting for the second method to return. How should your code wait for the results of the asynchronous calls? ❍ A. Use a separate WaitHandle.WaitOne call for each method. ❍ B. Use a separate callback delegate function for each method. ❍ C. Use a WaitHandle.WaitAny call, specifying both methods. ❍ D. Use a WaitHandle.WaitAll call, specifying both methods.
Answer B is correct. To continue processing other code while waiting for the results of an asynchronous Web method call, you must use callback delegate functions. Answers A, C, and D are incorrect because calling any of the WaitHandle methods will suspend processing of other calls while the Web methods complete.
Question 6 Your code has made an asynchronous call to a Web method and is now continuing with processing. You’ve reached a point where you could handle the return value from the asynchronous call, if it’s available, or continue with other processing. How can you check to see whether the asynchronous call is finished without blocking? ❍ A. Call the End method for the asynchronous Web method. ❍ B. Call the WaitHandle.WaitOne method. ❍ C. Call the WaitHandle.WaitAny method. ❍ D. Test the value of the IAsyncResult.IsCompleted property.
Answer D is correct. The IsCompleted property will tell you whether there are results ready to retrieve from the Web method. Answers A, B, and C are incorrect because these alternatives will block further code until the results are ready.
163 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Advanced . . . . . .Web . . Services . . . . .
Question 7 You are designing a SOAP extension that will modify incoming Web method calls. Due to changes on the server, you need to change the value of a parameter that’s being passed to the Web method. In which message stage should you invoke this SOAP extension? ❍ A. BeforeSerialize ❍ B. AfterSerialize ❍ C. BeforeDeserialize ❍ D. AfterDeserialize
Answer C is correct. For this SOAP extension, you need to modify the incoming XML before it has been converted to an object. That point is the BeforeDeserialize message stage. Answers A and B are incorrect because the BeforeSerialize and AfterSerialize stages apply to outgoing messages, not incoming ones. Answer D is incorrect because in the AfterDeserialize stage the message has already been converted to an object.
Question 8 You are designing a SOAP extension to modify outgoing Web method calls from the client to the server. The extension will run on the client, and when it discovers an obsolete parameter name in the SOAP request, it will replace this with the new parameter name. In which message stage should you invoke this SOAP extension? ❍ A. BeforeSerialize ❍ B. AfterSerialize ❍ C. BeforeDeserialize ❍ D. AfterDeserialize
Answer B is correct. To alter the XML of an outgoing SOAP request, you need to work with the message in the AfterSerialize stage of message processing. Answer A is incorrect because in the BeforeSerialize stage the message does not yet exist. Answers C and D are incorrect because the Deserialize stages occur for incoming messages, not outgoing messages.
164 Chapter 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 9 You are developing a client-side SOAP extension named TraceExt. Your project includes the StatsExt class and an attribute class named StatsExtAttribute. It also includes a form with a button that invokes a Web method using the following code: Private Sub btnRunMethod_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnRunMethod.Click ‘ Call a Web method on the Sales object Dim S As SalesWebService.Sales = _ New SalesWebService.Sales() txtSales.Text = S.GetSales() End Sub
Where should you apply the StatsExtAttribute attribute in order to activate the SOAP extension for this Web method? ❍ A. To the GetInitializer method in the TraceExt class ❍ B. To the Initialize method in the TraceExt class ❍ C. To the btnRunMethod_Click method in the form’s module ❍ D. To the GetSales method in the Web service proxy class
Answer D is correct. To activate a SOAP extension, you must apply its attribute to the Web method you wish to monitor in the proxy class. Answers A and B are incorrect because the TraceExt class does not require any attributes to do its work. Answer C is incorrect because adding the attribute to the Click method will not tell the proxy class to pass requests to the SOAP extension.
165 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Advanced . . . . . .Web . . Services . . . . .
Need to Know More? Jennings, Roger. Visual Basic .NET XML Web Services Developer’s Guide. McGraw-Hill/Osborne, 2002. Oellermann, William. Architecting Web Services. Apress, 2002. Scribner, Kenn and Mark C. Stiver. Applied SOAP: Implementing .NET XML Web Services. Sams, 2001. .NET Framework SDK documentation: “Altering the SOAP Message Using SOAP Extensions” and “Customizing SOAP Messages.”
7 Windows Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terms you’ll need to understand: ✓ Service Control Manager ✓ Windows service ✓ The ServiceBase class ✓ The ServiceProcessInstaller class ✓ The ServiceInstaller class ✓ The ServiceController class
Techniques you’ll need to master: ✓ Creating a Windows service using Visual Basic .NET ✓ Writing code to tie into service events ✓ Installing a Windows service
168 Chapter 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Windows services are ideal for applications that must run continuously in the background. The Windows operating system itself runs a variety of applications as services, from its FTP server to the computer browser to Internet Connection Sharing. These applications are managed by a part of the operating system called the Service Control Manager (SCM) and must conform to the protocols and interfaces defined by the SCM. Visual Basic .NET offers full support for creating and installing Windows services.
Understanding Windows Services A Windows service is a process that conforms to the interface rules of the SCM. The SCM is a part of the Windows operating system that provides a unified way to control, configure, and access Windows services. Windows services are available on Windows NT (where they are known as NT services), Windows 2000, Windows XP, and Windows .NET Server. There is no support of Windows services on the Windows 95, Windows 98, and Windows Me operating systems.
Each Windows service must implement a set of well-known methods, which enable the service to communicate with the SCM. These well-known methods define how a Windows service should handle the SCM messages. Some common messages sent by the SCM to a service are Start, Pause, Continue, and Stop. Although Windows services can interact with the desktop and provide a user interface, most services don’t.
Architecture of Windows Services There are five main components in the Windows services architecture: ➤ Windows Services Database—This database is a part of the Windows
Registry and stores information about all installed services, including the path to the executable file for the service as well as security and startup settings. ➤ Service Control Manager (SCM)—A Windows component that maintains
the Windows services databases and controls as well as configures and maintains installed services. The SCM is responsible for tasks such as sending Start and Stop messages to individual services.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Windows . . . . . Services . . . . . ➤ Windows Service Installer—Each service has its own installer that uses the
SCM to install, uninstall, and repair the service. ➤ Windows Services in Execution—Services can be started automatically
when Windows starts, or they can be started manually. Once a Windows service is started, it continues to run until it receives a Pause message or a Stop message. When a Windows service is paused, the process for the Windows service continues to exist, but the service does not respond to client programs. On the other hand, when a Windows service is stopped, its process is terminated and the memory is reclaimed. ➤ Windows Service Controller—The part of Windows that uses the SCM to
perform tasks such as stopping, starting, and pausing services, retrieving the status of services, and modifying configuration information. The Services applet in Control Panel uses the WSC to do its work.
.NET Framework Support for Windows Services The main .NET Framework classes involved in working with Windows service applications are as follows: ➤ The ServiceBase Class—A class that provides the base-level functionality
for a Windows service application. ➤ The ServiceProcessInstaller and ServiceInstaller Classes—Classes that enable
a Windows service application to be installed using the installation utility installutil.exe. ➤ The ServiceController Class—A class that enables a program to connect to
a Windows service and perform various operations, such as starting, stopping, querying, and so on.
Creating a Windows Service Application To create a Windows service, you derive a custom class from the ServiceBase class of the System.ServiceProcess namespace. Table 7.1 lists the important members of the ServiceBase class.
169
170 Chapter 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Table 7.1 Important Members of the ServiceBase Class Member Name
Type
Description
AutoLog
Property
When set to True, this property automatically logs the call to the OnStart, OnStop, OnPause, and OnContinue methods in the Application event log.
CanPauseAndContinue
Property
When set to true, this property indicates that the service can be paused and resumed.
CanShutdown
Property
When set to true, this property indicates that the service should be notified when the system is shutting down.
CanStop
Property
When set to true, this property indicates that the service can be stopped once it has started.
EventLog
Property
Specifies an event log that can be used to write customized messages to the Application event log on method calls such as OnStart and OnStop.
OnContinue
Method
Specifies the actions to take when a service resumes normal functioning after being paused. This method is executed when the SCM sends a Continue command to the Windows service.
OnPause
Method
Specifies the actions to take when a service pauses. This method is executed when the SCM sends a Pause command to the Windows service.
OnStart
Method
Specifies the actions to take when a service starts running. This method is executed when the SCM sends a Start command to the Windows service.
OnStop
Method
Specifies the actions to take when a service stops running. This method is executed when the SCM sends a Stop command to the Windows service.
Run
Method
Provides the main entry point for a service executable.
ServiceName
Property
Specifies a name that identifies the service.
Understanding How the SCM Interacts with a Windows Service As I mentioned earlier, the SCM handles the tasks involved in controlling a Windows service. When the SCM sends a Start message to the Windows service, the following things happen:
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Windows . . . . . Services . . . . . 1. The SCM finds the path of the Windows service application’s exe-
cutable file from the Windows service database. 2. SCM creates a Windows service process by executing the Main method
defined in the Windows service executable. 3. The Main method of the Windows service executable creates one or
more instances of the Windows service class and passes their references to the SCM through the static Run method of the ServiceBase class. The SCM uses these references to send messages to the Windows service. 4. The handler associated with the Start message—the OnStart method—
is executed. The OnStart method executes the code required for a Windows service to carry out its tasks, such as listening to a port for incoming requests, logging events to the event log, spooling print jobs, and so on. After the Windows service is started, SCM can use its reference to send various messages—such as Pause, Continue, and Stop—to the Windows service. These messages invoke the OnPause, OnContinue, and OnStop methods of the Windows service, respectively. Not all services implement the OnPause, OnContinue, and OnStop methods. Whether a service needs to implement these methods depends on the CanPauseAndContinue and CanStop properties of a Windows service. If these properties are True, the SCM can invoke the OnPause, OnContinue, and OnStop methods. But if your service can’t be paused, for example, set the CanPauseAndContinue property to False and the SCM will never call OnPause or OnContinue. If you set any of the CanStop, CanShutdown, and CanPauseAndContinue properties for a Windows service to True, you also must implement the corresponding handler methods (OnStop for CanStop, OnShutdown for CanShutdown, or OnPause and OnContinue for CanPauseAndContinue).
There is no CanStart property in the ServiceBase class. This means that not starting is not an option for a Windows service.
Creating a Windows Service Application To create a Windows service, follow these general steps:
171
172 Chapter 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1. Create a new solution in Visual Studio .NET. In the New Project dia-
log box, select Visual Basic Projects as the project type and Windows Service as the template. Name the project and click OK. 2. The Windows service project contains a file named Service1.vb. You’ll
probably want to rename this file to something more descriptive of your service. Click the designer surface and then use the Properties windows to set the properties for the service, as shown in Figure 7.1 (which shows a service named OrderService).
Figure 7.1 You can set various properties of a Windows service through the Properties window.
3. Switch to code view and you’ll find skeletons for the OnStart and
OnStop methods. You can add your own code to these methods, and you can use the method name drop-down list at the top of the code editor to create additional event procedures, as needed. 4. Set the startup object for the project to your service class. 5. Build the project. This step creates the Windows service application.
Compiling a Windows service project creates an executable file just like other Windows applications. However, you cannot directly run this executable. If you try doing so, you’ll get a Windows service start failure error with the following message: Cannot start service from the command line or ➥a debugger. A Windows Service must first be installed ➥(using installutil.exe) and then started with the Server Explorer, ➥Windows Services Administrative tool or the NET START command
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Windows . . . . . Services . . . . .
You need to install the Windows service application before you can start it.
Installing a Windows Service The .NET Framework allows you to create custom installer components. Custom installer components are the classes that can be used by an installation tool such as installutil.exe (shipped with .NET) to properly install an application. The following three installation components are used to create an installer for Windows service applications: ➤ The System.ServiceProcess.ServiceProcessInstaller Class—This class creates
the records for all the Windows services contained with the application in the Windows service database. You need to have just one instance of the ServiceProcessInstaller class in a Windows service application, regardless of how many services the application contains. ➤ The System.ServiceProcess.ServiceInstaller Class—This class writes specific
information about a Windows service in the Windows service database. You’ll have as many instances of the ServiceInstaller class as the number of services in the Windows service application. ➤ The System.Configuration.Install.Installer Class—This class works as the
entry point for the installation process. The Installer class maintains a collection of custom installer objects, which can be accessed through the Installers property. You’ll add the instance of the ServiceProcessInstaller class and instances of the ServiceInstaller class corresponding to your Windows service application to this collection. You’ll also apply the RunInstallerAttribute attribute to this class and set its value to True. The installutil.exe tool treats an installation as a single transaction. If you have multiple services in a single application, and any one of them fails to install properly, the entire installation will be rolled back.
The ServiceProcessInstaller and ServiceInstaller Classes Table 7.2 lists some important properties of the ServiceProcessInstaller class.
173
174 Chapter 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Table 7.2 Important Properties of the ServiceProcessInstaller Class Property
Description
Account
Specifies the type of account under which the services run. This property takes one of the values from the ServiceAccount enumeration. These values are LocalService, LocalSystem, NetworkService, and User. If you set the Account property to User and do not specify a value for either the Username or Password property, you are prompted to enter both a username and password at the time of installation.
Password
This property is only useful when the Account property is set to User. In that case, this property specifies the password of the account under which the service application runs.
Username
This property is only useful when the Account property is set to User. In that case, this property specifies the username of the account under which the service application runs.
Table 7.3 lists some important properties of the ServiceInstaller class. Table 7.3 Important Properties of the ServiceInstaller Class Property
Description
DisplayName
Specifies a descriptive friendly name that identifies the service to the user. This name is often used by interactive tools to display the service to the user.
ServiceName
Specifies a unique name by which the system identifies this service.
ServicesDependedOn
Specifies an array of strings representing the services that must be running for this service to run. If any service in the array is not running, the SCM tries to start that service before starting this service.
StartType
Indicates how and when this service is started. The value of this property is one of the ServiceStartMode enumeration values—Automatic, Disabled, or Manual. The value Automatic specifies that the service is started automatically when Windows starts. The default value of this property is Manual, which means that the service will not start automatically with Windows.
The ServiceName property of a ServiceInstaller object must exactly match the ServiceName property of the corresponding Windows service class.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Windows . . . . . Services . . . . . Unfortunately, the Installer class does not have a property to set the description for a Windows Service. If you need to set a description for a service, you have two choices—either use the Service Control utility (sc.exe) or modify the Registry key corresponding to the Windows service, add a string value named Description, and then set the data for this value with the description text.
Adding Installer Classes to a Windows Service Project When you use Visual Studio .NET to create a Windows service application, it is easy to create the required installer classes. The Properties window of the Windows service, which you saw in Figure 7.1, displays a link with the caption Add Installer. When you click that link, Visual Studio .NET automatically adds a class named ProjectInstaller in your project. This class derives from the Installer class and contains an instance of the ServiceProcessInstaller class as well as one or more instances of the ProcessInstaller class (depending on the number of Windows services you have in the application). After adding these classes, you can customize the installation by changing some of their properties directly in the Properties window: ➤ The Account property of the ServiceProcessInstaller class controls the
security account under which the service will run. ➤ The DisplayName property of the ServiceInstaller class controls the
name of the service in the Services administrative tool. ➤ The StartType property of the ServiceInstaller class controls whether
the service will be automatically started when Windows starts. After adding the Installer classes, you’ll need to rebuild the project. At this point, the service is ready to install.
Using installutil.exe to Install a Windows Service Application An executable file that contains the code for the Installer class can be easily installed using the command-line installutil.exe tool that comes as a part of the .NET Framework SDK. For example, you could install a service named OrderService.exe from a Visual Studio .NET command prompt by issuing this command: installutil OrderService.exe
175
176 Chapter 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Using Tools to Monitor and Control a Windows Service Windows, the .NET Framework SDK, and Visual Studio .NET provide various tools that help you to monitor and control a Windows service application.
Using the Services MMC Snap-In One of the easiest ways of manipulating a Windows service is through the Services MMC Snap-in. You can access this snap-in through the Administrative Tools section of the Windows Control Panel or from the Services and Applications section of the Computer Management Control Panel, depending on your operating system. The Services snap-in lists all the Windows services installed on the computer, along with their name, description, status, startup type, and logon account, as shown in Figure 7.2.
Figure 7.2 The Services snap-in enumerates the installed Windows services on a computer.
You can select a service in this list and use the Action menu or the toolbar buttons to start, pause, continue, restart, or stop a Windows service.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Windows . . . . . Services . . . . .
For more control options, you can display the Properties window for a service by double-clicking the service record in the Services snap-in. From the service’s Properties window, you can start, pause, continue, and stop the service. You can also change the startup type, start parameters, and service login account. The Recovery tab allows you to specify actions that need to be taken if the service fails to start.
Using Visual Studio .NET Server Explorer When using Visual Studio .NET, you need not leave the development environment to manipulate the Windows services. Visual Studio .NET allows you to manipulate services on both local and remote computers through the Server Explorer Window. To access the services, open the Server Explorer window and in the Servers node select the computer where you want to access the service. Inside the selected computer, you will find a node containing all the services on that computer. You can right-click a service and select options to start, pause, continue, and stop the Windows service from the shortcut menu. You can also open a more detailed Properties window that shows you the service name, dependencies, logon account, and other information.
Using the NET Utility (net.exe) The NET command-line utility comes installed with Windows. This utility allows you to perform various networking commands, including control of Windows services. Typical usage of net.exe with Windows services is as follows: ➤ To enumerate a list of installed services: NET START
➤ To start a Windows service: NET START WindowsServiceName
➤ To pause a Windows service: NET PAUSE WindowsServiceName
➤ To resume a paused Windows service: NET CONTINUE WindowsServiceName
177
178 Chapter 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ➤ To stop a Windows service: NET STOP WindowsServiceName
➤ To see all options for the NET command: NET /?
Using the Service Control Utility (sc.exe) The Service Control command-line utility comes installed with Windows XP and Windows .NET Servers. It also comes as a part of the Win32 SDK and the .NET Framework SDK. The Service Control utility provides various options to start, pause, continue, stop, configure, and query a Windows service, as shown in Figure 7.3.
Figure 7.3 The Service Control utility provides a powerful way to control and configure Windows services from the command line.
Controlling a Windows Service You might also need to manipulate a Windows service programmatically from your program. You can use the ServiceController class of the System.ServiceProcess namespace to programmatically control Windows services from your applications. Table 7.4 lists some important methods and properties of this class.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Windows . . . . . Services . . . . . Table 7.4 Important Members of the ServiceController Class Member
Type
Description
CanPauseAndContinue
Property
A value of True indicates that the service can be paused and resumed.
CanShutdown
Property
A value of True indicates that the service should be notified when the system is shutting down.
CanStop
Property
A value of True indicates that the service can be stopped after it has started.
Close
Method
Disconnects the ServiceController object from the Windows service.
Continue
Method
Continues a Windows service after it has been paused.
DisplayName
Property
Specifies a friendly name for the service.
ExecuteCommand
Method
Executes a custom command on the service.
GetServices
Method
Retrieves the Windows services installed on a computer.
MachineName
Property
Specifies the name of the computer on which this service resides. Its default value is set to the local computer. You need to change the MachineName property only in the case where you want to control the Windows services on a remote machine.
Pause
Method
Suspends a Windows service’s operation.
Refresh
Method
Refreshes the values of all the properties with their latest values.
ServiceName
Property
Specifies the name of the Windows service.
ServicesDependedOn
Property
Specifies the set of services that this Windows service depends on.
ServiceType
Property
One of ServiceType enumeration values that specifies how the Windows service is used. A Windows service can be of one of these types— InteractiveProcess (can communicate with the desktop), Win32OwnProcess (runs in its own process), or Win32ShareProcess (shares the process with other Windows services).
Start
Method
Starts the Windows service.
Status
Property
Retrieves the status of the Windows service. (continued)
179
180 Chapter 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Table 7.4 Important Members of the ServiceController Class (continued) Member
Type
Description
Stop
Method
Stops the Windows service and other services that are dependent on this service.
WaitForStatus
Method
Waits for the service to reach the specified status, which is a value of the ServiceControllerStatus enumeration. Its possible values are ContinuePending, Paused, PausePending, Running, StartPending, Stopped, and StopPending.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Windows . . . . . Services . . . . .
Exam Prep Questions Question 1 You are designing an application that needs to know the Windows services that are installed on a computer. Which of the following classes would allow you to retrieve this information? ❍ A. ServiceBase ❍ B. ServiceInstaller ❍ C. ServiceController ❍ D. ServiceProcessInstaller
Answer C is correct. The ServiceController class is used to enumerate and interact with the services already installed on a computer. Answer A is incorrect because ServiceBase is the class from which all services written in .NET derive. Answers B and D are incorrect because the ServiceInstaller and ServiceProcessInstaller classes are used to install services, not to interact with them after they’re installed.
Question 2 You are designing a Windows service application, and you want to set the service to start only when manually instructed to do so. Which of the following classes would allow you to specify this setting at the time the service is installed? ❍ A. ServiceBase ❍ B. ServiceInstaller ❍ C. ServiceController ❍ D. ServiceProcessInstaller
Answer B is correct. The StartType property of the ServiceInstaller class controls whether the service will be automatically started when Windows starts. Answer A is incorrect because ServiceBase is the class from which all services written in .NET derive. Answer C is incorrect because the ServiceController class is used to interact with already-installed services, not to change installation settings. Answer D is incorrect because the ServiceProcessInstaller class controls the overall service installation process, not the details of any single service.
181
182 Chapter 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 3 Which of the following methods is every Windows service required to implement? ❍ A. OnContinue ❍ B. OnPause ❍ C. OnStart ❍ D. OnStop
Answer C is correct. Every Windows service must contain an OnStart method, which is called when the service is started. Answers A, B, and D are incorrect because OnContinue, OnPause, and OnStop can be suppressed by properly setting other properties of the service class.
Question 4 You are developing a Windows service that needs to write an entry to the Application event log whenever the service is started, paused, resumed, or stopped. How should you fulfill this requirement? ❍ A. Create an EventLog component in the project and use this component to write entries in the event log. ❍ B. Create a method that writes entries in the event log and call this method from the OnStart, OnStop, OnPause, and OnContinue methods of the Windows service class. ❍ C. Set the AutoLog property of the Windows service class to True. ❍ D. Add an EventLog component to the ServiceInstaller class that you use to install the Windows service.
Answer C is correct. Setting the AutoLog property of the service to True makes the service automatically notify the event log of any change of state. Answers A and B are incorrect because, although they would work, they require you to spend time writing code to achieve the same effect that you can get by setting a property. Answer D is incorrect because the ServiceInstaller class has no effect on the runtime behavior of the component.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Windows . . . . . Services . . . . .
Question 5 You have created a Windows service application that contains three services, named A, B, and C. The Installers for the services install them in that order. During a test installation, service B fails to install properly due to a bad path setting. Which services will be installed on the computer? ❍ A. Service A only. ❍ B. Service C only. ❍ C. Services A and C. ❍ D. No services will be installed.
Answer D is correct. The installutil.exe tool treats an installation as a single transaction. If you have multiple services in a single application, and any one of them fails to install properly, the entire installation will be rolled back. Answers A, B, and C are incorrect because they all specify that services will be installed in this situation.
Question 6 You have designed a Windows service application that contains two Windows services. You now want to add Installer classes to this application so that the application can be installed by using installutil.exe. You have added a new class inherited from the Installers class in your application. To the Installers collection of this class, you would like to add the custom installation components for properly installing the Windows services in your application. Which of the following combinations of custom components should you add to the Installers collection of the Installer class? ❍ A. Add two instances each of the ServiceInstaller class and the ServiceProcessInstaller classes. ❍ B. Add two instances of the ServiceInstaller class and one instance of the ServiceProcessInstaller class. ❍ C. Add two instances of the ServiceProcessInstaller class and one instance of the ServiceInstaller class. ❍ D. Add one instance each of the ServiceInstaller class and the ServiceProcessInstaller classes.
Answer B is correct. Each service requires its own ServiceInstaller class, but the application only requires a single ServiceProcessInstaller class. Answers C and D are incorrect because they only specify a single ServiceInstaller class. Answers A and C are incorrect because they specify two ServiceProcessInstaller classes.
183
184 Chapter 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 7 You have created a Windows service and have added the proper Installer classes to the project. You have set the Account property of the ServiceProcessInstaller class to User but have left both the UserName and Password properties blank. What happens at installation time? ❍ A. The service fails to install. ❍ B. The service is installed using the LocalSystem account. ❍ C. The service is installed to run as a user with a blank username and password. ❍ D. You are prompted to enter a username and password at installation time.
Answer D is correct. Leaving the UserName and Password properties blank tells the ServiceProcessInstaller class to prompt you for a username and password at installation time. Answer A is incorrect because the service will still install. Answers B and C are incorrect because they do not correctly identify the security context of the installed service.
Question 8 You have used Visual Basic .NET to develop a Windows service. You would like to set the description shown for the service in the Services MMC snap-in. How should you proceed? ❍ A. Use the Service Control utility to set the description after the service is installed. ❍ B. Set the Assembly Name property of the service project to the description you want to display. ❍ C. Set the DisplayName property of the ServiceInstaller class to the desired description. ❍ D. Set the ServiceName property of the ServiceInstaller class to the desired description.
Answer A is correct. The Framework Class Library (FCL) does not provide a programmatic way to set the service description, so you must do it with the sc.exe utility after installation. Answer B is incorrect because the Assembly Name property controls the filename of the service executable. Answer C is incorrect because the DisplayName property controls the name of the service in the tool, not its description. Answer D is incorrect because the ServiceName property is used to tell the ServiceInstaller class which service to install.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Windows . . . . . Services . . . . .
Question 9 You have developed a Windows service that will perform mission-critical communications tasks. You must ensure that the service cannot be paused after it has been started. Which of these steps should you take to fulfill this requirement? ❍ A. Do not include a definition for the OnStop method in the class definition for Windows service. ❍ B. Do not include definitions for the OnPause and OnContinue methods in the class definition of the Windows service. ❍ C. Set the CanStart property of the Windows service to True, but set the CanStop properties to False. ❍ D. Set the CanPauseAndContinue property of the Windows service to False.
Answer D is correct. To prevent a service from being paused, you set the CanPauseAndContinue property to False. Answers A and C are incorrect because the OnStop method is not involved with pausing the service. Answer B is incorrect because omitting the methods will not prevent the SCM from attempting to pause the service. Instead, it will cause an exception when the SCM attempts to pause the service.
Question 10 You have recently designed a Windows service application. You now want to install the application in order to test its functionality. Which of the following options should you choose to install this application? ❍ A. Use the Visual Studio .NET Server Explorer window. ❍ B. Use the Services MMC snap-in. ❍ C. Use net.exe ❍ D. Use installutil.exe
Answer D is correct. Of the listed options, only installutil.exe can install a service. Answers A, B, and C are incorrect because these tools can interact with a service that’s already installed, but they cannot install a service themselves.
185
186 Chapter 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Need to Know More? Gunderloy, Mike. MCAD/MCSD Developing and Implementing Windows-based Applications with Visual Basic .NET and Visual Studio .NET Exam 70-306 Training Guide. Que, 2002. .NET Framework SDK Documentation: “Walkthrough: Creating a Windows Service Application in the Component Designer.”
8 Component Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terms you’ll need to understand: ✓ Activation type ✓ COM+ application ✓ COM+ catalog ✓ COM interface ✓ Context ✓ DTC (Distributed Transaction Coordinator) ✓ Just-in-time activation ✓ Object pooling ✓ Queued components ✓ Transaction
Techniques you’ll need to master: ✓ Implementing a services component ✓ Registering and configuring COM+ components ✓ Using the Component Services tool
188 Chapter 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
The .NET Framework is designed to work well with COM+, the enterprise infrastructure provided by Windows. COM+ incorporates functionality for security, reliability, availability, efficiency, and scalability as part of the operating system infrastructure. As a result, programmers need not write these features repeatedly in each application they develop. Instead, they can just request the operating system to provide these services.
Features of COM+ COM+ provides the following set of features to enterprise applications: ➤ Transaction management—This allows a set of objects to perform individ-
ual operations. Each object votes for the success or failure of the entire group of operations. If all objects vote for success, the entire transaction is committed; otherwise, every part of the transaction is rolled back. ➤ Object pooling—With object pooling, COM+ creates objects and keeps
them in a pool. When an application finishes using an object, it is returned to the pool, ready to be used when the next client makes a request. This improves the performance of a server application that hosts objects that are frequently used but are expensive to create. ➤ Just-in-time (JIT) activation—The objective of JIT activation is to mini-
mize the amount of time an object lives and consumes resources on the server. With JIT activation, the client can hold a reference to an object on the server for a long time, but the server only creates the object “just in time” when the client calls a method on the object. ➤ Role-based security—In the role-based security model, access to parts of
an application are granted or denied based on the role to which the callers belong. A role defines which users or groups in a Windows domain are allowed to work with what components, methods, or interfaces. ➤ Queued components—The queued components service allows you to cre-
ate components that can execute asynchronously, or in disconnected mode. Consider a scenario in which the salespersons take their laptop computers to the field and enter the orders on the go. Because they are in disconnected mode, these orders can be queued up in a message queue. When a salesperson connects back to the network, the orders can be retrieved from the message queue and processed by the order-processing components on the server.
189 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Component . . . . . . Services . . . . . ➤ Loosely coupled events—Loosely coupled events enable an object (publish-
er) to publish an event. Other objects (subscribers) can subscribe to an event. COM+ does not require the publisher or subscriber to know about each other. Therefore, loosely coupled events greatly simplify the programming model for distributed applications. COM+ 1.5 (the version in Windows XP and Windows Server 2003) adds two additional features: ➤ The ability to run a COM+ application as a Windows service—COM+ 1.5
allows you to configure a COM+ application to run as a Windows service. ➤ The ability to run a COM+ application as a Web service—COM+ 1.5 can
expose any COM+ component as an XML Web service as long as the component complies with Web services design guidelines. COM+ installs the Web service with IIS and generates the proper Web service configuration and information files.
Exposing .NET Components to COM/COM+ When COM+ was developed, COM was the prevalent componentdevelopment technology. Therefore, COM+ was developed with COM in mind. COM+ recognizes only COM components. Any .NET component that is exposed to COM+ must be exposed as a COM component.
Calling a .NET Component from COM/COM+ In order for COM+ (or any COM client) to find a .NET component, you need to register the .NET component as a COM server in the Windows Registry. This process is known as the assembly-registration process, and it can be performed by using any of the following methods: ➤ When using Visual Studio .NET, open the project’s property pages and
check the Register for COM Interop check box. ➤ Use the Assembly Registration tool (regasm.exe) that ships as a part of
the .NET Framework. ➤ In a program, use the RegistrationServices class of the
System.Runtime.InteropServices namespace.
190 Chapter 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Before you use any of these options, you must sign the .NET assembly using the Strong Name tool (sn.exe).
Exporting .NET Components As COM Type Libraries The .NET Framework also allows the .NET programmers to export their components as COM type libraries, by using a tool that creates a COMcallable wrapper (CCW). COM programmers can use the type information stored inside CCW to compile their programs and gain the benefit of early binding to the .NET types. Early binding significantly reduces the time required to access an object and additionally allows compilers to enforce type checking at compile time. You can export a .NET type as a COM type library by using any of the following methods: ➤ When using Visual Studio .NET, open the project’s property pages and
check the Register for COM Interop check box. ➤ Use the Assembly Registration tool (regasm.exe) with its
/tlb
option.
➤ Use the Type Library Exporter tool (tlbexp.exe) that ships as a part of
the .NET Framework SDK. ➤ In a program, use the ConvertAssemblyToTypeLib() method of the
TypeLibConverter class in the System.Runtime.InteropService namespace.
Architecture of Component Services You’ll need to understand some of the basic architecture of Component Services to pass the exam: ➤ Serviced components ➤ Declarative COM+ programming ➤ COM+ applications ➤ The COM+ catalog ➤ Serviced component activation
191 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Component . . . . . . Services . . . . .
Serviced Components Any class that uses enterprise services must derive from the System.EnterpriseServices.ServicedComponent class. Such a class is also called a serviced component. COM can only instantiate a .NET class with its public default constructor. COM can’t create an object and pass parameters for object creation at the same time.
The ServicedComponent class has methods but no properties or events. I have listed some important methods of this class in Table 8.1. All these methods are protected except the DisposeObject() method, which is a public static method. You can override the protected methods in a class inherited from the ServicedComponent class. Table 8.1 Important Methods of the ServicedComponent Class Method
Description
Activate()
Can be used to perform startup operations. It is called when an object is created or allocated from a pool.
CanBePooled()
Indicates whether the object should be pooled. It is called when an object is to be moved to the pool.
Construct()
Provides access to the construction string of the serviced component. It is called after the serviced component object is created (that is, after the constructor is executed).
Deactivate()
Can be used to perform cleanup operations. It is called when an object is about to be deactivated (that is, destroyed or moved to a pool).
DisposeObject()
Finalizes the resources used by the serviced component and removes the associated COM+ reference.
Declarative Programming Model Unlike the conventional procedural model, the programming model for enterprise services is declarative in large part. In Visual Basic .NET, you use attributes for this purpose. For example, to create a serviced component that supports transactions, you add the Transaction attribute, as shown here: _ Public Class MySampleSC Inherits ServicedComponent ... End Class
192 Chapter 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Formally, attributes are represented by classes whose names end in the word “Attribute.” So, for example, the Transaction attribute is implemented by the TransactionAttribute class. In coding, you are allowed to leave off the “Attribute” suffix, and I recommend that you do so to increase your code’s readability.
Table 8.2 lists some of the attributes you can use in your .NET code to configure a serviced component. Table 8.2 Attributes in the System.EnterpriseServices Namespace Attribute
Scope
Description
ApplicationActivation
Assembly
Specifies whether the serviced components are activated in the creator’s process (ActivationOption.Library, the default value) or in the system’s process (ActivationOption.Server).
ApplicationID
Assembly
Specifies the GUID of the COM+ application.
ApplicationName
Assembly
Specifies the name of the COM+ application.
ApplicationQueuing
Assembly
Enables queuing support for the COM+ application.
AutoComplete
Method
Indicates whether the method should automatically notify the COM+ context about its success or failure when it completes.
Description
Assembly, Class, Method, Interface
Specifies the description of the assembly, class, method, or interface.
EventClass
Class
Indicates that a class can participate in loosely coupled events.
EventTrackingEnabled
Class
Enables event tracking on the component.
InterfaceQueuing
Class, Interface
Enables queuing support on the specified interface or class.
JustInTimeActivation
Class
Indicates whether the serviced component supports just-in-time activation.
MustRunInClientContext Class
Indicates whether the serviced component must be created in the creator’s context.
ObjectPooling
Class
Indicates whether the serviced component will be created in an object pool and configures the size of the pool.
PrivateComponent
Class
Specifies that a serviced component should not be visible and should not be activated outside its containing COM+ application. (continued)
193 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Component . . . . . . Services . . . . . Table 8.2 Attributes in the System.EnterpriseServices Namespace (continued) Attribute
Scope
Description
Synchronization
Class
Specifies the synchronization support offered to the serviced component. It controls how multiple threads can execute the methods of the serviced component simultaneously.
Transaction
Class
Specifies the transaction support required by the serviced component.
COM+ Applications A COM+ application is a group of serviced components that perform related functions. Each of these components further consists of interfaces and methods. A COM+ application is the primary unit of administration and deployment for a serviced component. A COM+ application is always stored in a DLL file. A DLL file cannot run on its own. Therefore, a COM+ application is always configured to run in one of the following two ways: ➤Server application—In a server application, a COM+ application runs in
its own process. To enable this, COM+ provides a surrogate process (dllhost.exe) that hosts the DLL file for the COM+ application. ➤ Library application—In a library application, the COM+ application runs
in the process of the client that creates it. To enable this, the components in a library application are always loaded into the process of the creator. When choosing whether to run a COM+ application as a server application or a library application, you should look at both security and functional requirements. Server applications tend to offer lower performance but higher security than library applications. Library applications also do not support some COM+ services, including object pooling and queued components.
COM+ uniquely identifies each COM+ application and its components using GUIDs. If you don’t specify these GUIDs explicitly, the assemblyregistration process will assign them automatically. Each component in an assembly can be uniquely identified by applying the Guid attribute, as in the following code: Public Class NorthwindSC
194 Chapter 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Inherits ServicedComponent Implements INorthwind ...
COM+ Catalog The COM+ catalog stores information about COM+ applications. Each COM+ application and serviced component is uniquely identified in the COM+ catalog using a globally unique identifier (GUID). The other important information stored in the COM+ catalog for a serviced component is its runtime requirements. For example, if a component requires a transaction, this information is stored in the COM+ catalog. Later, when the component is activated, COM+ services use the catalog to determine the runtime requirements of the component. You can access and update the catalog in an integrated way by using the Component Services administrative tool. This tool is available in the Administrative Tools section of the Windows Control Panel.
Serviced Component Activation COM+ uses a somewhat complex process to activate serviced components. The steps are as follows: 1. When a client program creates a new instance of a serviced compo-
nent, .NET Enterprise Services uses the COM-based CoCreateInstance() API to request COM+ Component Services to instantiate the serviced component. 2. COM+ Component Services uses the GUID of the component to
retrieve the runtime information of the serviced component from the COM+ catalog. COM+ Component Services then checks to see if the client program is running in an environment that is compatible with the runtime requirements of the serviced component. 3. If the runtime requirements of the serviced component match with
those of the client program, the new object is created in the same context (runtime environment) as the client program. A reference to the newly created object is returned to the client program so that the client program can make direct calls on the newly created object. 4. If the runtime requirements of the serviced component are not com-
patible with those of the client program, COM+ Component Services creates a new context that matches the runtime requirements of the client and creates the serviced component object in that environment.
195 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Component . . . . . . Services . . . . .
COM+ Component Services then creates a proxy (a component with the same interface as the actual component, but which forwards all its requests to COM+) and returns the proxy to the client program. 5. The client program uses the proxy to communicate with the serviced
component object. A context is a set of properties that defines a runtime environment for the serviced component. A context is created during the activation process for a serviced component that is configured to require certain automatic services. Objects having the same runtime requirements share a context, whereas those having incompatible runtime requirements must reside in different contexts. An object can access its context-specific properties using the ContextUtil class of the System.EnterpriseService namespace. Table 8.3 shows some members of this class. Table 8.3 Important Members of the ContextUtil Class Member
Type
Description
DeactivateOnReturn
Property
Indicates whether the object should be deactivated when the object’s method returns.
DisableCommit()
Method
Tells the COM+ context to vote for aborting the current transaction. This method does not deactivate the object when the object’s method returns.
EnableCommit()
Method
Tells the COM+ context to vote for committing the current transaction. This method does not deactivate the object when the object’s method returns.
IsCallerInRole()
Method
Determines whether the caller is in a specified role.
IsInTransaction
Property
Indicates whether the current COM+ context is transactional.
IsSecurityEnabled
Property
Indicates whether the current COM+ context has role-based security enabled.
MyTransactionVote
Property
Specifies the COM+ context transaction vote—abort or commit.
Transaction
Property
Represents the current COM+ transaction object.
SetAbort()
Method
Indicates the COM+ context to vote for aborting the current transaction. This method also deactivates the object when the object’s method returns.
SetComplete()
Method
Indicates the COM+ context to vote for committing the current transaction. This method also deactivates the object when the object’s method returns.
196 Chapter 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Creating and Consuming a Serviced Component The following steps are typically involved in creating and registering a serviced component: 1. Create a class that inherits from the ServicedComponent class. 2. Compile the class and assign a strong name to create a strongly named
assembly. 3. Install the strongly named assembly in the Global Assembly Cache
(GAC). 4. Run the Services Installation Tool (regsvcs.exe) to install the assembly
into the COM+ catalog. After you have installed the serviced component in the COM+ catalog, you can create instances of the component or use the Component Services administrative tool to configure it.
Creating a Serviced Component To create a serviced component and register it with COM+, follow these steps: 1. Launch Visual Studio .NET. Select File, New, Blank Solution, and
name the new solution SC. Click OK. 2. Add a new Visual Basic .NET Class Library named SCLib to the solu-
tion. 3. Add a reference to the System.EnterpriseServices namespace to the
new project. 4. In the Solution Explorer, change the name of the default Class1.vb to
NorthwindSC.vb. 5. Open NorthwindSC.vb and replace the code with the following code: Imports Imports Imports Imports Imports
System System.Data System.Data.SqlClient System.EnterpriseServices System.Runtime.InteropServices
_ Public Class NorthwindSC Inherits ServicedComponent
197 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Component . . . . . . Services . . . . . Private sqlcnn As SqlConnection Private sqlda As SqlDataAdapter Private ds As DataSet Public Sub New() ‘ Create a connection to the ‘ Northwind SQL Server database sqlcnn = New SqlConnection( _ “data source=(local);” & _ “initial catalog=Northwind;” & _ “integrated security=SSPI”) End Sub ‘ This method executes a SELECT query and ‘ returns the results in a DataSet object Public Function ExecuteQuery( _ ByVal strQuery As String) As DataSet ‘ Create a SqlDataAdapter object to ‘ talk to the database sqlda = New SqlDataAdapter( _ strQuery, sqlcnn) ‘ Create a DataSet object ‘ to hold the results ds = New DataSet() ‘ Fill the DataSet object sqlda.Fill(ds, “Results”) ExecuteQuery = ds End Function ‘ This method updates the database with ‘ the changes in a DataSet object Public Function UpdateData( _ ByVal ds As DataSet) As Integer ‘ Update the database ‘ and return the result Dim sqlcb As SqlCommandBuilder = _ New SqlCommandBuilder(sqlda) UpdateData = sqlda.Update( _ ds.Tables(“Results”)) End Function End Class
6. Open the AssemblyInfo.vb file in the project and add the following
Imports directive: Imports System.EnterpriseServices
7. Add assembly-level attributes, as shown here:
198 Chapter 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8. From the Visual Studio .NET program group in the Windows Start
menu, launch the Visual Studio .NET command prompt. 9. Change the directory to the folder where the SCLib project resides
and issue the following command to create a pair of public/private keys: sn -k sclib.snk
10. Select Build, Build SCLib. This step packages the serviced component
into the file SCLib.dll, which is located in the bin directory of your project. 11. In the Visual Studio .NET Command Prompt window, change the
directory to the folder where the SCLib.dll file resides. 12. Issue the following command to install the serviced component assem-
bly to the COM+ catalog: regsvcs SCLib.dll
13. Issue the following command to install the assembly to the Global
Assembly Cache (GAC): gacutil /i SCLib.dll
14. Open the Component Services administrative tool from the
Administrative Tools section of the Windows Control Panel. Using the tree on the left side, navigate to Computers, My Computer, COM+ Applications. You should be able to view the Northwind Data Application, as shown in Figure 8.1. You can explore the application here to see its properties.
Consuming a Serviced Component Instantiating and using a serviced component is no different from instantiating and using any other managed component. Follow these steps to try it with the component you just created: 1. Add a new Visual Basic .NET Windows application named SCClient
to the solution. 2. Add references to the System.EnterpriseServices namespace and the
SCLib project. 3. Open the default form in code view.
199 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Component . . . . . . Services . . . . . 4. Add the following Imports directives: Imports System.Data.SqlClient Imports SCLib
5. Place two Label controls, a TextBox control (txtQuery), two Button
controls (btnExecute and btnUpdate), and a DataGrid control (dgResults) on the form. Arrange the controls as shown in Figure 8.2. Set the Multiline property of the TextBox control to True.
Figure 8.1 Administering a Component Services application.
Figure 8.2 The design of a form that uses the SCLib serviced component.
200 Chapter 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6. Add the following code in the class definition of the form: ‘ Declare the serviced component Private nsc As NorthwindSC
7. Add the following code in the Load event handler: Private Sub Form1_Load( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ‘ Instantiate the serviced component nsc = New NorthwindSC() End Sub
8. Add the following code to the Click event handlers for the Button con-
trols: Private Sub btnExecute_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnExecute.Click Try ‘ Call the ExecuteQuery() method of the ‘ NorthwindSC serviced component to execute ‘ query and bind the results to the data grid dgResults.DataSource = _ nsc.ExecuteQuery(txtQuery.Text) dgResults.DataMember = “Results” Catch ex As Exception MessageBox.Show(ex.Message, “Invalid Query”, _ MessageBoxButtons.OK, MessageBoxIcon.Error) End Try End Sub Private Sub btnUpdate_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnUpdate.Click Try ‘ Call the UpdateData() method of the ‘ NorthwindSC serviced component to update ‘ the database and display the number ‘ of updated rows in the database Dim intRows As Integer = nsc.UpdateData( _ CType(dgResults.DataSource, DataSet)) MessageBox.Show(String.Format( _ “{0} row(s) updated successfully”, intRows), _ “Row(s) Updated”, MessageBoxButtons.OK, _ MessageBoxIcon.Information) ‘ Load the updates and bind the grid ‘ with the updates dgResults.DataSource = _ nsc.ExecuteQuery(txtQuery.Text) dgResults.DataMember = “Results” Catch ex As Exception MessageBox.Show(ex.Message, “Update Failed”, _ MessageBoxButtons.OK, MessageBoxIcon.Error) End Try End Sub
201 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Component . . . . . . Services . . . . . 9. Build the project and set it as the startup project for the solution. 10. Run the solution. Enter a query in the text box and click the button.
The code invokes a method on the serviced component. The code binds the results from the method to the DataGrid control. Make some changes to the data in the DataGrid control and click the Update button to save the changes to the database. If there is no error in the updates, a message box with the number of rows updated will be displayed.
Understanding and Using Enterprise Services Although you know how to create and consume a serviced component, there’s not much point to this unless you use some of the automatic services provided by COM+. In this section, I’ll give you a high-level overview of the following COM+ services: ➤ Object pooling ➤ Just-in-time activation ➤ Object construction ➤ Automatic transaction management ➤ Queued components
Object Pooling The object pooling service allows you to increase the scalability and performance of an application by minimizing the time and resources required in creating objects repeatedly. It does this by maintaining a pool of already created objects and then efficiently reusing them repeatedly. You can configure a class to use the object pooling service by applying the ObjectPooling attribute on the class, as shown in the following example: _ Public Class NorthwindSC Inherits ServicedComponent Implements INorthwind ...
202 Chapter 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Table 8.4 lists various properties of the ObjectPooling attribute that you can use to configure the way object pooling works for the class. Table 8.4 Properties of the ObjectPooling Attribute Property
Description
CreationTimeout
Specifies a length of time (in milliseconds) to wait for an object to become available in the pool before throwing an exception.
Enabled
Specifies whether object pooling is enabled for a component; the default value for this property is True.
MaxPoolSize
Specifies the maximum number of pooled objects that should be created for a component.
MinPoolSize
Specifies the minimum number of objects that should be available to a component at all times.
In addition to using the ObjectPooling attribute, an object-pooled class also overrides the CanBePooled() method of the ServicedComponent class. The overridden version of this method should return either True or False. An object is only pooled if the CanBePooled() method returns True. At a conceptual level, you can envision that COM+ places a Pooling Manager between the client and the server, as shown in Figure 8.3.
Figure 8.3 The Pooling Manager intercepts any requests for object creation and provides the object pooling service.
The Pooling Manager follows a set of rules for creating objects: ➤ When the COM+ application is started, a MinPoolSize number of
objects are created and thereafter maintained in the pool at all times when the application is running. ➤ Each time the pooling manager receives a request to create an object,
the Pooling Manager checks to see whether the object is available in the pool. If the object is available, the Pooling Manager provides an already created object from the pool.
203 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Component . . . . . . Services . . . . . ➤ If no objects are currently available in the pool, the Pooling Manager
checks to see whether the number of objects currently in the pool has reached MaxPoolSize. If not, the Pooling Manager creates new objects to fulfill the request. The Pooling Manager creates as many objects as needed to keep the available objects at the level of MinPoolSize while not exceeding MaxPoolSize. ➤ If no object is available and no new object can be created because of the
size restriction of the pool, the client requests are queued to receive the first available object from the pool. If an object cannot be made available within the time specified in the CreationTimeOut property, an exception is thrown. ➤ When the client is done with an object, it invokes the Dispose() method
on the object. The Pooling Manager intercepts this request and calls the CanBePooled() method on the object to check whether the object can be pooled. If the method returns True, the object is stored in the object pool. Otherwise, the object is destroyed. Object pooling is most useful in the following situations: ➤ When the cost of creating an object is relatively high ➤ When usage costs are relatively low ➤ When an object will be reused often ➤ When you want to limit the number of object instances
Object pooling might not be useful in these situations: ➤ When an object is inexpensive to create ➤ When the object does not maintain any state ➤ When the object must be activated in the caller’s context ➤ When you do not need to restrict the number of object instances
Just-in-Time Activation When you’re using object pooling, there are two ways you can approach object creation from the client: ➤ In the first approach, a client creates an object and holds onto it until
the client no longer needs it. The advantage of this approach is that it’s faster because clients need not create objects repeatedly. The
204 Chapter 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
disadvantage is that this approach can be expensive in terms of server resources in a large-scale application. ➤ In the second approach, a client can create, use, and release an object.
The next time it needs the object, it creates it again. The advantage to this technique is that it conserves server resources. The disadvantage is that as your application scales up, your performance slows down. If the object is on a remote computer, each time an object is created, there must be a network roundtrip, which negatively affects performance. The just-in-time activation service of COM+ provides a server-side solution that includes advantages of both of the preceding approaches while avoiding the disadvantages of each. To use this service in a class, all you need to do is to mark the class with the JustInTimeActivation attribute set to True. When the client requests a just-in-time object from the server, COM+ intercepts that request, creates a proxy, and returns the proxy to the client. The client maintains a long-lived reference to the proxy, thinking that it is a reference to the actual object. This way, the client does not spend time repeatedly creating the object. The server also saves resources because it can delay creating the object until the client invokes a method on it. When the client invokes a method on the object (using the proxy), COM+ actually creates the object, calls the method, returns the results, and then destroys the object. Because the objects are short lived, server resources are consumed only for a small period, and the server is readily available to serve other waiting clients. COM+ maintains a “done bit” to specify when the object will be deactivated. The interception mechanism checks the done bit after each method call finishes. If the value of the done bit is True, the object is deactivated. You can set this bit to True in the following ways: ➤ Using the ContextUtil.SetComplete() or ContextUtil.SetAbort() method—
Usually these methods are used to vote for the success or failure of a transaction, but they also set the done bit to True. ➤ Using the ContextUtil.DeactivateOnReturn property—When you set this
property to True in a method, the property sets the done bit to True. ➤ Using the AutoComplete attribute—When you always want to deactivate
an object when the method call returns, you can apply this attribute to the method definition. This attribute automatically calls ContextUtil.SetComplete() if the method completes successfully. If the method throws an exception, the ContextUtil.SetAbort() method is invoked. In both cases, the done bit is set to True.
205 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Component . . . . . . Services . . . . .
The JIT activation and object pooling services complement each other’s features. When these services are used in combination, they can maximize the throughput for an application by providing the following benefits: ➤ JIT activation enables clients to hold long-lived references to a server
object (through a proxy) without consuming server resources. ➤ JIT activation enables the server objects to be destroyed as soon as their
work is over in order to minimize the resource consumption on the server. ➤ Object pooling caches already created objects and saves time by activat-
ing and deactivating the objects from the pool instead of re-creating them from scratch. If offered a choice of which COM+ services to use in an application, remember that object pooling and JIT activation usually work together.
Automatic Transaction Processing A transaction is a series of operations performed as a single unit. A transaction is successful only when all the operations in that transaction succeed. The transaction-processing mechanism of COM+ provides two significant advantages over traditional transaction-processing techniques: ➤ Distributed transactions—A local transaction is one whose scope is limited
to a single transactional resource, such as a SQL Server database. On the other hand, a distributed transaction can span over several transactionaware resources. The transaction-aware resources in a distributed transaction might be heterogeneous (such as SQL Server database, Oracle database, Microsoft Messaging Queue) and might involve multiple computers over a network. ➤ Automatic transactions—A typical database transaction, such as the one
implemented using Transact-SQL code or ADO.NET code, is manual in nature. With manual transactions, you explicitly begin and end transactions and implement all the necessary logic to take care of the commit and rollback process. However, COM+ provides automatic transaction services that you can use in your program without writing any additional code. COM+ implements this with the help of a Windows service called Microsoft Distributed Transaction Coordinator (MSDTC).
206 Chapter 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Applying the System.EnterpriseService.Transaction attribute to a class enables that class for transactions. The Transaction attribute takes a value from the TransactionOption enumeration values listed in Table 8.5. Table 8.5 Members of the TransactionOption Enumeration Member
Description
Disabled
Specifies that the component’s ability to participate with COM+ in managing transactions has been disabled. This setting is for compatibility reasons only.
NotSupported
Specifies that the component will never participate in transactions.
Required
Specifies that the component uses transactional resources such as databases and will participate in a transaction if one already exists; otherwise, a new transaction must be created.
RequiresNew
Specifies that the component requires a new transaction to be created even if a transaction already exists.
Supported
Specifies that the component will participate in a transaction if one already exists. This setting is mostly used by the components that do not themselves use any transactional resources. To preserve the consistency of a transaction, a component must not carry state from one transaction to another. To enforce statelessness for all transactional components, COM+ uses JIT activation. JIT activation forces an object to deactivate and lose state before the object can be activated in another transaction. For a class, if you apply the Transaction attribute and set its value to TransactionOption.Supported, TransactionOption.Required, or TransactionOption.RequiresNew, COM+ automatically sets the JustInTimeActivation attribute to True.
Each component that participates in a transaction has its own context. This context stores various flags that specify the state of an object. Two such flags are the done bit and the consistent bit. In addition to objects, the transaction itself has a context. The context of a transaction maintains an abort bit. The purpose of abort bit is to determine whether the transaction as a whole failed or succeeded. Table 8.6 shows how these bits interact.
207 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Component . . . . . . Services . . . . . Table 8.6 The Abort, Done, and the Consistent Bits and Their Effect on the Transaction Outcome Bit
Scope
Abort
Entire This bit is also called the transaction doomed bit. COM+ sets this bit to False when creating a new transaction. If this bit is set to True in a transaction’s lifetime, it cannot be changed back.
Effect on the Transaction Outcome
Description
If the abort bit is set to True,the transaction is aborted.
Consistent Each context
This bit is also called the happy bit. COM+ sets this bit to True when creating an object. A programmer can choose to set this bit to True or False, depending on the program logic, to indicate that the object is either consistent or inconsistent.
If the consistent bit in any of the contexts is set to False, the transaction is aborted. If the consistent bit in all the contexts is set to True, the transaction is committed.
Done
Each COM+ object that participates in a transaction must also support just-in-time activation and therefore must maintain a done bit. When a method call begins, the done bit is set to False. When a method call finishes, COM+ checks the status of the done bit. If the bit is True, the active object is deactivated.
When exiting a method, if the done bit is set to True and the consistent bit is set to False, then the Abort bit is set to True.
Each context
The .NET enterprise services library provides the ContextUtil class to work with the context of an object. Table 8.7 shows those methods of the ContextUtil class that influence the done bit and the consistent bit of an object. Table 8.7 How the Methods of the ContextUtil Class Affect the Consistent Bit and the Done Bit Method
Effect on Consistent Bit
Effect on Done Bit
DisableCommit()
False
False
EnableCommit()
True
False
SetAbort()
False
True
SetComplete()
True
True
208 Chapter 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Queued Components From the perspective of a client, a queued component is a serviced component that can be invoked and executed asynchronously. Queued components are based on the Microsoft Message Queuing (MSMQ) technology, which is part of the Windows operating system. Figure 8.4 shows schematically how queued components function.
Figure 8.4 With queued components, messages are recorded in a message queue for later retrieval.
Here’s a list of the pieces involved: ➤ Recorder—The recorder kicks in when a client makes a call to the queued
component. The recorder records the call, packages it as a message, and stores the message in the message queue. ➤ Queue—The queue is a repository of messages. Each COM+ application
has a set of queues assigned to it. ➤ Listener—The listener’s role is to poll the queue for incoming messages
and, when there is one, to pass the message to the player. ➤ Player—The player unpacks a message and invokes the methods that
were recorded by the client on the queued component. To configure a component to work as a queued component, you need to apply the following two attributes: ➤ The ApplicationQueuing attribute—You apply this attribute at the assembly
level to enable queuing support for an application. If a client will call queued components, the QueueListenerEnabled property must be set to True. Here’s an example:
➤ The InterfaceQueueing attribute—You apply this attribute at the compo-
nent level to specify the interface through which COM+ allows the calls on the component to be recorded and stored in the queue. This is shown in the following example:
209 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Component . . . . . . Services . . . . . When creating queued components, you need to keep some limitations in mind. Methods should not return value or reference parameters, and you shouldn’t use callbacks. These depend on continuous communication with the client, which might not be there in a queuing situation.
210 Chapter 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exam Prep Questions Question 1 You have developed a serviced component that will only be used by .NET clients. You intend to use COM+ to manage a pool of objects from this component. Which steps must you perform to enable this? [Select all correct answers.] ❑ A. Use the tlbexp utility to create a type library for the component. ❑ B. Sign the component with a strong name. ❑ C. Install the component in the Global Assembly Cache (GAC). ❑ D. Register the component in the COM+ catalog.
Answers B and D are correct. Components managed by COM+ must be registered in the COM+ catalog, and they must be signed with a strong name. Answer A is incorrect because a type library is not necessary for .NET clients. Answer C is incorrect because installation in the GAC is optional, not necessary.
Question 2 You have developed a distributed inventory-management system for your company. The system includes a front end designed as a Windows Forms application, and a set of serviced components that reside on various servers. You must be able to continue to enter inventory information even if one of the COM+ servers is unavailable. Which COM service can you use to enable this level of application availability? ❍ A. Automatic transactions ❍ B. Object pooling ❍ C. Queued components ❍ D. Just-in-time activation
Answer C is correct. By using queued components, you can ensure that messages from the front-end application are queued for later processing when a back-end server is unavailable. Answer A is incorrect because transactions ensure consistency in a system, not availability. Answers B and D are incorrect because object pooling and just-in-time activation will not do anything to improve availability if a component is unavailable.
211 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Component . . . . . . Services . . . . .
Question 3 You have created a serviced component that allows users on your intranet to retrieve information from the corporate accounting system. The component is registered in the COM+ catalog on your main corporate application server. Object pooling is enabled, with the minimum pool size set to 15 and the maximum pool size set to 50. You monitor the component and find that 50 copies of the object are in use. What will happen if another request for the object is received? ❍ A. An object in use is selected randomly and reassigned to the new request. ❍ B. A new object will be created to fulfill the request. ❍ C. The request is queued until either a connection is available or the timeout limit has been exceeded. ❍ D. The request generates an immediate exception.
Answer C is correct. The Pooling Manager will keep track of requests that exceed the maximum pool size and fill the request if an object becomes available before the timeout limit passes. Answer A is incorrect because a client application can hold the object as long as it likes. Answer B is incorrect because the Pooling Manager won’t exceed the maximum pool size. Answer D is incorrect because the Pooling Manager won’t throw an exception as part of normal pool management.
Question 4 The component that manages security in your system takes a comparatively long time to create, but it’s required by every client application. You have developed the security component as a serviced component. Which COM+ services can you use to make this expensive component more quickly available to client applications? [Select two.] ❑ A. Object pooling ❑ B. Automatic transactions ❑ C. Just-in-time activation ❑ D. Queued components
Answers A and C are correct. The combination of object pooling and justin-time activation allows you to deploy a pool of components that can be readily available to client applications without the overhead of creating the objects each time they are required. Answers B and D are incorrect because transactions and queuing do not cut the cost of object creation.
212 Chapter 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 5 You have developed a class that makes use of COM+ transaction services. At one point in your code, where you know operations have completed successfully, you want to commit the transaction and finish processing. Which method should you call? ❍ A. DisableCommit ❍ B. EnableCommit ❍ C. SetAbort ❍ D. SetComplete
Answer D is correct. The SetComplete method indicates that the transaction has completed successfully. Answer A is incorrect because the DisableCommit method prevents the transaction from being committed. Answer B is incorrect because EnableCommit signifies an intent to commit the transaction but does not itself commit the transaction. Answer C is incorrect because SetAbort rolls back the transaction.
Question 6 You have developed a COM+ application that needs to be available at all times, even when no one is logged on to the application server. You’ve decided to configure the application as a Windows service. Which operating systems can you use on the application server? [Select two.] ❑ A. Windows NT 4.0 ❑ B. Windows 2000 ❑ C. Windows XP ❑ D. Windows Server 2003
Answers C and D are correct. Running a COM+ application as a Windows service or as a Web service is a feature of COM+ 1.5. COM+ 1.5 is only available on Windows XP and Windows Server 2003. Answers A and B are incorrect because COM+ 1.5 is not available on these older operating systems.
213 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Component . . . . . . Services . . . . .
Question 7 Which of these components is a good choice for object pooling using COM+? ❍ A. A security component that cannot be shared between instances of the application. ❍ B. A hidden form component that must be activated in the caller’s context. ❍ C. A statistical component that must perform extensive analysis when it is instantiated. ❍ D. A random number component that is a thin wrapper over the System.Random class.
Answer C is correct. Object pooling is useful when the cost of creating an object is relatively high, because it enables you to reuse objects instead of recreating them. Answer A is incorrect because object pooling won’t help with objects that cannot be reused. Answer B is incorrect because object pooling doesn’t guarantee that an object will use the caller’s context. Answer D is incorrect because object pooling is not needed when a component is inexpensive to create.
Question 8 You have created a component that participates in sales transactions within your company. You are managing the transaction using COM+. This particular component can either participate in an existing transaction or create a new one, but it must be enlisted in a transaction. Which setting should you select for the TransactionOption enumeration? ❍ A. Disabled ❍ B. Required ❍ C. RequiresNew ❍ D. Supported
Answer B is correct. The Required member lets the component use an existing transaction if one is available, or it forces the creation of a new transaction if there is not an existing transaction. Answer A is incorrect because the Disabled member prevents the component from participating in transactions. Answer C is incorrect because the RequiresNew member prevents the component from participating in existing transactions. Answer D is incorrect because the Supported member allows the component to participate in transactions but does not require it to do so.
214 Chapter 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 9 You are deploying a serviced component that is licensed for a specific number of users. Which attribute can you use to limit the number of simultaneous connections to the serviced component? ❍ A. The JustInTimeActivation attribute ❍ B. The Transaction attribute ❍ C. The ApplicationQueuing attribute ❍ D. The ObjectPooling attribute
Answer D is correct. The ObjectPooling attribute can specify a maximum pool size, which will limit the number of connections to the object. Answer A is incorrect because just-in-time activation controls the lifetime of objects, but not their number. Answer B is incorrect because the Transaction attribute controls the scope of objects, but not their number. Answer C is incorrect because the ApplicationQueuing attribute does not limit the number of simultaneous objects.
215 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Component . . . . . . Services . . . . .
Need to Know More? Gunderloy, Mike. MCAD/MCSD Developing and Implementing Windows-Based Applications with Visual Basic .NET and Visual Studio .NET Exam 70-306 Training Guide. Que, 2002. Lowy, Juval, COM and .NET Component Services. O’Reilly, 2002. NET Framework SDK Documentation: “Writing Serviced Components.”
9 Calling Unmanaged Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terms you’ll need to understand: ✓ Runtime Callable Wrapper (RCW) ✓ Managed code ✓ Unmanaged code ✓ Platform Invoke
Techniques you’ll need to master: ✓ Instantiating and invoking a COM component from .NET code ✓ Using Platform Invoke (PInvoke) to call Windows API functions
218 Chapter 9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
When designing .NET, Microsoft recognized the need to provide easy migration paths from previous versions of its tools to the .NET world. In particular, if you heeded the advice to use COM for intercomponent communications and to design your applications as sets of COM servers and clients, you’ll find the upgrade path to .NET smooth. That’s because the .NET Framework includes good support for interoperating with existing COM-based code. In addition, .NET includes a capability called Platform Invoke (or PInvoke) that lets you use Windows API calls from within .NET applications.
Using COM Components .NET components can call COM components, and COM components can call .NET components. This means that you can migrate one component (a control, a class library, and so on) at a time and still keep all your code working together. The exam tests your ability to call COM components from .NET applications, so that’s what I’ll concentrate on. There are four basic reasons for maintaining part of a system in COM components while moving other parts to .NET components: ➤ It takes time to learn enough about Visual Basic .NET and the .NET
Framework to be productive. While you’re making your way up the learning curve, you may have to continue development of existing COM components. ➤ You may have components that can’t be easily moved to .NET because
they use language features that are no longer supported or because of other implementation quirks. ➤ It takes time to move code from one system to the other. Unless you can
afford extended downtime, a gradual move lets you write the converted code at a slower pace. ➤ Your application may depend on third-party controls or libraries for
which you do not have the source code. Although you can call COM code from .NET code, that doesn’t mean you should always do so. You’ll generally get improvements in performance, scalability, and maintainability by migrating the COM components instead of calling them directly.
219 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Calling . . . .Unmanaged . . . . . . Code . . .
Understanding Runtime Callable Wrappers As you probably already know, Visual Basic .NET creates code that operates within the .NET Common Language Runtime (CLR). Code that operates within the CLR is called managed code. Managed code benefits from the services that the CLR offers, including garbage collection, memory management, and support for versioning and security. Code that does not operate within the CLR is called unmanaged code. Code that was created by tools that are older than the .NET Framework is by definition unmanaged code. COM components are unmanaged code because COM was designed before the CLR existed, and COM components don’t make use of any of the services of the CLR. Managed code expects that all the code with which it interacts will use the CLR. This is an obvious problem for COM components. How can you take a component that was developed before the advent of .NET and make it look like a .NET component to other .NET components? The answer is to use a proxy. In general terms, a proxy accepts commands and messages from one component, modifies them, and passes them to another component. The particular type of proxy that allows you to use COM components within a .NET application is called a runtime callable wrapper (RCW). That is, it’s a proxy that can be called by the CLR. Figure 9.1 shows schematically how the pieces fit together.
Figure 9.1 An RCW allows you to use COM components within the .NET Framework.
220 Chapter 9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Registering a COM DLL Suppose you have a COM DLL named MyCustomer.dll. Like a .NET class library, this DLL can expose objects, methods, and properties. For example, MyCustomer.dll might contain a Balances class, with a CustomerCount property and a GetBalance method. When you build such a DLL using Visual Basic 6, the COM DLL is automatically registered in the Windows Registry. If you’re installing a DLL from some outside source, the installation program will normally call regsvr32.exe to register the file by using a command similar to the following: regsvr32 MyCustomer.dll
However, COM registration won’t make the objects in the COM DLL visible to .NET applications. For that, you need to create an RCW.
Using the Type Library Importer Tool (tlbimp.exe) The task of using COM components from the .NET Framework is made easier by the fact that COM components, like .NET components, have metadata that describe their interfaces. For .NET components, the metadata is embedded in the assembly manifest. For COM components, the metadata is stored in a type library. A type library can be a separate file, or (as with Visual Basic 6 class libraries) it can be embedded within another file. The .NET Framework includes a tool, the Type Library Importer tool (tlbimp.exe), that can create an RCW from COM metadata contained in a type library. For example, if MyCustomer.dll is registered on your computer, you can create the RCW by running this command line: tlbimp MyCustomer.dll /out:NETMyCustomer.dll
Note that you’ll need to run the command from within a .NET command prompt (Start, Programs, Microsoft Visual Studio .NET, Visual Studio .NET Tools, Visual Studio .NET Command Prompt). The resulting file, NETMyCustomer.dll in this case, is the RCW. You can set a reference to this file from the Add Reference dialog box within Visual Studio .NET and then use all the objects, methods, and properties it contains. The code to use the hypothetical Balances object might look like this: Public Function RetrieveBalance( _ ByVal custNumber As Short) As Decimal Dim b As NETMyCustomer.Balances = _
221 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Calling . . . .Unmanaged . . . . . . Code . . . New NETMyCustomer.Balances() RetrieveBalance = b.GetBalance(custNumber) End Function
After you create an RCW, the classes in the COM component can be used just like native .NET classes. When you use a class from the COM component, .NET makes the call to the RCW, which in turn forwards the call to the original COM component and returns the results to your .NET managed code. The Type Library Importer tool supports the command-line options listed in Table 9.1. Table 9.1 Command-line Options for the Type Library Importer Tool Option
Meaning
/asmversion:versionNumber
Specifies the version number for the created assembly
/delaysign
Prepares the assembly for delay signing
/help
Displays help for command-line options
/keycontainer:containerName
Signs the assembly with the strong name from the specified key container
/keyfile:filename
Specifies a file containing public/private key pairs that is used to sign the resulting file
/namespace:namespace
Specifies the namespace for the created assembly
/out:filename
Specifies the name of the created assembly
/primary
Produces a primary interop assembly
/publickey:filename
Specifies the file containing a public key that is used to sign the resulting file
/reference:filename
Specifies a file to be used to resolve references from the file being imported
/silent
Suppresses information that would otherwise be displayed on the command line during conversion
/strictref
Refuses to create the assembly if one or more references cannot be resolved
/sysarray
Imports COM SafeArray objects as instances of the System.Array type
/unsafe
Creates interfaces without the .NET Framework security checks
/verbose
Displays additional information on the command line during conversion
/?
Displays help about command-line options
222 Chapter 9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . If you want to use a COM DLL via an RCW from a serviced component or if you want to place the RCW in the Global Assembly Cache, you must assign a strong name to the RCW. You can do so by using the /keyfile option of the Type Library Importer tool (tlbimp.exe).
Using COM Components Directly The Visual Studio .NET interface provides a streamlined way to use a COM component from your .NET code. Instead of creating an RCW, you can add a reference directly to the COM DLL from within Visual Studio .NET. To do this, select the COM tab in the Add Reference dialog box. Scroll down the list of COM components until you come to the DLL that you wish to use. Click Select and then click OK. When you directly reference a COM library from the Visual Studio .NET Integrated Development Environment (IDE), the effect is almost the same as if you used the Type Library Importer tool to import the same library. Visual Studio .NET creates a new namespace with the name of the original library and then exposes the classes from the library within that namespace. Although you can use either of the two methods described in this chapter to call a COM component from a .NET component, here are some reasons to prefer one method over the other: ➤ For a COM component that will only be used in a single Visual Basic
.NET project and that you wrote yourself, use the easiest method: a direct reference from the .NET project. This method is suitable only for a truly private component that does not need to be shared by the other projects. ➤ If a COM component is shared among multiple projects, use the Type
Library Importer tool so that you can sign the resulting assembly and place it in the Global Assembly Cache (GAC). Shared code must be signed with a strong name. ➤ If you need to control details of the created assembly—such as its name,
namespace, or version number—you must use the Type Library Importer tool. The direct reference method gives you no control over the details of the created assembly. You should not use either of the import methods on code that is written by another developer. That’s because you are not allowed to sign code that is written by someone else. If you need to use a COM component from another developer, you should obtain a Primary Interop Assembly (PIA) from the original developer of the component. Microsoft supplies PIAs for all its own common libraries. For example, PIAs for almost all the components of Microsoft Office XP are available at http://www.microsoft.com/downloads/details.aspx?FamilyId=C41BD61E-30604F71-A6B4-01FEBA508E52&displaylang=en.
223 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Calling . . . .Unmanaged . . . . . . Code . . .
Using Platform Invoke So far in this chapter, you’ve seen interoperability between managed code and unmanaged code by way of method calls to classes in COM libraries. There’s a second way that the .NET Framework can interoperate with unmanaged code, though: through functional calls to unmanaged libraries. The Platform Invoke feature (often abbreviated as PInvoke) of .NET allows .NET code to call functions from unmanaged libraries such as the Windows API. To call unmanaged functions from your .NET code, you need to provide the declarations of the function in your .NET code. There are two ways to do this. First, you can use a Declare statement, just as you could in previous versions of Visual Basic: Declare Auto Function GetComputerName Lib “kernel32” ( _ ByVal lpBuffer As String, _ ByRef nSize As Integer) As Integer
The Declare statement specifies that a particular function is contained in the named library. You must declare the parameters and return type of the function to be compatible with those in the library. But Declare doesn’t offer you much control over the way that .NET handles an API call. For more detailed control, you’ll want to use the DllImport attribute instead. The DllImport attribute is a member of the System.Runtime.InteropServices namespace. The DllImport attribute tells the CLR where to find the implementation of the method by specifying the name of the unmanaged library. After the method is declared, you can use it in Visual Basic .NET just like you use any other method. Functions imported using DllImport must always be declared as Shared. In addition to the name of the library, the DllImport attribute also accepts other parameters (see Table 9.2). Table 9.2 Parameters for the DllImport Attribute Parameter
Description
CallingConvention
Defines the calling convention to use. The values are specified by the CallingConvention enumeration—Cdecl, FastCall, StdCall (default value), ThisCall and Winapi.
CharSet
Specifies the character set to use. By default it uses CharSet.Ansi. The other possible values are CharSet.Auto, CharSet.Unicode, and CharSet.None (which is obsolete and behaves as CharSet.Ansi). (continued)
224 Chapter 9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Table 9.2 Parameters for the DllImport Attribute (continued) Parameter
Description
EntryPoint
Represents the name of the entry point in the DLL. If the EntryPoint field is not specified, the name of the method is used as the entry point. If the EntryPoint field is passed, you can provide a custom name for the method.
ExactSpelling
Specifies whether the name of the entry point should exactly match the name of the function in the unmanaged DLL. By default the value is False.
PreserveSig
Indicates whether the method signature should be preserved or can be changed. By default the value is True.
SetLastError
Specifies whether the last error of the Win32 function should be preserved. By default the value is False.
For example, you could use the DllImport attribute to make the GetComputerName API available to your .NET applications this way: Imports System.Runtime.InteropServices _ Public Shared Function GetComputerName( _ ByVal lpBuffer As StringBuilder, _ ByRef nSize As Integer) As Integer
Having done this, you can call GetComputerName like any other function: Public Function ServerName() As String Dim sbBuf As StringBuilder = New StringBuilder(128) Dim intLen As Integer = sbBuf.Capacity Dim intRet As Integer = 0 ‘ Call the Win API method intRet = GetComputerName(sbBuf, intLen) ServerName = sbBuf.ToString() End Function
In Visual Basic .NET, you should use the StringBuilder object for a Windows API call that expects a string buffer to be modified by the function.
You’ll see that I used the CharSet.Auto parameter in the DllImport attribute of the GetComputerName method declaration. You may know that many Windows API calls come in two versions, depending on the character set you’re using. For example, GetComputerName really exists as GetComputerNameA (for ANSI characters) and GetComputerNameW (for
225 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Calling . . . .Unmanaged . . . . . . Code . . .
Unicode characters). The Auto modifier instructs the .NET Framework to use the appropriate version of the API call for the platform where the code is running. Platform Invoke can also handle API calls that require structures as parameters. For example, a call to the GetSystemTime API fills in a structure that consists of eight members that together indicate the system time. You can declare a structure by using the StructLayout attribute shown in the following example: _ Public Class SystemTime Public year As Short Public month As Short Public dayOfWeek As Short Public day As Short Public hour As Short Public minute As Short Public second As Short Public milliseconds As Short End Class _ Public Shared Sub GetSystemTime( _ ByVal time As SystemTime) End Sub
You would then call the GetSystemTime API this way: _ Public Function WebServerTime() As SystemTime Dim t As New SystemTime() ‘ call the Win32 API method GetSystemTime(t) WebServerTime = t End Function
In this case, the StructLayout attribute tells the Visual Basic .NET compiler that the location of the individual fields is sequential within the class. By using the StructLayout attribute, you can ensure that the .NET Framework constructs the same structure that the API function is expecting to receive. Many API calls require a Rect structure, which consists of four members that are filled in with the coordinates of a rectangle. In Visual Basic .NET, you can declare a structure with explicit byte offsets for each member, which lets you define any structure that the Windows API requires: _ Public Structure Rect Public left As Integer Public top As Integer Public right As Integer Public bottom As Integer End Structure
226 Chapter 9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
In this case, the StructLayout attribute tells the Visual Basic .NET compiler that you’ll explicitly specify the location of the individual fields within the structure. The FieldOffset attribute specifies the starting byte of each field within the structure.
227 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Calling . . . .Unmanaged . . . . . . Code . . .
Exam Prep Questions Question 1 You have written several applications for your own use, all of which share classes from a COM component that you also wrote. You are moving the applications to .NET, but you intend to leave the COM component untouched. How should you proceed? ❍ A. Use Platform Invoke to call functions from the existing COM component in each application. ❍ B. Set a direct reference from each application to the existing COM component. ❍ C. Use the Type Library Importer tool to create an unsigned RCW for the COM component. Place a copy of this RCW in each application’s directory. ❍ D. Use the Type Library Importer tool to create a signed RCW for the COM component. Place this RCW in the GAC.
Answer D is correct. The easiest way to handle this situation is to create one RCW and put it in a place where it can be shared. That place is the GAC. Answer A is incorrect because PInvoke isn’t used to call COM component functions. Answers B and C are incorrect because they both result in multiple copies of the RCW when a single copy will do.
Question 2 You are creating a Windows service in .NET that needs to use functions from a logging library that is supplied as a COM library by an independent software vendor (ISV). What should you do to use the classes and methods from this library in your service? ❍ A. Use the Type Library Importer tool to create a signed RCW for the library. Install the RCW in the GAC. ❍ B. Create wrapper code that uses Platform Invoke to call functions from the library. Import this wrapper code into your application. ❍ C. Obtain a PIA from the developer of the library. Install the PIA in the GAC. ❍ D. Use the Type Library Importer tool to create an unsigned RCW for the library. Install the RCW in the GAC.
Answer C is correct. Because you did not create the library, the proper course of action is to obtain a PIA from the original developer. Answers A and D are
228 Chapter 9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
incorrect because they result in you creating your own RCW. Answer B is incorrect because PInvoke is not used with COM libraries.
Question 3 You want to use an unmanaged DLL named Hardware.dll in your Visual Basic .NET application. Hardware.dll does not provide any COM interfaces. How can you call the GetResources function of this library in your .NET code? ❍ A. Use the Windows Forms ActiveX Control Importer tool. ❍ B. Use the DllImport attribute to declare the extern method GetResources from Hardware.dll. ❍ C. Use the Type Library Importer tool. ❍ D. Add a reference to the Hardware.dll library in your Visual Studio .NET project.
Answer B is correct. The DllImport attribute lets you declare external functions from unmanaged DLLs for use via PInvoke. Answers A and C are incorrect because these tools are used with COM components, not with unmanaged DLLs. Answer D is incorrect because you can only set a direct reference to a COM DLL, not to an unmanaged DLL.
Question 4 Your VB .NET application uses objects from a COM component named Statistics.dll. You have tested the application on your own computer and it works fine. You deploy the application to a test server by using XCOPY. On testing, you discover that none of the functionality supplied by Statistics.dll is working. What could be the problem? ❍ A. Statistics.dll is not stored in the Windows System directory. ❍ B. You have neglected to create an RCW for Statistics.dll. ❍ C. The COM component needs to be registered on the test server. ❍ D. Service Pack 1 for the .NET Framework is not installed on the test server.
Answer C is correct. COM components must be registered (using regsvr32.exe) on any computer where they will be used, even if you’re using them from a .NET application. Answer A is incorrect because COM components can be located anywhere on the computer. Answer B is incorrect because without an RCW you would not have been able to use the application on your computer. Answer D is incorrect because there are no interoperability fixes in SP1.
229 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Calling . . . .Unmanaged . . . . . . Code . . .
Question 5 You are planning to use two classes from a COM component in your .NET application. You’d like to place these two classes into a namespace named ImportedCOM. What must you do? ❍ A. Set a direct reference to the COM component. Create an empty class file in your .NET project. Specify the ImportedCOM namespace in that file and import the wrapper class. ❍ B. Use the Type Library Importer tool with the /namespace option to set the namespace within the RCW. ❍ C. Use the Type Library Importer tool with the /out option to create a file with the desired name. ❍ D. Use Platform Invoke within a Namespace declaration to import the classes.
Answer B is correct. The /namespace option of the Type Library Importer tool lets you specify the target namespace for the imported components. Answer A is incorrect because the specified procedure will wrap the component in an extra namespace. Answer C is incorrect because setting the filename will not set the namespace. Answer D is incorrect because PInvoke is not used with COM components.
Question 6 Your company supplies a COM component to provide Internet mail services for your clients. Some of your clients are moving their own applications to the .NET Framework and require an RCW for your component. How should you proceed? ❍ A. Use the Type Library Importer tool to create and sign a PIA for your component. ❍ B. Set a reference to your component from any Visual Basic .NET project to create an RCW for your component. ❍ C. Use the ActiveX Library Importer tool to create and sign a PIA for your component. ❍ D. Create a class that uses Platform Invoke to call functions from your component.
Answer A is correct. Because you developed the component, you should create a PIA for its RCW. The Type Library Importer tool is the tool that creates PIAs. Answer B is incorrect because setting a reference won’t produce a signed RCW. Answer C is incorrect because the ActiveX Library Importer is for ActiveX controls, not COM components. Answer D is incorrect because Platform Invoke is for API calls, not for COM objects.
230 Chapter 9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 7 Your application will use classes and methods from a COM component that communicates directly with Windows through the use of the Windows API. Which methods can you use to access the classes in the COM component? [Select two.] ❑ A. Set a direct reference to the COM component in your Visual Studio .NET project. ❑ B. Add the COM component directly to the Visual Basic .NET toolbox. ❑ C. Use Platform Invoke to declare the API functions within the COM component. ❑ D. Use the Type Library Importer tool to create an RCW for the COM component.
Answers A and D are correct. You can access a COM component from .NET code by direct reference (which creates an RCW implicitly) or by creating an RCW explicitly. Answer B is incorrect because you cannot add COM components to the Visual Studio .NET toolbox. Answer C is incorrect because Platform Invoke cannot be used to call classes from a COM component.
Question 8 You are responsible for migrating an existing COM application to Visual Basic .NET. The existing application consists of six COM server components and a single client user interface component that instantiates and invokes objects from the server components. You want to give the user interface of the application an overhaul and migrate to Visual Basic .NET with low risk and minimal downtime. How should you proceed? ❍ A. Bring only the user interface code into Visual Basic .NET. Use COM interoperability to call the existing COM servers from the .NET user interface code. Migrate the servers one by one. ❍ B. Bring all the servers into Visual Basic .NET. Use COM interoperability to call the migrated servers from the existing user interface code. ❍ C. Completely rewrite the entire application, using Visual Basic .NET. ❍ D. Cut and paste all the existing code into Visual Basic .NET.
Answer A is correct. To minimize the risk, you should migrate the components one at a time, using COM interoperability to communicate with the old components. Migrating the user interface first allows you to upgrade the user interface without affecting the server components. Answer B is incorrect because it requires migrating most of the components at once, and answer C
231 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Calling . . . .Unmanaged . . . . . . Code . . .
is incorrect because it requires migrating all the components at once. Answer D is incorrect because pasting old code into VB .NET will not give you a compilable application.
Question 9 You have developed a COM component that contains classes that are useful in your company’s business processes. You want to use the functionality from these classes in your .NET applications. How can you use these classes while maintaining the benefits of managed code, such as type safety and automatic garbage collection? ❍ A. Call the methods from the COM component directly via Platform Invoke. ❍ B. Use the Type Library Importer tool to create an RCW for the COM component. ❍ C. Add a direct reference to the COM component. ❍ D. Rewrite the COM component as a .NET component.
Answer D is correct. The only way to get the benefits of managed code is to actually migrate the component to managed code. Answer A is incorrect because Platform Invoke cannot be used to call methods from a COM component. Answers B and C are incorrect because they will make the COM functionality available as unmanaged code.
Question 10 Your application uses the GetComputerName API function. This function exists in kernel32.dll in both ANSI and Unicode versions. Your declaration is as follows: _ Public Shared Function GetComputerName( _ buffer As StringBuilder, size As Integer) _ As Integer
Your code is failing with a System.EntryPointNotFoundException exception when you call this function. What should you do to fix this failure? ❍ A. Add the CharSet.Auto parameter to the declaration. ❍ B. Supply the full path for kernel32.dll. ❍ C. Declare the function as GetComputerNameA instead of GetComputerName. ❍ D. Declare the function as GetComputerNameW instead of GetComputerName.
232 Chapter 9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Answer A is correct. The problem is that GetComputerName is actually an alias for either GetComputerNameA or GetComputerNameW, depending on the platform. Specifying the CharSet.Auto parameter lets the .NET CLR choose the correct version, depending on the platform. Answer B is incorrect because kernel.dll is always in the path. Answers C and D are incorrect because they will fail if the code is run on the wrong platform.
233 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Calling . . . .Unmanaged . . . . . . Code . . .
Need to Know More? Nathan, Adam. .NET and COM: The Complete Interoperability Guide. Sams, 2002. Troelsen, Andrew. COM and .NET Interoperability. Apress, 2002. .NET Framework SDK Documentation: “Interoperating with Unmanaged Code.”
10 Testing and Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terms you’ll need to understand: ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓
Debugging Testing Tracing Debug class Trace class TraceListener class TraceSwitch class TraceContext class
✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓
Call Stack window Me window Autos window Locals window Immediate window Watch window EventLog class PerformanceCounter class
Techniques you’ll need to master: ✓ Creating a unit test plan ✓ Configuring trace listeners and trace switches ✓ Displaying trace output ✓ Configuring an application for debugging
✓ Executing tests and debugging errors ✓ Controlling debugging with the Web.config file ✓ Logging test results
236 Chapter 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
You need to test and monitor distributed applications to ensure their quality and that they are functioning. In this chapter, you’ll discover techniques for testing and debugging different types of applications that make up an enterprise solution. You’ll learn how to test and debug a Windows application, Web application, Web service, serviced component, .NET Remoting object, and Windows service.
Testing A test plan is a document that guides the process of testing. A good test plan typically includes the following information: ➤ Which software component needs to be tested? ➤ What parts of a component’s specification are to be tested? ➤ What parts of a component’s specification are not to be tested? ➤ What approach needs to be followed for testing? ➤ Who will be responsible for each task in the testing process? ➤ What is the schedule for testing? ➤ What are the criteria for a test to fail or pass? ➤ How will the test results be documented and disseminated?
Three levels of testing are involved in most software projects: ➤ Unit testing—Involves testing the elementary unit of the application
(usually a class). ➤ Integration testing—Tests the integration of two or more units or the
integration between subsystems of those units. ➤ Regression testing—Usually involves the process of repeating the unit and
integration tests whenever a bug is fixed to ensure that no old bugs have recurred and that no new bugs have been introduced. You should also run your regression tests when you have modified or added code to make sure the new code does not have unintended consequences. Remember, testing can only show the presence of errors but can never confirm their absence.
237 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Testing . . . . and . . Debugging . . . . . .
Tracing The process of collecting information about program execution is called tracing. You can trace a program’s execution in Visual Basic .NET by generating messages about the program’s execution with the use of the Debug and Trace classes. The Trace and Debug classes have several things in common: ➤ They both belong to the System.Diagnostics namespace. ➤ They have members with the same names. ➤ All their members are static. ➤ They are conditionally compiled (that is, their statements are included
in the object code only if a certain symbol is defined). The only difference between the Debug and Trace classes is that the members of the Debug class are conditionally compiled, but only when the DEBUG symbol is defined. On the other hand, members of the Trace class are conditionally compiled, but only when the TRACE symbol is defined. Visual Basic .NET provides two basic configurations for a project: Debug and Release. Debug is the default configuration. When you compile a program by using the Debug configuration, both TRACE and DEBUG symbols are defined. When you compile a program in the Release configuration, only the TRACE symbol is defined. When you compile a program by using the Debug configuration, the code that uses the Debug and the Trace classes is included in the compiled code. When you run such a program, both the Debug and Trace classes generate messages. On the other hand, when a program is compiled by using the Release configuration, it does not include any calls to the Debug class. Therefore, when such a program is executed, you get only the messages generated by using the Trace class. Table 10.1 summarizes the members of both the Trace and Debug classes. Table 10.1 Members of Debug and Trace Classes Member
Type
Description
Assert
Method
Asserts that a particular logical condition evaluates to True at runtime. If not, it displays a message.
AutoFlush
Property
Automatically calls the Flush method after every write to the Listeners collection. (continued)
238 Chapter 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Table 10.1 Members of Debug and Trace Classes (continued) Member
Type
Description
Close
Method
Severs the connection with the Listeners collection after flushing any remaining output.
Fail
Method
Displays an error message.
Flush
Method
Writes all buffered data to the Listeners collection.
Indent
Method
Increments the IndentLevel property.
IndentLevel
Property
Specifies the indent level.
IndentSize
Property
Specifies the number of spaces in an indent.
Listeners
Property
The collection of Listener objects that will receive the trace output.
Unindent
Method
Decrements the IndentLevel property.
Write
Method
Writes the given information to the trace listeners in the Listeners collection.
WriteIf
Method
Writes the given information to the trace listeners in the Listeners collection only if a condition is True.
WriteLine
Method
Same as Write, but appends the information with a newline character.
WriteLineIf
Method
Same as WriteIf, but appends the information with a newline character.
Using Trace and Debug to Display Information One typical use of the Trace and Debug classes is to place assertions in your code. An assertion is a statement that you assume is true and that outputs a message if you’re wrong: Debug.Assert(intNumber >= 0, “Invalid value”, _ “negative value in debug mode”) ‘ Write a trace assertion Trace.Assert(intNumber >= 0, _ “Invalid value”, _ “negative value in trace mode”)
Trace Listeners Listeners are the classes responsible for forwarding, recording, and displaying the messages generated by the Trace and Debug classes. You can have multiple listeners associated with the Trace and Debug classes by adding Listener
239 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Testing . . . . and . . Debugging . . . . . .
objects to their Listeners property. The Listeners property is a collection capable of holding any number of objects derived from the TraceListener class. Both the Debug and the Trace classes share the Listeners collection, so an object added to the Listeners collection of the Debug class is automatically available in the Trace class, and vice versa. The TraceListener class is an abstract class that belongs to the System.Diagnostics namespace. It has three implementations: ➤ DefaultTraceListener—An object of this class is automatically added to the
Listeners collection. Its behavior is to write messages on the Output window. ➤ TextWriterTraceListener—An object of this class can write messages to
any class that derives from the Stream class, which includes the console or a file. ➤ EventLogTraceListener—An object of this class writes messages to the
Windows event log. Messages sent through the Debug and Trace objects are directed through each Listener object in the Listeners collection. Debug and Trace share the same Listeners collection, so any Listener object that is added to the Trace.Listeners collection is also added to the Debug.Listeners collection.
Trace Switches Trace switches allow you to set the parameters that can control the level of tracing that needs to be done in a program. These switches are set in an XML-based external configuration file. This is especially useful when the application is in production mode. You might not normally want your application to generate any trace messages. However, if the application has problems or you just want to check on the health of the application, you can instruct the application to emit a particular type of trace information by just changing the configuration file. There’s no need to recompile the application. The application will automatically pick up the changes from the configuration file the next time you run the application. The two predefined classes for creating trace switches are BooleanSwitch and TraceSwitch. Both classes derive from the abstract Switch class. You can also define your own trace switch class by deriving a class from the Switch class. The BooleanSwitch class is used to differentiate between two modes of tracing: trace-on and trace-off. Its default value is zero, which corresponds to the
240 Chapter 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
trace-off state. A class value set to any nonzero value corresponds to a traceon state. Unlike the BooleanSwitch class, the TraceSwitch class provides five different levels of tracing switches. These levels are defined by the TraceLevel enumeration, listed in Table 10.2. The default value of TraceLevel for a trace switch is 0 (Off). Table 10.2 The TraceLevel Enumeration Enumerated Value
Integer Value
Type of Tracing
Off
0
None
Error
1
Only error messages
Warning
2
Warning messages and error messages
Info
3
Informational messages, warning messages, and error messages
Verbose
4
Verbose messages, informational messages, warning messages, and error messages
Table 10.3 displays the important properties of the TraceSwitch class. Table 10.3 Important Properties of the TraceSwitch Class Property
Description
Description
Describes the switch (inherited from Switch).
DisplayName
Identifies the switch (inherited from Switch).
Level
Specifies the trace level that helps in selecting which trace and debug messages will be processed. Its value is one of the TraceLevel enumeration values (refer to Table 10.2).
TraceError
Returns True if Level is set to Error, Warning, Info, or Verbose; otherwise, it returns False.
TraceInfo
Returns True if Level is set to Info or Verbose; otherwise, it returns False.
TraceVerbose
Returns True if Level is set to Verbose; otherwise, it returns False.
TraceWarning
Returns True if Level is set to Warning, Info, or Verbose; otherwise, it returns False.
Here’s a quick demonstration of the use of trace switches: 1. Create a new Visual Basic .NET Windows application. 2. Add the following code to the default form in the project: Private Sub Form1_Load( _ ByVal sender As System.Object, _
241 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Testing . . . . and . . Debugging . . . . . . ByVal e As System.EventArgs) Handles MyBase.Load Dim ts As TraceSwitch = _ New TraceSwitch(“TestTrace”, _ “Trace the test application”) If ts.TraceVerbose Then ‘ Write a debug message Debug.WriteLine( _ “TraceVerbose is True”) End If If ts.TraceInfo Then ‘ Write a debug message Debug.WriteLine( _ “TraceInfo is True”) End If If ts.TraceWarning Then ‘ Write a debug message Debug.WriteLine( _ “TraceWarning is True”) End If If ts.TraceError Then ‘ Write a debug message Debug.WriteLine( _ “TraceError is True”) End If End Sub
3. Add an Application Configuration file named App.config to the current
project. In the XML editor, type the following configuration data in the XML file:
4. Run the project using the default Debug configuration. You should see
all the trace messages in the Output window. Stop the project and then experiment with different values for the trace switch to see their effect on the output.
Conditional Compilation Table 10.4 summarizes the preprocessing directives that are available in Visual Basic .NET.
242 Chapter 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Table 10.4 Visual Basic .NET Preprocessing Directives Directives
Description
#If, #Else, #ElseIf, and #End If
These directives conditionally skip sections of code. The skipped sections are not part of the compiled code.
#Const
This directive defines a preprocessor constant. This constant can be used only within a conditional compilation directive, not in regular code.
#ExternalSource and #End ExternalSource
These directives are used by the compiler to track line numbers for compiler error messages. You won’t use them in your own code.
#Region and #End Region
These directives mark sections of code. A common example of these directives is the code generated by the Windows Forms Designer. This marking can be used by visual designers such as Visual Studio .NET to show, hide, and format code.
In addition to the preprocessing directives, Visual Basic .NET also provides the ConditionalAttribute class. You can mark a method as conditional by applying the Conditional attribute to it. The Conditional attribute takes one argument that specifies a symbol. The conditional method is either included or omitted from the compiled code, depending on the definition of the specified symbol at that point. If the symbol definition is available, the call to that method is included; otherwise, the method call is excluded from the compiled code. For example, you can mark a method to be included only if the DEBUG symbol is defined this way: _ Public Sub InitializeDebugMode() ‘ Debug processing here End Sub
ASP.NET Tracing In addition to the Trace and Debug classes, ASP.NET supports one more method for tracing, which is specially designed for Web applications and Web services. This method of tracing is called ASP.NET tracing, and it is implemented by the TraceContext class. The TraceContext class is responsible for gathering the execution details of a Web request. You can access the TraceContext object for the current request through the Trace property of the Page object. Once you have the
243 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Testing . . . . and . . Debugging . . . . . .
TraceContext object, you can invoke its member methods to write trace messages to the trace log. Table 10.5 lists some of the important members of the TraceContext class. Table 10.5 Important Members of TraceContext Class Member
Type
Description
IsEnabled
Property
Specifies whether tracing is enabled for a request.
TraceMode
Property
Indicates the sort order in which the messages should be displayed. It can have one of three values—Default, SortByCategory and SortByTime.
Warn
Method
Writes messages to the trace log in red, to indicate them as warnings. It has three overloads—one with message, one with category and message, and the last one with category, message, and exception object.
Write
Method
Writes the messages to the trace log. It has the same three overloads as the Warn method.
By default, tracing is not enabled. Therefore, trace messages are not displayed. You can enable tracing for a page by using the Trace attribute of the Page directive. When the Trace attribute is set to True, the page appends the tracing information of the current Web request to its output. You can also enable tracing by setting the DOCUMENT object’s Trace property to True. This gives you both automatic tracing and the ability to insert your own messages in the trace output. Here’s how: 1. Create a new Visual Basic ASP.NET Web Application project. 2. Set the default Web Form to FlowLayout mode. Add a Button control
named btnTrace to the Web Form. 3. Switch to HTML view of the form in the designer. Add the Trace=”True”
attribute to the Page directive:
4. Switch back to design view of the form. Double-click the Button con-
trol and add the following code to the event handler to handle the Click event: Private Sub btnTrace_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnTrace.Click Trace.Write(“Sent by the Trace.Write method”) Trace.Warn(“Sent by the Trace.Warn method”) End Sub
244 Chapter 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5. Run the project. ASP.NET will display a wide range of information
after rendering the controls on the page. Click the Trace button. The page will be reloaded with the output from the Trace.Write and Trace.Warn statements, as shown in Figure 10.1.
Figure 10.1 Tracing information.
Here’s a summary of the information that tracing adds to the page: ➤ Request details—Includes the session identifier, the time the request was
made, the request character encoding, the type of HTTP request (GET or POST), the HTTP response status code, and the response character encoding. ➤ Trace information—Includes the messages and warnings generated by the
ASP.NET engine or by you by making calls to the Write or Warn methods of the TraceContext class. This information is displayed in four
245 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Testing . . . . and . . Debugging . . . . . .
columns—the category of the message, the trace message, the number of seconds since the first trace message was displayed, and the number of seconds since the most recent trace message was displayed. ➤ Control tree—Includes the entire collection of controls in the ASP.NET
page hierarchically. The information is displayed in four columns—the control identifier, the fully qualified type of the control, the size (in bytes) of the rendered control including its child controls, and the size (in bytes) of the view state of the control excluding its child controls. ➤ Session state—Includes the session state only if any data is stored in the
session. The Session State table displays the session key, the fully qualified type of the session data stored, and the value of the session data. ➤ Cookies collection—Includes the cookies associated with the application.
The information displayed includes the name of the cookie, the value of the cookie, and its size. ➤ Headers collection—Includes the HTTP headers passed to the Web page.
It displays the name of the header and its value. ➤ Form collection—Includes the form collection. It is displayed only if there
is a Web Form defined in the page and the form is posting back from the server. It displays the name of the control in the form and its value. ➤ Querystring collection—Includes the querystring collection only if any
querystring parameters are passed while requesting the page. It displays the name of the querystring parameter and its value. ➤ Server variables—Includes all the server variables associated with the
page. It displays the name of the server variable and its value. You can enable tracing for an entire Web application using the application configuration Web.config file in the application’s root directory. Enabling tracing through the Web.config file allows you to view the trace information using a trace viewer in a separate page instead of displaying it with the page output. The element is used to configure tracing for an application. The attributes of the element are provided in the following list: ➤ enabled—Indicates whether tracing is enabled for an application. If
enabled, trace information can be viewed using the trace viewer. ➤ localOnly—Indicates whether the trace viewer can be viewed by only the
local client (running on the Web server itself) or by any client.
246 Chapter 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ➤ pageOutput—Indicates whether the trace information should be dis-
played along with the page output. If set to False, trace.axd will record but not display the information. ➤ requestLimit—Indicates the number of requests whose trace information
should be stored on the server. Tracing gets disabled when the request limit is reached. ➤ traceMode—Indicates the order in which the trace messages should be
displayed in the Trace Information section. It can be either SortByCategory (sorted by the Category column) or SortByTime (sorted by the First[s] column). The page-level trace setting overrides the trace setting for the application. For example, if pageOutput is set to False in the Web.config file and if the trace attribute is enabled at the page level, the trace information is still displayed along with the page output.
Follow these steps to use the trace viewer and application tracing instead of page tracing: 1. Open the Web.config file from Solution Explorer. Modify the
element defined in the element as follows:
2. Remove the
Trace=”True”
attribute from the Page directive of the
default Web Form. 3. Run the project. Click the button. You will notice that there is no trace
information along with the page display. 4. Now navigate to trace.axd under your application directory, as shown
in Figure 10.2. This is not a real page but rather is intercepted by ASP.NET to show trace information. Click the View Details link to see the details of a particular request. 5. Set the enabled attribute of the trace element to False in the Web.
config file.
247 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Testing . . . . and . . Debugging . . . . . .
Figure 10.2 The Application Trace page viewed using the trace viewer.
Debugging Debugging is the process of finding the errors in a program, locating the lines of code that are causing those errors, and then fixing those errors. Visual Studio .NET comes loaded with a large set of tools and features to help you with various debugging tasks, including the following: ➤ Support for the cross-language debugging of Visual Basic .NET, Visual
C#, Visual C++ .NET, Managed Extensions for C++, script, and SQL ➤ Support for debugging both managed and unmanaged applications ➤ The ability to attach a debugger to a running program outside the
Visual Studio .NET environment on a local or remote machine ➤ Support for end-to-end debugging for distributed applications
Setting Breakpoints and Stepping Through Program Execution The Debug menu provides three options for step-by-step execution of a program, as listed in Table 10.6. The keyboard shortcuts listed in the table correspond to the Visual Basic settings of the Visual Studio IDE. If you have personalized the keyboard scheme either through the Tools, Options, Environment, Keyboard menu or through the VS .NET Start Page, you might have a different keyboard mapping. You can check out the keyboard mappings available for your customization through VS .NET’s contextsensitive help.
248 Chapter 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Table 10.6 Debug Options for Step-by-Step Execution Debug Menu Item
Keyboard Shortcut
Step Into
F8
Executes the code in step mode; if a method call is encountered, the program execution steps into the code of the function and executes the method in step mode.
Step Over
Shift+F8
Use this key combination when a method call is encountered and you do not want to step into the method code. When this key combination is pressed, the debugger will execute an entire method without any step-by-step execution (interruption) and then step to the next statement after the method call.
Step Out
Ctrl+Shift+F8
Use this key combination inside a method call to execute the rest of the method without stepping and then resume step execution mode when the control reaches back to the calling method.
Purpose
Breakpoints are markers in the code that signal the debugger to pause execution as soon as it encounters one. Once the debugger pauses at a breakpoint, you can take your time to analyze variables, data records, and other settings in the environment to determine the state of the program. You can choose to execute the program in step mode from this point on. For example, if you place a breakpoint in the Click event handler of a button, the program will be paused when you click the button and the execution reaches to the point where you have marked the breakpoint. You can now step through the execution for the rest of the event handler. After the handler code is over, control will be transferred back to the form under execution. This time, if you click another button and you don’t have a breakpoint set in its event handler, the program is no longer under step execution. Be sure to insert breakpoints wherever you want execution to pause for debugging.
Analyzing Program State to Resolve Errors When you break the execution of a program, the program is stuck at a particular state in its execution cycle. You can use various debugging tools to analyze the values of variables, the results of expressions, or the path of execution to help identify the cause of the error you are debugging.
249 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Testing . . . . and . . Debugging . . . . . .
Visual Basic .NET offers a variety of debugging windows you can use when a program is in break mode: ➤ The Call Stack window—Shows the method call stack, giving you infor-
mation about the path the code has taken to reach its current point of execution. The currently executing method is at the top of the stack, with an arrow pointing to it. When this method quits, the next entry in the stack will be the method receiving the control of execution. ➤ The Me window—Lets you examine the members associated with the
current object (such as the form that contains your code). You can change the values of these members here as well. ➤ The Autos window—Displays the variables used in the current statement
and the previous statement. The debugger determines this information for you automatically; that is why the name of this window is Autos. ➤ The Locals window—Displays the variables that are local to the current
context (that is, the current method under execution) with their current values. ➤ The Immediate window—Lets you issue commands or evaluate expres-
sions. ➤ The Watch window—Enables you to evaluate variables and expressions.
Select a variable from the code and drag and drop it in the Watch1 window to view the value of that variable on a continuous basis. In Visual Basic 6.0, you could edit the code of a running program, and the new code would be used immediately without a restart. This Break-Edit-Continue capability is not present in Visual Basic .NET.
Debugging When an Exception Occurs You can control the way the debugger behaves when it encounters a line of code that throws an exception. You can control this behavior through the Exceptions dialog box, shown in Figure 10.3, which is invoked via the Debug, Exceptions menu option. The Exceptions dialog box allows you to control the debugger’s behavior for each type of exception defined in the system. In fact, if you have defined your own exceptions, you can add them to this dialog box.
250 Chapter 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Figure 10.3 The Exceptions dialog box allows you to control the debugger’s behavior for system and custom-defined exceptions.
There are two levels at which you can control the behavior of the debugger when it encounters exceptions: ➤ When the exception is thrown—You can instruct the debugger to either
continue or break the execution of the program when an exception is thrown. The default setting for Common Language Runtime exceptions is to continue the execution, possibly in anticipation that there will be an exception handler. ➤ When the exception is not handled—If the program that you are debugging
fails to handle an exception, you can instruct the debugger to either ignore it and continue or to break the execution of the program. The default setting for Common Language Runtime exceptions is to break the execution, warning the programmer of a possible problematic situation.
Debugging a Running Process The Visual Studio .NET debugging environment also allows you to debug processes that are started outside the debugging environment. To access external processes from Visual Studio .NET, you need to invoke the Processes dialog box, which you can do in two ways:
251 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Testing . . . . and . . Debugging . . . . . . ➤ When you have a solution open in Visual Studio .NET, you can invoke
the Processes dialog box by selecting Debug, Processes. ➤ When no solution is open in Visual Studio .NET, the Debug menu is
not displayed. However, you can invoke the Processes dialog box by selecting Tools, Debug Processes. In the Processes dialog box, select the process that needs to be debugged in the Available Processes section and then click the Attach button to attach the process to the debugger. You can then open the source code files in Visual Studio .NET and place breakpoints in the code. The Visual Studio .NET debugger breaks the execution of the process when the breakpoint is reached. You can invoke various debugging windows, such as the Watch, Locals, and Autos windows, to analyze variables and step through the program execution. To debug a deployed or running Web application or a Web service, you need to attach the Visual Studio .NET debugger to the aspnet_wp.exe process running on the Web server. After this debugging setup is done, the Web programs can be debugged just like any other program. The ASP.NET worker process (aspnet_wp.exe) processes requests from all ASP.NET applications. If, after debugging, you choose to terminate the aspnet_wp.exe process, it will affect all Web applications running on the server. You need to be especially careful when selecting this option on a production/shared server. The server will restart the process as necessary, but session and application state information will be lost.
Debugging a Remote Process The process of debugging a remote process is almost the same as debugging an already running process. The only difference is that, prior to selecting a running process from the Processes dialog box, you must select the remote machine name from the Name drop-down list box in the Processes dialog box. Before you can debug a process remotely, you need to perform a one-time configuration on the remote machine (where the processes are running). You can do this in two ways: ➤ Install Visual Studio .NET on the remote machine. ➤ Install the Remote Components Setup on the remote machine (you can
start this from the Visual Studio .NET Setup Disc 1). In addition to this, you must ensure that your user account is a member of the Debugger Users group on the remote machine. If you want to debug the
252 Chapter 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ASP.NET worker process, you must also have administrative privileges (that is, you should be a member of the Administrators group) on the remote machine. The local computer and the remote computer must be members of a trusted domain in order for remote debugging to be possible. If SQL Server is installed on the remote machine, the setup process just described also configures the machine for SQL Server stored procedures debugging.
Debugging the Code in DLL Files The process of debugging a DLL file is similar to the process of debugging an EXE file. There is one difference though: The code in the DLL file cannot be directly invoked, so you need to have a calling program that calls the various methods/components of the DLL file. You typically need to take the following steps in order to debug code in a DLL file: 1. Launch the program (such as an EXE file, a Web page, a Web service,
and so on) that uses the components or methods in the DLL file. 2. Launch Visual Studio .NET and attach the debugger to the calling
program. Set a breakpoint in the calling program in which the method in the DLL file is called or else in the source code of the DLL file. Continue with the execution. 3. The execution breaks when the breakpoint is reached. At this point,
select Debug, Step Into to move to the source code of the DLL file. Execute the code in the step mode while you watch the value of its variables. In addition, if the code files are executing on a remote machine, you need to make sure the remote machine is set up with remote debugging support, as explained in the previous section.
Debugging Client-Side Scripts Visual Studio .NET also allows you to debug client-side scripts. The process is similar to the process I discussed earlier for ASP.NET Web Forms. However, you must note the following additional points for client-side scripting: ➤ Client-side debugging only works with Microsoft Internet Explorer.
253 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Testing . . . . and . . Debugging . . . . . . ➤ You have to enable script debugging in Internet Explorer. To do this,
select Tools, Internet Options. Then select the Advanced tab and uncheck the Disable Script Debugging option in the Browsing section. ➤ Attach the debugger to the IEXPLORE.EXE process displaying the
Web Form. This is only required if you are debugging an already running process. While attaching the process, in the Attach to Process dialog box, make sure you also select the Script option.
Debugging a Windows Service In most aspects, debugging a Windows service is like debugging any other application. However, a Windows service runs within the context of the Service Control Manager. Therefore, in order to debug a Windows service, you must attach a debugger to the process in which the Windows service is running. If the Windows service is not already started, you need to start the Windows service to perform debugging. When you attach a debugger to a Windows service, the service suspends its processing but continues to be in the Started state. This might affect the functionality of the Windows service. Therefore, you need to be especially careful when selecting this option on a production or shared server.
If a Windows service is executing on a remote machine, you need to make sure the remote machine is set up with remote debugging support, as explained in the section “Debugging a Remote Process.”
Debugging a Serviced Component A serviced component is stored in a DLL file. The code in the serviced component cannot be directly invoked, so you need to have a client (calling) program that creates the serviced component object and calls various methods of the serviced component. Therefore, to debug a serviced component, you need to take steps similar to those of debugging any DLL file. However, the debugging differs slightly depending on whether the serviced component application is a Library or Server application. If the serviced component is a Library application, the serviced component runs in the process of the client application. In this case, you can set breakpoints in the serviced component or the client application and run the client application in debug mode. When the breakpoint is reached, you can step
254 Chapter 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
into the code of the serviced component. In the case of an already running client application, you can set breakpoints in the serviced component or the client application and attach a debugger to the client application’s process. On the other hand, if the serviced component is a Server application, the serviced component runs in a separate process called dllhost.exe. Setting breakpoints in the client code and attaching a debugger to the client application will only debug the client application; it will not step into the code of the serviced component. In this case, to debug the serviced component, you should place breakpoints in the serviced component code and attach a debugger to the dllhost.exe process in which the desired serviced component is running. If multiple COM+ server applications are running on a machine, multiple dllhost.exe processes will be running on the machine. You can identify the unique process identifier (PID) of the dllhost.exe that is running your serviced component with the help of Component Services administrative tool. Drill down to the COM+ Applications node and select View, Status View. You can now view the PID for the dllhost.exe process that hosts the serviced component. You can use the PID of the dllhost.exe process to attach a debugger to that process using the Processes dialog box.
Debugging a .NET Remoting Object A .NET Remoting object is stored in a DLL file, just as a serviced component is. A .NET Remoting object executes in the process of the remoting server application irrespective of its activation mode. Therefore, to debug a remoting object, you need to take the following steps: 1. If the remoting server is running in its own process, attach the debug-
ger to that process. 2. If the remoting server is hosted in IIS, attach a debugger to the
ASP.NET worker process (aspnet_wp.exe). 3. Set breakpoints in the remoting object class definition.
After you take these steps, the Visual Studio .NET debugger breaks the execution when it reaches the breakpoint in the code. Attaching a debugger to the process in which a remoting client application is running will only debug the client application and will not step into the code of the remoting object class definition. In order to debug both client and server applications, you can attach a debugger to both the applications and step seamlessly into the code of both the applications.
255 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Testing . . . . and . . Debugging . . . . . .
If a remoting object is executing on a remote machine, you need to make sure the remote machine is set up with remote debugging support, as explained in the section “Debugging a Remote Process.”
Debugging an XML Web Service Debugging XML Web services is similar to debugging Web applications. They also run in the ASP.NET worker process (aspnet_wp.exe). You only need to set breakpoints in the Web methods of the Web service. After setting breakpoints, you can debug Web services using any of the following methods: ➤ You can run a Web service from Visual Studio .NET and then step into
the code of the Web service by invoking the methods through the Web service test page. ➤ You can also attach a debugger to the aspnet_wp.exe process to step into
the code of an already running Web service. ➤ You can create a client application for the Web service that invokes its
Web methods. You can then step into the code of the Web service by running the client application from Visual Studio .NET. ➤ You can attach a debugger to an already running client application and
then step into the code of the Web service when the code reaches the breakpoint. Also, if the Web service is executing on a remote machine, you need to make sure the remote machine is set up with remote debugging support, as explained in the section “Debugging a Remote Process.”
Working with Event Logs Event logging is the standard way in Windows for applications to leave records of their activities. You can easily monitor the behavior of an application by using the Event Viewer utility to analyze its messages in the event log. You can also view events from within the Visual Studio .NET environment. You can access event logs through the Server Explorer. The Framework Class Library provides a set of classes that are designed to work with event logs. With the help of these classes, you can programmatically read from or write to the event logs. Programmatic access might even allow you to automate some of the administrative tasks associated with an application.
256 Chapter 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
By default, three event logs are available: Application, Security, and System. Other applications or operating system components, such as Active Directory, might include other event logs. Table 10.7 lists the important members of the EventLog class. Table 10.7 Important Members of the EventLog Class Member
Type
Description
CreateEventSource
Method
Opens an event source so that an application can write event information
Delete
Method
Deletes an event log
DeleteEventSource
Method
Disconnects this object from the actual event log
EnableRaisingEvents
Property
Specifies whether the EventLog object receives notifications for the EntryWritten event
Entries
Property
Retrieves a collection of all entries in the event log
EntryWritten
Event
This event is raised whenever an event is written to the local computer, if the EnableRaisingEvents property is set to True
Exists
Method
Returns True if the requested event log exists
GetEventLogs
Method
Returns an array of all event logs on the computer
Log
Property
Specifies the name of the log to read from or write to
LogDisplayName
Property
Specifies an event log’s friendly name
LogNameFromSourceName Method
Retrieves the underlying event log name for the specified source name
MachineName
Property
Specifies the name of the computer on which to read or write events
Source
Property
Specifies the source to register and use when writing to an event log
SourceExists
Method
Finds whether a given event source exists
WriteEntry
Method
Creates a new entry in the event log
Each application that is interested in interacting with an event log must register an event source with the log. When an event source is registered, its information is stored in the system registry and is available across application restarts.
257 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Testing . . . . and . . Debugging . . . . . .
The CreateEventSource method allows you to register an application with an event log. If the event log does not already exist, this method will create it for you. The WriteEntry method of the EventLog object allows you to write messages to the event log specified by the event source. If you haven’t called CreateEventSource, WriteEntry will create the event source for you.
Working with Performance Counters Performance counters are Windows’ way of collecting performance data from running processes. Microsoft Windows itself provides several hundred performance counters—each of which monitors a particular system parameter. In addition, the various .NET server products, such as SQL Server and Exchange Server, and applications, such as the .NET Framework, also publish their own custom performance counters. The PerformanceCounter class allows you to read performance examples for processes that are running on a machine. By using this class, an application can even publish its own performance counter to inform the world about its performance level. Table 10.8 lists some important members of the PerformanceCounter class. Table 10.8 Important Members of the PerformanceCounter Class Member
Type
Description
CategoryName
Property
Specifies the performance counter category name.
Close
Method
Closes the performance counter and frees all the resources.
CounterHelp
Property
Describes the performance counter.
CounterName
Property
Specifies the name of the performance counter.
CounterType
Property
Specifies the type of the performance counter.
Decrement
Method
Decrements the value of the performance counter by one.
Increment
Method
Increments the value of the performance counter by one.
IncrementBy
Method
Increments or decrements the value of the performance counter by a specified amount.
InstanceName
Property
Specifies the instance name.
MachineName
Property
Specifies the computer name.
NextSample
Method
Gets a sample for the performance counter and returns the raw, or uncalculated, value for it. (continued)
258 Chapter 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Table 10.8 Important Members of the PerformanceCounter Class (continued) Member
Type
Description
NextValue
Method
Gets a sample for the performance counter and returns the calculated value for it.
RawValue
Property
Gets a sample for the performance counter and returns its raw, or uncalculated, value.
ReadOnly
Property
Indicates whether the performance counter is in read-only mode.
RemoveInstance Method
Deletes an instance from the PerformanceCounter object.
The .NET Framework allows applications to create their own custom performance counters and publish their performance data. This performance data can then be monitored via the Performance Monitoring tool (perfmon.exe). Visual Studio .NET makes it easy for you to create new performance categories and counters: It provides the Performance Counter Builder Wizard, which is available via Server Explorer. Open Server Explorer and from the Servers node select the server in which you want to create a performance counter. Right-click the Performance Counters node and select the Create New Category option. The Performance Counter Builder dialog box appears. Enter the values in the dialog box and then click OK to create the category and the counter.
259 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Testing . . . . and . . Debugging . . . . . .
Exam Prep Questions Question 1 You are debugging a .NET process that executes on a remote computer. Which of these setup procedures must you perform? [Select all correct answers.] ❑ A. Visual Studio .NET on the local computer ❑ B. Visual Studio .NET on the remote computer ❑ C. Remote Components setup on the local computer ❑ D. Remote Components setup on the remote computer
Answers A and D are correct. Remote debugging requires Remote Components on the machine where the code is running, and Visual Studio .NET on the computer where you want to run the debugger. Answer B is incorrect because Visual Studio .NET is not necessary on the computer with the remote component. Answer C is incorrect because the Remote Components are not required on the local computer.
Question 2 You have the following segment of code in your program: Dim tl As EventLogTraceListener = _ New EventLogTraceListener(“TraceLog”) Dim t2 As EventLogTraceListener = _ New EventLogTraceListener(“TraceLog”) Trace.Listeners.Add(tl) Debug.Listeners.Add(t2) Trace.WriteLine(“Sample Message”) Debug.WriteLine(“Sample Message”)
When you run the program through Visual Studio .NET in Debug mode, how many times would the message “Sample Message” be written to the trace log? ❍ A. One ❍ B. Two ❍ C. Three ❍ D. Four
Answer D is correct. The Debug and Trace objects share the same Listeners collection, so adding the object to each Listeners collection actually adds it to both collections. In debug mode, both Trace and Debug output is written.
260 Chapter 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
So the two messages are written twice each to the log. Answers A, B, and C are incorrect because they do not account for all the messages.
Question 3 You are debugging a complex Visual Basic .NET Windows Forms application and would like to monitor the variable values that are in use in the current line as you move through the application. Which window provides the easiest way to follow these variables? ❍ A. Autos ❍ B. Me ❍ C. Watch ❍ D. Locals
Answer A is correct. The Autos window automatically shows variables that are in use in the current statement and the immediately previous statement. Answer B is incorrect because the Me window is used to examine the members of the current object. Answer C is incorrect because the Watch window is used to monitor expressions. Answer D is incorrect because the Locals window shows all local variables.
Question 4 You are developing a Windows Forms application that makes heavy use of SQL Server stored procedures. After you execute one of these stored procedures, the output variable @Final contains an unexpected value. What should you do to trace how this value was calculated? ❍ A. Use the SQL Server PRINT command to display the value of @Final periodically during the stored procedure. ❍ B. Replace the stored procedure with a temporary Visual Basic .NET procedure containing identical logic. ❍ C. Use the Locals window to monitor @Final as you step through the stored procedure. ❍ D. Use Debug.Write statements to display the value of @Final periodically during the stored procedure.
Answer C is correct. Visual Studio .NET allows you to step through stored procedures and view the values of local variables interactively. Answer A is
261 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Testing . . . . and . . Debugging . . . . . .
incorrect because it requires modifying the stored procedure, which could have side effects. Answer B is incorrect because replacing the stored procedure may hide the error. Answer D is incorrect because you cannot put Debug.Write statements inside of a stored procedure.
Question 5 You are testing some code and you suspect that the value of a particular variable is zero when it ought not to be. Which method of the Trace object can you use to output a message if the value is zero? ❍ A. Flush ❍ B. Assert ❍ C. Fail ❍ D. Write
Answer B is correct. The Assert method will display a message if a specified condition is not true. Answer A is incorrect because the Flush method makes sure all output is flushed to the Listeners collection. Answers C and D are incorrect because Fail and Write both write their message unconditionally.
Question 6 Your application is in break mode and you wish to check the return value of the Peek method on a FileStream object. Which window should you use for this task? ❍ A. Watch ❍ B. Me ❍ C. Autos ❍ D. Immediate
Answer D is correct. The Immediate window allows you to execute statements interactively. Answer A is incorrect because the Watch window lets you evaluate an expression on a continuous basis while the program is executing. Answer B is incorrect because the Me window shows the members of the current object. Answer C is incorrect because the Autos window displays the variables used in the current and previous statements.
262 Chapter 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 7 In your Visual Basic .NET program, you have the following lines of code: Dim MyTraceSwitch As TraceSwitch = _ New TraceSwitch( _ “SwitchOne”, “The first switch”) MyTraceSwitch.Level = TraceLevel.Error
Which of the following expressions in your program would evaluate to True? ❍ A. MyTraceSwitch.TraceInfo ❍ B. MyTraceSwitch.TraceWarning ❍ C. MyTraceSwitch.TraceVerbose ❍ D. MyTraceSwitch.TraceError
Answer D is correct. The Level property of a TraceSwitch specifies the minimum error level that should be traced. Only levels at or above that level will return True. Answers A, B, and C are incorrect because Info, Warning, and Verbose messages are all less serious than Error messages.
Question 8 You are deploying an application at a client site and are concerned that it may use up an unacceptable amount of bandwidth. Which of these objects can you use to monitor the resource use of your application? ❍ A. Trace ❍ B. EventLog ❍ C. PerformanceCounter ❍ D. Debug
Answer C is correct. The PerformanceCounter object lets you monitor the value of Windows performance counters, including network resources. Answers A and D are incorrect because the Trace and Debug objects are used for runtime output of error information. Answer B is incorrect because EventLog is used as a place to store messages.
263 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Testing . . . . and . . Debugging . . . . . .
Need to Know More? Burton, Kevin. .NET Common Language Runtime Unleashed. Sams, 2002. Grimes, Richard. Developing Applications with Visual Studio .NET. Addison-Wesley, 2002.
11 Deployment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terms you’ll need to understand: ✓ Binding policy ✓ Delay signing ✓ Deployment ✓ Global Assembly Cache (GAC) ✓ Merge module ✓ Native compilation ✓ Native Image Cache ✓ Private assembly ✓ Publisher policy ✓ Shared assembly ✓ Side-by-side execution ✓ Strong name
Techniques you’ll need to master: ✓ Creating a setup program for a .NET application ✓ Registering components and assemblies ✓ Configuring side-by-side assemblies ✓ Understanding and controlling binding policy
266 Chapter 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A .NET application is normally made up of many units called assemblies. When you run a .NET application, the Common Language Runtime (CLR) needs to locate all the assemblies used by that application. The set of rules that the CLR uses to locate an assembly is called binding policy. You’ll need to understand binding policy to successfully deploy .NET applications. The .NET Framework greatly simplifies various deployment tasks. In fact, just copying the files to the target computer can easily deploy some simple applications. .NET also offers Windows Installer–based Setup projects for applications with complex deployment requirements.
Deploying Private Assemblies A private assembly is an assembly that is used by a single application. Private assemblies are the simplest type of assemblies to deploy. In order to deploy private assemblies, simply copy them to the application’s base directory or one of its subdirectories. An application does not contain the complete filename and the location of the assembly file to which it needs to refer. The CLR instead uses a process called probing to locate the privately deployed assemblies. You can have a certain degree of control over the probing process by modifying the binding policy using application configuration files.
Binding Policy for Privately Deployed Assemblies Binding policy for privately deployed assemblies is a set of rules that instructs the CLR to search for an assembly in specific locations. The CLR includes a default binding policy, but you can use the application configuration file to specify binding rules that instruct the CLR to search for particular assemblies in additional locations. For Windows applications, the application configuration file is application specific and is located in the base directory of the application. The name of application configuration file is of the format ExecutableFileName.config. For example, the application configuration file for MathApp.exe would be MathApp.exe.config. In the case of Web applications, the application configuration file is stored in the root directory of the application and is named Web.config. An application configuration file is an XML file that is used to configure an application. The element in which you’ll be most interested in this section is the element, which specifies additional search locations for an
267 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Deployment . . . . . .
assembly. A stripped-down version of an application configuration file containing the element is as follows:
You can use the privatePath attribute of the element to specify the subdirectories of the application’s base directory that might contain assemblies. Each of these subdirectories is delimited with a semicolon.
How the CLR Binds to a Privately Deployed Assembly The CLR takes the following steps to locate a privately deployed assembly: 1. The CLR determines the name of the assembly from the manifest of
the requesting assembly. 2. The CLR checks to see if the requested assembly has already been
loaded from the previous requests. If the assembly has already been loaded, the CLR binds to the assembly and stops searching any further. 3. The CLR reads the application configuration file to check if any pri-
vate path hints are available in the element. If there are hints, CLR will use these directory locations to search the assembly. 4. If the referenced assembly has no culture information, the CLR uses
the following locations, in the given order, to find the assembly: ➤ ApplicationBase\AssemblyName.dll ➤ ApplicationBase\AssemblyName\AssemblyName.dll ➤ ApplicationBase\PrivatePath1\AssemblyName.dll ➤ ApplicationBase\PrivatePath1\AssemblyName\AssemblyName.dll ➤ ApplicationBase\PrivatePath2\AssemblyName.dll ➤ ApplicationBase\PrivatePath2\AssemblyName\AssemblyName.dll
…
268 Chapter 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ➤ ApplicationBase\AssemblyName.exe ➤ ApplicationBase\AssemblyName\AssemblyName.exe ➤ ApplicationBase\PrivatePath1\AssemblyName.exe ➤ ApplicationBase\PrivatePath1\AssemblyName\AssemblyName.exe ➤ ApplicationBase\PrivatePath2\AssemblyName.exe ➤ ApplicationBase\PrivatePath2\AssemblyName\AssemblyName.exe
… Here, ApplicationBase is the directory in which the requesting application is installed. AssemblyName is the name of the assembly to search, and PrivatePath1 and PrivatePath2 are the hints provided in the element of the application configuration file. Note that the assembly name does not contain the extension; therefore, the CLR searches for both DLL as well as EXE files. If the assembly is found in any of these locations, the CLR binds to the assembly and stops searching any further. 5. If the referenced assembly has culture information, the following direc-
tories are searched: ➤ ApplicationBase\Culture\AssemblyName.dll ➤ ApplicationBase\Culture\AssemblyName\AssemblyName.dll ➤ ApplicationBase\PrivatePath1\Culture\AssemblyName.dll ➤ ApplicationBase\PrivatePath1\Culture\AssemblyName\
AssemblyName.dll ➤ ApplicationBase\PrivatePath2\Culture\AssemblyName.dll ➤ ApplicationBase\PrivatePath2\Culture\AssemblyName\
AssemblyName.dll … ➤ ApplicationBase\Culture\AssemblyName.exe ➤ ApplicationBase\Culture\AssemblyName\AssemblyName.exe ➤ ApplicationBase\PrivatePath1\Culture\AssemblyName.exe
269 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Deployment . . . . . . ➤ ApplicationBase\PrivatePath1\Culture\AssemblyName\
AssemblyName.exe ➤ ApplicationBase\PrivatePath2\Culture\AssemblyName.exe ➤ ApplicationBase\PrivatePath2\Culture\AssemblyName\
AssemblyName.exe … Here, Culture is a culture code corresponding to the assembly. If the assembly is found in any of these locations, the CLR binds to the assembly and stops searching any further. 6. If the CLR cannot locate the assembly using the preceding steps,
assembly binding fails. Any version information contained in the private assembly is for informational purposes only. The CLR does not use the version information of a private assembly to bind to a specific version.
If you’re having trouble with an assembly not being found at runtime, you can run the .NET Framework’s Assembly Binding Log Viewer tool, fuslogvw.exe, from a Visual Studio .NET Command Prompt to investigate the problem. This tool will give you a reason for the bind failure, information about the calling assembly, and information on the search paths and policies that were used in the failed attempt to bind.
Using the .NET Framework Configuration Tool to Specify Additional Probing Locations If you want to add additional locations to the list that the CLR uses, you can use the .NET Framework Configuration tool. You’ll find this tool in the Administrative Tools section of Windows Control Panel. You can add any application to be managed by this tool and then use the properties of the application to add to the search path, as shown in Figure 11.1. This tool, in fact, stores this information in the application configuration file. You can also include probing information manually by modifying the application configuration file using any editor.
270 Chapter 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Figure 11.1 You can specify additional probing locations for an assembly using the .NET Framework Configuration tool.
Deploying Shared Assemblies A shared assembly is shared among multiple applications on a machine. The .NET Framework requires all shared assemblies to have a strong name. A strong name uses four attributes to identify an assembly: ➤ Simple name ➤ Version number ➤ Culture identity (optional) ➤ Public key token
The .NET Framework provides special storage for shared assemblies in the form of the Global Assembly Cache (GAC). In addition to providing a shared location, the GAC also provides integrity checking and side-by-side versioning for shared assemblies.
Assigning a Strong Name to an Assembly A strong name is a cryptographic construct that provides protection against tampering. To create a strong name, you need a key pair, which consists of a public key and a private key. You can create a key pair with the .NET sn.exe tool, using the -k flag: sn -k KeyPairFile.snk
271 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Deployment . . . . . .
When you create a strongly named assembly, the public key is stored in the assembly manifest—along with other identification information, such as name, version number, and culture. To verify that only the legitimate owner of the public key has created the assembly, an assembly is signed using the publisher’s private key. The private key is assumed to be known only to the publisher of the assembly. The combination of a public key and a private key is known as a key pair. Key pairs have the property that data encrypted with the private key can only be decrypted using the public key. But knowing the public key doesn’t let you encrypt the data. It is also computationally infeasible to determine the private key if you know only the public key. The purpose of this public key cryptography is not to encrypt things so that they can’t be decrypted. Rather, it is to encrypt them so that their origin is known. If you keep your private key private (as you should!), then you can use it to produce messages that can only come from you. You must keep your private key private! Anyone who has your private key can forge your signature to an assembly, potentially one containing dangerous or malicious code.
The process of signing an assembly and verifying its signature works like this: ➤ Signing an assembly—When you sign an assembly, a cryptographic hash
of the assembly’s contents is computed. The hash is then encoded with the private key and is stored within the assembly. The public key is stored in the assembly manifest. ➤ Verifying the signature—When the CLR verifies an assembly’s identity, it
reads the public key from the assembly manifest and uses it to decrypt the cryptographic hash that is stored in the assembly. It then recalculates the hash for the current contents of the assembly. If the two hashes match, this ensures two things: The contents of the assembly were not tampered with after the assembly was signed, and only the party that has a private key associated with the public key stored in the assembly has signed the assembly. After you create a file containing a key pair, you can produce a strongly named assembly by using the AssemblyKeyFile attribute to reference that file (normally this is done in the AssemblyInfo.vb file):
272 Chapter 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Delay Signing an Assembly In most companies, the private key is stored securely, and only a few people have access to it. To help keep this key secure, the .NET Framework provides a delay signing technique for assemblies. When you use delay signing, you use only the public key to build an assembly. Associating public keys with an assembly allows you to place the assembly in the GAC and complete most of the development and testing tasks with the assembly. Later, when you are ready to package the assembly, an authorized person signs the assembly with the private key. Signing with the private key ensures that the CLR will provide tamper protection for the assembly. Delay signing involves these steps: 1. Extract the public key from a file that is storing the public/private key
pair by using the Strong Name tool, as follows: sn.exe -p KeyPairFile.snk PublicKey.snk
2. Add another attribute to the AssemblyInfo.vb file:
3. When you are ready to deploy the delay-signed assembly, sign it with
the company’s private key: sn.exe -R MyAssembly.dll KeyPairFile.snk
An assembly signed with a strong name does not automatically assert a company’s identity, such as its name. For that purpose, you can use an Authenticode signature— in which case, the company’s identity is asserted. An important thing to know is the order of commands when signing an assembly using both sn.exe and signcode.exe. You must sign your assembly with the Strong Name tool (sn.exe) before you sign it with the File Signing tool (signcode.exe). Remember, strong names protect the code in an assembly from tampering, whereas signing provides evidence of the assembly’s origin.
Adding an Assembly to the GAC After you have associated a strong name with an assembly, you can place the assembly in the GAC. There are several ways you can add an assembly to the GAC: ➤ Drag and drop the assembly to the GAC folder on your hard drive. This
will be C:\WINNT\assembly or C:\WINDOWS\Assembly, depending on your operating system. ➤ Use the Add an Assembly to the Assembly Cache link in the Microsoft
.NET Framework Configuration tool.
273 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Deployment . . . . . . ➤ Use the gacutil.exe tool: gacutil /i AssemblyName.dll
➤ Build and run a Setup project that uses the Windows Installer. This is
the preferred method for installing a shared assembly when you distribute an application.
Binding Policy for Shared Assemblies For shared assemblies, the binding policy specifies both where to search for the assembly and which version to bind to the application. When the CLR searches for a shared assembly, it goes through three stages of binding policy resolution: ➤ Application Policy Resolution—At this stage, the CLR will look for an
application configuration file for the binding rules. This configuration file can be used to specify additional search paths for an assembly. In addition, you can also use this file to redirect the CLR to a specific version of an assembly. The application-specific binding rules are usually set either by the application developer or by the administrator. ➤ Publisher Policy Resolution—Publisher policy is set by the publisher of a
shared assembly to distribute service pack–like updates to the customers. For example, the publisher could redirect all applications to use the new version, 1.1, of an assembly instead of the old version, 1.0. By default, the binding rules specified in the publisher policy override the application policy. If however, you want an application to override the updates and continue using the existing versions, you can bypass the publisher policy file by specifying the XML element in the application configuration file. ➤ Administrator Policy Resolution—The binding rules at this stage are speci-
fied by the administrator in the machinewide configuration file named machine.config. This file is stored in the config subdirectory under the .NET Framework installation directory on a machine. The settings specified in the machine configuration file override any settings specified in the application policy and the publisher policy.
274 Chapter 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
How the CLR Binds to a Shared Assembly The CLR uses the following steps to locate a shared assembly: 1. It determines the correct version of the assembly by examining the
application configuration file, publisher policy file, and machine configuration file in the order mentioned in the previous section. 2. It checks whether the assembly is already loaded. If the requested
assembly has been loaded in one of the previous calls, the CLR binds to the already loaded assembly and stops searching any further. 3. It checks the GAC. If the assembly is in the GAC, the CLR loads the
assembly from there, binds to it, and stops searching any further. 4. If a
element is specified in the configuration files, the CLR locates the assembly by using the paths specified in the element. If the CLR finds the assembly, the binding is successful; otherwise, the binding request fails and the CLR stops searching any further.
5. It follows the steps needed to probe for a private assembly, as explained
previously in the section “How the CLR Binds to a Privately Deployed Assembly,” to locate the assembly.
Packaging a .NET Application for Deployment Packaging an application means identifying all the individual files and settings for an application and putting them together so that the application can be easily distributed and deployed on the target computers. The choice of packaging depends on the nature of the application and its users. For installing simple applications, sometimes a tool as simple as the XCOPY command can be used. For sophisticated requirements, you might want to use a tool that creates a Windows Installer–based setup package for the application.
Packaging an Application for Deployment by Copying the Files Applications developed using Microsoft .NET Framework do not generally use the Windows Registry for storing application-specific data and configuration settings. Instead, all settings are stored in XML-based configuration files.
275 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Deployment . . . . . .
It is possible to deploy such an application by copying all the build output and content files to a folder of your choice on the target computer. You can simply use the XCOPY command or use FTP if you are deploying across the Internet. When you need to uninstall an application, all you need to do is to delete the folder that contains the application’s files. Because the deployment process is nonintrusive and causes minimal changes on the target computer, it is also sometimes called zero-impact installation. However, there are scenarios in which copying the files is not sufficient for deploying an application. Here are some common installation tasks that are difficult to do just by copying the files: ➤ Creating IIS virtual directories ➤ Registering services with the Service Control Manager ➤ Registering components with the COM+ catalog ➤ Creating shortcuts and Start menu entries ➤ Adding shared assemblies to the GAC ➤ Allowing the user to select features to install ➤ Using different relative paths on the target machine ➤ Creating or configuring databases ➤ Adding custom event logs and performance counters ➤ Presenting a user interface during the installation process ➤ Managing licensing and user registration
Packaging an Application for Deployment Using Microsoft Windows Installer The Microsoft Windows Installer is an installation and configuration service built in to the Windows operating system. It gives you complete control over installation of an application, a component, or an update. The Windows Installer includes many built-in actions for performing the installation process. Among the actions that the Installer can perform are the following: ➤ Install files ➤ Create shortcuts ➤ Create Registry keys
276 Chapter 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ➤ Run SQL scripts and other programs during installation ➤ Provide “on-demand” installation of features ➤ Manage repairs, updates, and uninstallations Windows Installer version 2.0 (the version used to install .NET applications) requires Windows XP, Windows .NET Server, Windows 2000, Windows NT 4.0 with Service Pack 6 or later, or Windows Me. Earlier Windows Installer versions require Windows NT 4.0 with Service Pack 3 or later, Windows XP, Windows 2000, or Windows Me. Windows Installer is also available as a redistributable for Windows NT 4.0, Windows 95, and Windows 98. It can be downloaded from http://www.microsoft.com/ msdownload/platformsdk/sdkupdate/psdkredist.htm.
When you create an installation program for the Windows Installer service, the end result is a Windows Installer (.msi) package. When this package is executed on the target machine, the Windows Installation service will install the program by reading the installation information stored in the Windows Installer package. You can create a Windows Installer package by using Setup and Deployment Visual Studio .NET projects, or by using installation tools from vendors such as ActiveInstall, InstallShield, and Wise Solutions. Microsoft Visual Studio .NET, through its Setup and Deployment projects, offers four types of deployment project templates: ➤ Setup Project—Used to create installation packages for deploying
Windows-based applications. ➤ Web Setup Project—Used to create installation packages for deploying
Web-based applications. ➤ Merge Module Project—Used to create installation packages for compo-
nents that may be shared by multiple applications. ➤ Cab Project—Used to package ActiveX components so that they can be
downloaded over the Internet. This type of project is largely obsolete.
Creating a Setup Project Visual Studio .NET provides the Setup Project template to create an installer for a Web application. It also provides a Setup Wizard that helps you in creating different types of setup and deployment projects using an interactive interface. Typically, you run this wizard to create a Setup project in the same solution that contains the Web application you wish to deploy. Here’s an outline of the steps involved:
277 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Deployment . . . . . . 1. In the Solution Explorer window, right-click the Solution and select
Add, New Project. Select Setup and Deployment Projects from the Project Types tree and then select Setup Wizard from the list of templates on the right. 2. Name the project and click OK. This will launch the Setup Wizard.
The first panel that will appear is the Welcome screen. Click Next. 3. The wizard will then show the Choose a Project Type panel. Choose
Create a Setup for a Web Application in the first group of options. Click Next. 4. The third panel of the wizard is the Choose Project Outputs to Include
panel. Generally, you should select Primary Output from ProjectName and Content Files from ProjectName. Click Next. 5. The wizard will then show the Choose Files to Include panel. Click the
Add button to include any additional files, such as Readme files, licensing agreements, or help files. Click Next. 6. The fifth and last panel will show a summary of your choices. Click
Finish to create the Setup project. When a Setup project is compiled, the output files are placed in the Release or Debug folder, depending on the active configuration. The contents of the folder are an installer package (.msi), executables (.exe), and initialization (.ini) files. The .msi file is the installation package in the Microsoft Windows Installer format. If the Windows Installer service is installed on your computer, you can directly start the installation by double-clicking this file. The executable files consist of Setup.exe, InstMsiA.exe, and InstMsiW.exe. Setup.exe (also called the Windows Installer bootstrapper) bootstraps the installation process by first testing for the presence of the Windows Installer service on the target machine. If the Windows Installer service is not installed, the bootstrapper will first install it using either InstMsiA.exe (for Windows 9x and Me) or InstMsiW.exe (for Windows NT/2000/XP/.NET) and then will instruct the Windows Installer service to execute the installation based on the information stored in the installation package (.msi file). The setup.ini file stores the initialization settings, such as the name of the installation database, for the bootstrap file setup.exe. There is one catch to using Visual Studio .NET setup projects. Setup projects created with Visual Studio .NET will only work on the computers where the .NET Framework runtime has already been installed. For a setup that can be installed from scratch, you should consider using a third-party tool.
278 Chapter 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
The output files generated can be deployed (copied) to any target machine and then installed and later uninstalled. When an application is uninstalled, all the actions performed by the installer application during the installation on the target machine are undone, leaving the target machine in its original state. You can also choose to repair or reinstall the application installed by clicking the Change button in the Add/Remove Programs dialog box.
Customizing Visual Studio .NET Setup and Deployment Projects Visual Studio .NET provides the following editors to customize various aspects of the installation process: ➤ File System Editor—The File System Editor provides a mapping of the
file system on the target machine. Each folder is referred to with a special name that is converted to represent the folder on the target machine during the installation process. For example, at the time of installation, the special folder User’s Desktop will be converted to the actual desktop path on the target machine. You can add files to various special folders—Application Folder, Common Files Folder, Program Files Folder, User’s Desktop, System Folder, User’s Startup Folder, and many others—each of which represents a particular folder on the target machine. ➤ Registry Editor—The Registry Editor allows you to specify Registry keys,
subkeys, and values that are added to the Registry on the target machine during the installation process. You can also import Registry files into the Registry Editor. ➤ File Types Editor—The File Types Editor enables you to associate file
extensions and actions with applications. For example, files with an extension (.qry, .txt, and so on) and action (Open, Print, Edit, and so on) can be associated with the application. Later, the application will get triggered whenever the associated actions are performed on the files with the associated extensions. ➤ User Interface Editor—The User Interface Editor allows you to customize
the user interface that is provided to the user during the installation process. The user interface is composed of the various dialog boxes that appear during the installation process. The user interface provided to the user is divided into three stages: Start, Progress, and End. You can add different types of dialog boxes for each stage, and each stage allows only certain types of dialog boxes to be added.
279 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Deployment . . . . . .
The User Interface Editor displays the user interface that is applicable during both end-user installation and administrative installation. You can customize the user interface for both installation types. The administrative installation occurs when you run the msiexec command-line tool with the /a option. This installation type is intended to place the setup files on a network drive from which they can be executed by other users. ➤ Custom Actions Editor—The Custom Actions Editor allows you to run
compiled DLLs, EXEs, scripts, assembly files, or assemblies at the end of an installation. These files can be used to perform custom, vital actions that were not carried out during installation. If the custom action fails, the entire installation process is rolled back. For example, you might have to install the database that is required by your application during the installation process. ➤ Launch Conditions Editor—The Launch Conditions Editor allows you to
set conditions that are to be evaluated when an installation begins on a target machine. If the conditions are not met, installation stops. For example, let’s say that you would like to install a Visual Basic .NET application only if the .NET Framework is installed on the target machine. This condition is added, by default, by Visual Studio .NET. You might also need to perform other checks, such as checking whether a particular file exists on the target machine or verifying a particular Registry key value on the target machine.
Deploying Server Applications Some applications have special deployment requirements. In particular, you should know how to deploy the major classes of server applications covered by the exam: Web services, Windows services, serviced components, and remoting objects.
Deploying a Web Service A Web service can be deployed on a Web server in a variety of ways. Here are some of the methods you can use: ➤ Manually copying the files—If you have access to the Web server and to
the development computer, you can simply copy the project’s files to the Web server. You also need to configure the target folder as a virtual directory, set access permissions for the virtual directory, and configure the virtual directory as an IIS application.
280 Chapter 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ➤ Using the Project, Copy Project command of Visual Studio .NET—Because
the Copy Project command can also set the destination directory as an IIS application, it saves an extra step required when manually copying the files using XCOPY or FTP. ➤ Using a Windows Installer package created using the Visual Studio .NET Web
Setup project—If you create a Web Setup project that includes the primary output from the Web service project, it will install the Web service on the target computer.
Deploying Windows Services Unlike a Web service, a Windows service application is installed in a directory on the file system of the target computer. Therefore, you use a Setup Project template instead of Web Setup Project template to deploy a Windows service. In addition, you also need to register a Windows service with the Windows Service Control Manager. The .NET Framework provides custom installation components to take care of this. These components need to be installed using a custom action in the Setup project. For more details on installing a Windows service, refer to Chapter 7, “Windows Services.”
Deploying a Serviced Component The two main steps to deploy a serviced component are as follows: 1. Register the serviced component with the COM+ catalog. There are
three ways you can do this: ➤ Lazy registration—The .NET Framework automatically registers a
serviced component with the COM+ catalog when the component is requested for the first time. The registration of a component requires local administration rights, and the component registration will fail if the first user of that application does not have these rights. This option can be used while developing or testing a component but is not a good idea for deployment. ➤ Manual registration—You can use the Component Services adminis-
trative tool (regsvcs.exe) to manually register a serviced component with the COM+ catalog. This technique of registration is useful in combination with XCOPY deployment of the serviced component. ➤ Programmatic registration—You can use the RegistrationHelper class
to programmatically register a serviced component with the COM+
281 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Deployment . . . . . .
catalog. This registration technique is what you will use when creating a Windows Installer–based setup package for the deployment of a serviced component. 2. Install the serviced component assembly at a location where the CLR
can locate it. Where the CLR locates an assembly also depends on the program that makes the request to the assembly. Therefore, the installation location might depend on how the component is registered with the COM+ catalog: ➤ If the component is registered as a library application, the serviced
component is created in the process of the calling application. In this case, the serviced component might be deployed as a private application within the calling application directory structure. But if the serviced component is used by multiple calling applications, instead of introducing redundancy by copying the serviced component in the directory of each calling application, a better idea is to install the serviced component in the GAC. ➤ If the component is registered as a server application, the serviced
component is created in the process of dllhost.exe, which is located in the Windows System directory. Obviously, the GAC is also a better installation choice in this case. From the preceding list, it is clear that, in most cases, you should install a serviced component assembly in the GAC. Also, you should either use the Component Services administrative tool for the registration of the serviced component in the COM+ catalog or use the RegistrationHelper class when programmatically registering a serviced component (for example, when registering through a setup program). You can install serviced components by using a Visual Studio .NET Setup project, or manually by using the Component Services administrative tool.
Deploying a .NET Remoting Object A .NET Remoting object is generally deployed with the server application that uses it. This server application can be created as a console application, a Windows application, a Windows service, or a Web application. Based on what you have studied so far, the process of deploying a .NET Remoting object is very similar. Components, such as serviced components and .NET Remoting objects, can be shared between multiple applications. You might want to distribute these
282 Chapter 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
components to be used by other developers as part of their applications. The process of packaging a component for reuse in other applications is different from packaging a Windows application for deployment. When you have a component that will be shared among multiple applications, you should package it as a merge module (.msm file). A merge module includes the actual component, such as a .dll file, along with any related setup logic, such as resources, Registry entries, custom actions, and launch conditions. Merge modules cannot be directly installed. They need to be merged with the installation program of an application that uses the shared component, packaged into a merge module. When you modify a component to release new versions, you create a new merge module for each of the new versions. A new merge module should be created for each successive version of a component in order to avoid version conflicts.
283 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Deployment . . . . . .
Exam Prep Questions Question 1 You are developing a set of components in Visual Basic .NET. You plan to install these components in the GAC on the user’s machine. You want to sign your components with a cryptographic digital signature to prevent tampering, as well as with an Authenticode signature so that the identity of your company is certified through an independent certifying authority. Which of the following options would you use for signing the components before they are packaged for deployment? ❍ A. Use sn.exe to sign the assemblies. ❍ B. Use signcode.exe to sign the assemblies. ❍ C. Use sn.exe followed by signcode.exe to sign the assemblies. ❍ D. Use signcode.exe followed by sn.exe to sign the assemblies.
Answer C is correct. You must use sn.exe to apply a strong name to the assemblies, and signcode.exe to add the Authenticode signature. You must always add the strong name before the Authenticode signature. Answers A and B are incorrect because they do not include both necessary tools. Answer D is incorrect because it uses the tools in the wrong order.
Question 2 You have developed a database-intensive Web service application. When the application is installed on the user’s computer, the required database must also be installed by running a series of SQL scripts. The execution of the program cannot continue without the database. Therefore, if setup of the database fails, you would like to roll back the installation process. Which of the following editors would you use in the Setup project to ensure that the database is properly installed on the target machine? ❍ A. File System Editor ❍ B. Custom Actions Editor ❍ c. Launch Conditions Editor ❍ D. Registry Editor
Answer B is correct. The Custom Actions Editor allows you to run custom code during a setup (for example, to run SQL scripts). Answer A is incorrect because the File System Editor creates files and folders but does not execute code. Answer C is incorrect because the Launch Conditions Editor is used to decide whether to proceed with setup at all. Answer D is incorrect because the Registry Editor is only used to specify Registry keys to create.
284 Chapter 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 3 Your application uses a private assembly named gc.dll that is installed in a subdirectory named utility. How can you ensure that the CLR can find this assembly when it loads your application? [Select two correct answers.] ❑ A. Apply a strong name to the private assembly. ❑ B. Add to the application’s configuration file. ❑ C. Make sure the main application and the assembly use the same culture. ❑ D. Use the .NET Framework Configuration tool to specify a probing path for the assembly.
Answers B and D are correct. The probing entry in the configuration file tells the CLR where to look for a private assembly. You can add this path by hand or by using the .NET Framework Configuration tool. Answer A is incorrect because a strong name doesn’t change the binding location for a private assembly. Answer C is incorrect because having the same culture won’t help if the assembly is not on the standard search path.
Question 4 You have installed an application that originally loaded version 1.0 of SomeAssembly.dll, which is a shared assembly. The application’s configuration file redirects the application to use version 1.1 instead of version 1.0, and it also contains the XML element. The publisher policy file for the assembly redirects requests from version 1.1 to version 2.0. The administrator policy file on the computer redirects requests from version 1.0 to version 2.4. Which version of the assembly will be loaded when you run the application? ❍ A. 1.0 ❍ B. 1.1 ❍ C. 2.0 ❍ D. 2.4
Answer D is correct. The administrator policy file overrides both the application configuration file and the publisher policy file. Answer A is incorrect because the administrator policy file overrides the original manifest. Answers B and C are incorrect because these bindings come from files that are overridden by the administrator policy file.
285 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Deployment . . . . . .
Question 5 You are preparing several applications for deployment. Which of these applications would be appropriate for deployment via XCOPY? ❍ A. An application that requires running SQL scripts to initialize a database ❍ B. An application that uses functions from a single shared assembly that must be installed to the GAC ❍ C. An application that uses functions from five private assemblies, each of which is in a subdirectory with its own name ❍ D. An application that requires a custom performance counter
Answer C is correct. As long as a private assembly is in a folder with the same name as the assembly, the CLR will find it during binding policy resolution. Answer A is incorrect because XCOPY cannot run SQL scripts. Answer B is incorrect because XCOPY cannot install assemblies to the GAC. Answer D is incorrect because creating a performance counter requires running a custom installation component.
Question 6 You are responsible for maintaining the installation of a .NET application on your corporate server. The application uses a serviced component, Statistics.dll, which is signed with a strong name. You have version 1.0 of this serviced component, which you have installed in the root directory of the application. You later receive version 2.0 of Statistics.dll, which you install in the Global Assembly Cache as well as the root directory of the application. You reconfigure the application configuration file of the Windows service to redirect version 1.0 calls to version 2.0. Now you receive version 3.0 of Statistics.dll, which you again install in the Global Assembly Cache. You do not reconfigure the application configuration file. Now when you run the Windows service, which version of Statistics.dll is loaded and from which location? ❍ A. Version 1.0 from the root directory of the application ❍ B. Version 2.0 from the Global Assembly Cache ❍ C. Version 2.0 from the root directory of the application ❍ D. Version 3.0 from the Global Assembly Cache
Answer B is correct. The application configuration file calls for version 2.0, and the GAC copy will be loaded in preference to the local copy. Answer A is incorrect because the application configuration file redirects the call from version 1.0 to version 2.0. Answer C is incorrect because the copy in the root directory will not be loaded if there is also a copy in the GAC. Answer D is incorrect because you haven’t reconfigured the application to use version 3.0.
286 Chapter 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 7 You have created a serviced component for commercial sale. Some customers will buy the component hosted in a Windows service, whereas others will host it in IIS. How should you package the Windows service for deployment? ❍ A. Place all the files for the component in a Zip file and then instruct purchasers to unzip the file to an appropriate spot. ❍ B. Build a merge module Setup project for the component and include this merge module in separate Setup projects for the Windows service and IIS versions. ❍ C. Build separate Setup projects for the Windows service and IIS versions, with no files shared between the two. ❍ D. Supply the source code for the component and instruct purchasers to recompile it on the target computer.
Answer B is correct. When a component is shared between two or more Setup projects, you should build a merge module to make sure it is treated properly by the Windows Installer service. Answer A is incorrect because simple file-copy deployment won’t properly register a serviced component. Answer C is incorrect because including the same component in two separate Setup projects without using a merge module violates the Windows Installer guidelines. Answer D is incorrect because it causes extra work for customers as compared to shipping a professional setup program.
Question 8 You have created a serviced component that will be run as a server application. You are now ready to deploy this component to end-user computers across your company. How should you proceed? ❍ A. Deploy the serviced component to a directory under Program Files/CompanyName and use lazy registration. ❍ B. Deploy the serviced component to a directory under Program Files/CompanyName and use programmatic registration. ❍ C. Deploy the serviced component to the GAC and use lazy registration. ❍ D. Deploy the serviced component to the GAC and use programmatic registration.
287 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Deployment . . . . . .
Answer D is correct. Server applications are hosted by dllhost, so the component must be placed in either the Windows system directory or the GAC so that the CLR can find it. Lazy registration is not a good choice for deployment because it requires administrative privileges. So your best choice is to place the component in the GAC and use programmatic registration. Answers A and B are incorrect because they install the component to the wrong location. Answer C is incorrect because it uses lazy registration.
Question 9 You work as a software developer in a large manufacturing company. You create a Web service that provides inventory information to the company’s partners and customers. The Web service has been thoroughly tested using a test server. You now want to deploy the Web service on the company’s production server. You do not want to manually configure any settings on the production machine. Which of the following methods of deployment should you choose? ❍ A. Ftp the files from the test server to the production server. ❍ B. Create a Web Setup project for your application and use the setup program to deploy the application on the production machine. ❍ C. Use the XCOPY command to copy all your files to the production server. ❍ D. Use the Visual Studio .NET Copy Project command to copy all the project files to the production server.
Answer B is correct. Only the Web Setup project will automatically set up the virtual directory and other IIS settings required for the Web service to function properly. Answers A, C, and D are incorrect because these options will get the files to the server but will require manual setup to make the Web service actually work.
288 Chapter 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Need to Know More? Gunderloy, Mike. MCAD 70-310 Training Guide. Que, 2003. Richter, Jeffrey. Applied Microsoft .NET Framework Programming. Microsoft Press, 2002. Deploying .NET Applications: Lifecycle Guide. downloads/release.asp?releaseid=40545.
www.microsoft.com/
12 Security Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terms you’ll need to understand: ✓ Authentication ✓ Authorization ✓ Code access security ✓ Code group ✓ Configured assembly ✓ Declarative security ✓ Imperative security ✓ Impersonation ✓ Permission ✓ Permission set ✓ Role-based security
Techniques you’ll need to master: ✓ Implementing code access security ✓ Configuring authentication for .NET applications ✓ Configuring authorization for .NET applications ✓ Implementing identity management
290 Chapter 12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
The .NET Framework includes a comprehensive set of security tools, including both low-level classes for managing security and an overall framework for applying these tools to particular applications. The tools for managing security include code access security and role-based security. Code access security allows you to control what code can execute on a particular computer, as well as what that code can do. Role-based security, which encompasses authentication, authorization, and identity management, allows you to control the actions that particular users can take.
Configuring Security Broadly speaking, .NET security breaks down into two separate areas: ➤ Code access security—Manages the security of the .NET source code itself.
You can tell the .NET Framework the resources your code needs to execute properly, and the .NET Framework will check for permission to access those resources on the machine at runtime. ➤ Role-based security—Manages the user rather than the code. Using role-
based security allows you to provide (or deny) access to resources based on an identity provided by the user running the code.
Understanding Code Access Security Code access security is based on specific permissions that the Common Language Runtime (CLR) can grant to or deny from code. Code can make four different types of permission requests: ➤ It can request the minimum permissions that it requires to run. ➤ It can request optional permissions that it would like but does not
require. ➤ It can refuse permissions to ensure that it does not have access to partic-
ular resources. ➤ It can demand permissions on the part of calling code.
The CLR decides whether a particular permission will be granted. If a piece of code is unable to obtain the minimum permissions it requires, that piece of code won’t execute. The security settings of the computer determine the maximum permissions that code can be granted, but code is allowed to request (and receive) fewer permissions than the maximum.
291 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Security . . . . .Issues . . .
The .NET Framework groups permissions into three types: ➤ Code access permissions—Represent access to a protected resource or the
authorization to perform a protected operation ➤ Identity permissions—Represent access based on credentials that are a part
of the code itself ➤ Role-based permissions—Represent access based on the user who is run-
ning the code Each permission in the .NET Framework is represented by a particular class that derives from System.Security.CodeAccessPermission. Table 12.1 lists the available code access permissions, which are the most important for controlling the actions that code can take on a particular computer. You can also create your own custom permission classes if necessary. Table 12.1 Code Access Permissions in the .NET Framework Permission
Explanation
DirectoryServicesPermission
Controls access to the System.DirectoryServices namespace
DnsPermission
Controls access to Domain Name System (DNS) services
EnvironmentPermission
Controls access to environment variables
EventLogPermission
Controls access to the Windows event log
FileDialogPermission
Controls access to files selected from the Open dialog box
FileIoPermission
Controls access to reading and writing files and directories
IsolatedStorageFilePermission
Controls access to private virtual file systems
IsolatedStoragePermission
Controls access to isolated storage
MessageQueuePermission
Controls access to message queuing via Microsoft Message Queues
OleDbPermission
Controls access to data via the System.Data.OleDb namespace
PerformanceCounterPermission Controls access to performance counters PrintingPermission
Controls access to printers
ReflectionPermission
Controls access to the reflection features of .NET
RegistryPermission
Controls access to the Windows Registry
SecurityPermission
Controls access to unmanaged code (continued)
292 Chapter 12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Table 12.1 Code Access Permissions in the .NET Framework (continued) Permission
Explanation
ServiceControllerPermission
Controls access to starting and stopping services
SocketPermission
Controls access to Windows sockets
SqlClientPermission
Controls access to data via the System.Data.SqlClient namespace
UiPermission
Controls access to the user interface
WebPermission
Controls access to making Web connections
Requesting Minimum Permissions Permissions can be requested by applying attributes. For example, to request unrestricted file dialog permissions as the minimum level of permission necessary for an assembly to run, you’d add this code to the assembly: Imports System.Security.Permissions
If this code runs, it means that the assembly in which it is contained can perform any file dialog operation. For the most part, you’ll find that code that requests permissions runs without any problem, which means that it was granted the requested permission. That’s because, by default, you have full permissions to run any code that originates on your own computer.
Code Groups and Permission Sets A code group is a set of assemblies that share a security context. You define a code group by specifying the membership condition for the group. Every assembly in a code group receives the same permissions from that group; however, because assemblies can be members of multiple code groups, two assemblies in the same group might end up with different permissions in the end. The .NET Framework supports seven different membership conditions for code groups: ➤ The application directory membership condition—Selects all code in the
installation directory of the running application. ➤ The cryptographic hash membership condition—Selects all code matching a
specified cryptographic hash. Practically speaking, this is a way to define a code group that consists of a single assembly.
293 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Security . . . . .Issues . . . ➤ The software publisher membership condition—Selects all code from a speci-
fied publisher, as verified by Authenticode signing. ➤ The site membership condition—Selects all code from a particular Internet
domain. ➤ The strong name membership condition—Selects all code with a specified
strong name. ➤ The URL membership condition—Selects all code from a specified URL. ➤ The zone membership condition—Selects all code from a specified security
zone (Internet, Local Intranet, Trusted Sites, My Computer, or Untrusted Sites). Permissions are granted in permission sets. A permission set is composed of one or more code access permissions that are granted as a unit. The .NET Framework supplies seven built-in permission sets: ➤ The Nothing permission set—Grants no permissions. ➤ The Execution permission set—Grants permission to run but not to access
protected resources. ➤ The Internet permission set—Grants limited permissions designed for code
of unknown origin. ➤ The LocalIntranet permission set—Grants high permissions designed for
code within an enterprise. ➤ The Everything permission set—Grants all permissions except for the per-
mission to skip verification. ➤ The SkipVerification permission set—Grants the permission to skip security
checks. ➤ The FullTrust permission set—Grants full access to all resources. This per-
mission set includes all permissions. You can also create your own custom permission sets.
Granting Permissions The easiest way to grant or deny permissions in the .NET Framework is to use the Microsoft .NET Framework Configuration tool. Follow these steps to see the main features of this tool:
294 Chapter 12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1. Select Start, Programs, Administrative Tools, Microsoft .NET
Framework Configuration. 2. Expand the Runtime Security Policy node, the User node, and then
the Permission Sets node to see the built-in .NET permission sets. 3. Right-click the Everything permission set and select Duplicate to
create a new permission set named Copy of Everything. 4. Right-click the Copy of Everything permission set and select Rename.
Rename the permission set No FileDialog. 5. With the No FileDialog permission set selected, click the Change
Permissions link in the right panel of the Configuration tool. In the Create Permission Set dialog box, select File Dialog and click Remove. Click Finish to save your changes. 6. Expand the Code Groups node and click the default All_Code code
group. Click the Add a Child Code Group link in the right panel of the Configuration tool. 7. In the Create Code Group dialog box, name the new group
TestGroup. Enter a description and click Next. 8. Select the Hash condition. Click the Import button and browse to any
.NET executable file that you’ve created. Click Open to calculate the hash for this file. Click Next. 9. Select the No FileDialog permission set and click Next. Click Finish to
create the new code group. 10. Right-click the TestGroup code group and select Properties. Check
the box to make this code group exclusive. Click OK. 11. Run the application you selected by double-clicking it in Windows
Explorer. If the code tries to use a file dialog, you’ll receive a policy exception error box indicating that the code cannot be run. Click No to dismiss the error. 12. Stop the application and delete the TestGroup code group to return
your application’s security to its original state. The .NET Framework SDK also includes a tool, caspol.exe, that can manipulate code groups and permission sets from the command line. If you’re trying to automate security operations, you can make good use of this tool from a batch file.
295 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Security . . . . .Issues . . .
Imperative Security Requesting permissions through the use of attributes is known as declarative security. A second method to request permissions is known as imperative security. With imperative security, you create objects to represent the permissions that your code requires. You could use imperative security in an event procedure this way: Private Sub btnGetName_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnGetName.Click Try Dim fdp As FileDialogPermission = _ New FileDialogPermission( _ PermissionState.Unrestricted) ‘ Check to see whether the code ‘ has the specified permission fdp.Demand() If dlgOpen.ShowDialog = _ DialogResult.OK Then txtFileName.Text = dlgOpen.FileName End If Catch ex As Exception MessageBox.Show(“Exception: “ & _ ex.Message) End Try End Sub
The only time you absolutely must use imperative security is when you must make security decisions based on factors only known at runtime, such as the name of a particular file. In most other cases, you’ll find that declarative security is easier to use.
Computing Permissions Determining the actual permissions applied to any given piece of code is a complex process. To begin the process, think about permissions at the Enterprise level only. The CLR starts by examining the evidence a particular piece of code presents to determine its membership in code groups at that level. Evidence is just an overall term for the various identity permissions (publisher, strong name, hash, and so on) that can go into code group membership. Code groups are organized into a hierarchy. In general, the Common Language Runtime will examine all the code groups in the hierarchy to determine membership. However, any code group in the hierarchy can be marked as Exclusive. The Common Language Runtime stops checking for group membership if code is found to be a member of an Exclusive code
296 Chapter 12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
group. Also, if code is not a member of a code group, membership won’t be checked for children of that group. In any case, code will be determined to be a member of zero or more code groups as a first step. Next, the CLR retrieves the permission set for each code group that contains the code. If the code is a member of an Exclusive code group, only the permission set of that code group is taken into account. If the code is a member of more than one code group and none of them are Exclusive code groups, all the permission sets of those code groups are taken into account. The permission set for the code is the union of the permission sets of all relevant code groups. That is, if code is a member of two code groups, and one code group grants FileDialog permission, but the other does not, the code will have FileDialog permission from this step. This is a “least-restrictive” combination of permissions. So far, this process has accounted for the permissions at one level (the Enterprise level). But there are actually four levels of permissions: Enterprise, Machine, User, and Application Domain. Only the first three levels can be managed within the .NET Framework Configuration tool, but if you need specific security checking within an application domain (roughly speaking, an application domain is a session in which code runs), you can do this in code. An application domain can reduce the permissions granted to code within that application domain, but it cannot expand them. The CLR determines which of the four levels are relevant by starting at the top (the Enterprise level) and working down. Any given code group can have the LevelFinal property; in which case the examination stops there. For example, if code is a member of a code group on the Machine level, and that group has the LevelFinal property, only the Enterprise and Machine levels are considered in assigning security. The Common Language Runtime computes the permissions for each level separately and then assigns the code the intersection of the permissions of all relevant levels. That is, if code is granted FileDialog permission on the Enterprise and Machine levels but is not granted FileDialog permission on the User level, the code will not have FileDialog permission. Across levels, this is a “most-restrictive” combination of permissions. At this point, the Common Language Runtime knows what permissions should be granted to the code in question, considered in isolation, but code does not run in isolation; it runs as part of an application. The final step in evaluating code access permissions is to perform a stack walk, in which the Common Language Runtime examines all code in the calling chain from the original application to the code being evaluated. The final permission set for the code is the intersection of the permission sets of all code in the calling
297 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Security . . . . .Issues . . .
chain. That is, if code is granted FileDialog permission but the code that called it was not, the code will not be granted FileDialog permission.
Requesting Other Types of Permissions Sometimes, you might want to request a particular permission even though your application doesn’t absolutely require that permission to proceed. That’s the purpose of optional permissions. To request optional permissions, use the SecurityAction.RequestOptional flag: Imports System.Security.Permissions
To use optional declarative permissions in Visual Basic .NET, your code should have a Sub Main starting point with a Try...Catch block. If optional permissions for the assembly can’t be granted, this block will catch the exception. If minimum permissions can’t be granted, the program will be shut down whether or not this block is present. When you request minimum permissions, the CLR will give your assembly any other permissions it can in addition to the minimum permissions. When you request optional permissions, the CLR will only give the assembly those permissions, and no others. So if you make an optional permissions request, you must be sure to request all the permissions that your code requires, including user interface permissions if you display any user interface.
You can also tell the CLR about permissions that you do not want your code to have. This can be useful if the code is potentially available to untrusted callers (for example, users who invoke the code over the Internet), and you want to limit the potential harm they can do. The flag for this is SecurityAction.RequestRefuse. Finally, you might want to ensure that all the code that calls your code has a particular permission. For example, you might want to raise an exception if any code in the calling stack doesn’t have Registry permissions. You can do this by specifying SecurityAction.Demand in the declaration of the security attribute.
Configuring Authentication To understand security in distributed applications, you must be knowledgeable about the closely intertwined subjects of authentication and authorization. Authentication refers to the process of obtaining credentials from a user
298 Chapter 12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
and verifying her identity. After an identity has been authenticated, it can be authorized to use various resources. ASP.NET provides you with flexible alternatives for authentication. Some, but not all, of these authentication methods also make sense in regular Windows applications. You can perform authentication yourself in code or delegate authentication to other authorities. Because it’s the most comprehensive case, I’ll consider authentication in the context of an ASP.NET application first and discuss other types of distributed applications later in the chapter.
No Authentication The simplest form of authentication is no authentication at all. To enable an application to execute without authentication, you add this section to its configuration file:
Setting the mode to None tells ASP.NET that you don’t care about user authentication. The natural consequence of this, of course, is that you can’t base authorization on user identities because users are never authenticated. This is appropriate for any ASP.NET site that should be available to anonymous users.
IIS and ASP.NET Authentication An ASP.NET application actually has two separate authentication layers. That’s because all requests flow through IIS (Internet Information Services) before they’re handed to ASP.NET, and IIS can decide to deny access before the ASP.NET process even knows about the request. Here’s a rundown on how the process works: 1. IIS first checks to make sure the incoming request comes from an IP
address that is allowed access to the domain. If not, the request is denied. 2. IIS performs its own user authentication, if it’s configured to do so. (I
talk more about IIS authentication later in the chapter.) By default, IIS allows anonymous access, so requests are automatically authenticated. 3. If the request is passed to ASP.NET with an authenticated user,
ASP.NET checks to see whether impersonation is enabled. If impersonation is enabled, ASP.NET acts as though it were the authenticated user. If not, ASP.NET acts with its own configured account.
299 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Security . . . . .Issues . . . 4. The identity from step 3 is used to request resources from the operat-
ing system. If all the necessary resources can be obtained, the user’s request is granted; otherwise, it is denied. As you can see, several security authorities interact when the user requests a resource or a Web page. If things aren’t behaving the way you think they should, it can be helpful to review this list and make sure you’ve considered all the factors involved.
Authentication Providers So what happens when a request gets to ASP.NET? The answer depends on the site’s configuration. The ASP.NET architecture delegates authentication to an authentication provider—a module whose job it is to verify credentials and provide authentication. ASP.NET ships with three authentication providers: ➤ The Windows authentication provider—Allows you to authenticate users
based on their Windows accounts. This provider uses IIS to perform the actual authentication and then passes the authenticated identity to your code. ➤ The Passport authentication provider—Uses Microsoft’s Passport service to
authenticate users. ➤ The Forms authentication provider—Uses custom HTML forms to collect
authentication information and allows you to use your own logic to authenticate users. Credentials are then stored in a cookie. To select an authentication provider, you make an entry in the Web.config file for the application. You can use one of these entries to select the corresponding built-in authentication provider:
You can also create your own custom authentication provider. This doesn’t mean you plug a new module in place of the supplied provider; it means that you write custom code to perform authentication and set the authentication mode for the application to None. For example, you might check a database to authenticate users at the level of incoming requests. In that case, you wouldn’t want to use any of the .NET authentication providers.
300 Chapter 12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Configuring IIS Authentication If you decide to use Windows authentication within your applications, you’ll need to consider how to configure IIS authentication. That’s because Windows identities are actually provided by IIS. IIS offers four different authentication methods: ➤ If you select anonymous authentication, IIS does not perform any
authentication. Anyone is allowed access to the ASP.NET application. ➤ If you select basic authentication, users must provide a Windows user-
name and password to connect. However, this information is sent across the network in clear text, making basic authentication dangerously insecure on the Internet. ➤ If you select digest authentication, users must still provide a Windows
username and password to connect. However, the password is hashed (scrambled) before being sent across the network. Digest authentication requires that all users be running Internet Explorer 5 or later and that Windows accounts are stored in Active Directory. ➤ If you select Windows integrated authentication, passwords never cross
the network. Users must still have a Windows username and password, but either the Kerberos or challenge/response protocols are used to authenticate the user. Windows integrated authentication requires that all users be running Internet Explorer 3.01 or later.
Passport Authentication ASP.NET has built-in connections to Microsoft’s Passport authentication service. If your users have signed up with Passport, and you configure the authentication mode of the application to be Passport authentication, all authentication duties are offloaded to the Passport servers. Passport uses an encrypted cookie mechanism to indicate authenticated users. If users have already signed in to Passport when they visit your site, they’ll be considered authenticated by ASP.NET. Otherwise, they’ll be redirected to the Passport servers to log in. To use Passport authentication, you’ll need to download the Passport Software Development Kit (SDK) and install it on your server. The SDK can be found at http://msdn.microsoft.com/library/default.asp?url=/downloads/ list/websrvpass.asp.
301 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Security . . . . .Issues . . .
You’ll also need to license Passport authentication. Currently, the license fees are $10,000 per year plus a periodic $1,500 testing fee per protected URL. You can get details on licensing Passport at http://www.microsoft.com/net/ services/passport/.
Forms Authentication Forms authentication provides you with a way to handle authentication using your own custom logic within an ASP.NET application. (Note that this is different from custom authentication using an ISAPI filter, which takes place before the request ever gets to ASP.NET.) With forms authentication, the logic of the application goes like this: 1. When a user requests a page from the application, ASP.NET checks
for the presence of a special session cookie. If the cookie is present, the request is processed. 2. If the cookie is not present, ASP.NET redirects the user to a Web form
that you provide. 3. You can carry out whatever authentication checks you like in your
form. When the user is authenticated, you indicate this to ASP.NET, which creates the special cookie to handle subsequent requests.
Configuring Authorization After your application has authenticated users, you can proceed to authorize their access to resources. But there’s a question to answer first: Just who is the user to whom you are granting access? It turns out that there are different answers to that question, depending on whether you implement impersonation. With impersonation, the ASP.NET process can actually take on the identity of the authenticated user. Impersonation only applies to applications that use ASP.NET to communicate with the server. For other server applications (such as services and serviced components), impersonation doesn’t come into the picture. Once a user has been authenticated and you’ve decided whether to use impersonation, you can proceed to grant access to resources. You can use the role-based authorization features of the .NET Framework for this purpose.
302 Chapter 12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Implementing Impersonation ASP.NET impersonation is controlled by entries in the applicable Web.config file. The default setting is no impersonation. You can also explicitly specify this setting by including the following element in the file:
With this setting, ASP.NET does not perform user impersonation. What does that mean? It means that ASP.NET will always run with its own privileges. By default, ASP.NET runs as an unprivileged account named ASPNET. You can change this by making a setting in the processModel section of the machine.config file. This setting can only be changed in machine.config, so any change automatically applies to every site on the server (and no site can have a setting different from that of the server). To use a high-privilege system account instead of a low-privilege account, set the userName attribute of the processModel element to SYSTEM. So when impersonation is disabled, all requests will run in the context of the account running ASP.NET—either the ASPNET account or the system account. This is true whether you’re using anonymous access or authenticating users in some fashion. The second possible setting is to turn on impersonation:
In this case, ASP.NET takes on the identity passed to it by IIS. If you’re allowing anonymous access in IIS, this means that ASP.NET will impersonate the IUSR_ComputerName account that IIS itself uses. If you’re not allowing anonymous access, ASP.NET will take on the credentials of the authenticated user and make requests for resources as if it were that user. Finally, you can specify a particular identity to use for all authenticated requests:
With this setting, all requests are made as the specified user (assuming that the password is correct in the configuration file).
Security for Windows Services In most aspects, a Windows service is an application like any other. You can use code access security to specify the permissions that this application needs
303 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Security . . . . .Issues . . .
and control whether those permissions are available by using the .NET Framework configuration tool. But because Windows services are launched at bootup time and run for the entire time that the operating system is loaded, you need to pay special attention to the security context in which they run. The security context for a service is initially specified by the Account property of the ServiceProcessInstaller object that was used to place the service on the system (although the user can later change this context by using the Services administrative tool). .NET lets you choose one of the four values of the ServiceAccount enumeration for this property: ➤ The LocalService account is a built-in account that has few privileges on
the local computer. When accessing resources from a remote computer, the LocalService account presents anonymous credentials. ➤ The NetworkService account is a built-in account that has few privileges
on the local computer. When accessing resources from a remote computer, the NetworkService account presents the computer’s credentials. ➤ The LocalSystem account is a built-in account that has high privileges
on the local computer. When accessing resources from a remote computer, the LocalSystem account presents the computer’s credentials. ➤ The User value for the Account property requires you to supply a valid
Windows username and password. The service runs with the privileges of the specified user and presents that user’s credentials when requesting network resources. The LocalService and NetworkService accounts are only available on Windows XP and Windows Server 2003. These accounts do not exist on Windows 2000 or older operating systems.
The LocalSystem account is used for most of the built-in services in Windows, such as the Computer Browser, Event Log, and Indexing services. These are services that require extensive access to resources on your computer to do their work. It might be tempting to install your own services using this account as well, but you should consider carefully whether your services need such sweeping privileges. Remember that ease of use is balanced by danger in this case. If you’ve made an error in your code, an attacker could potentially exploit your service to gain the privileges of the account under which it runs. If that account is the LocalSystem account, a successful attacker could take over the entire computer.
304 Chapter 12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Security for Web Services Because they are applications layered on top of ASP.NET, Web services offer you many opportunities for configuring and implementing security. You can choose to secure things at the level of IIS itself, in the ASP.NET layer, or in the application itself. Depending on the choices you make, nearly any type of security can be applied to a Web service.
Platform and Application Security Because SOAP messages come in via HTTP on port 80, IIS handles them on Windows servers. This means that you can use the full spectrum of IIS authentication modes for a Web service: anonymous, basic, digest, integrated (Windows), and so on. You can also configure IIS to accept requests from only a specified range of IP addresses. If the incoming SOAP request fails to authenticate (assuming that you have disabled anonymous authentication) or the IP address is not allowed access to the server, that’s it: The Web service will not be called. Forms authentication and Passport authentication are not supported for Web services applications.
Assuming that the SOAP request properly authenticates, the next question is which identity will be passed to ASP.NET and then to the Web service. This depends on the type of authentication you’ve performed and on whether impersonation is enabled; you can make settings in the Web.config file for a Web service to control impersonation just as you can for any other ASP.NET application (see the section “Implementing Impersonation” earlier in the chapter for details). Here are the particulars: ➤ If impersonation is disabled, requests will run in the security context of
either the ASPNET account or the system account, depending on the processModel setting in the machine.config file. ➤ If impersonation is enabled and you allow anonymous access in IIS,
requests will run in the security context of the IUSR_ComputerName account. ➤ If impersonation is enabled, you do not allow anonymous access, and
you do not specify a user identity in the identity tag, requests will run in the security context of the authenticated Windows user.
305 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Security . . . . .Issues . . . ➤ If impersonation is enabled, you do not allow anonymous access, and
you do specify a user identity in the identity tag, requests will run in the security context of the specified Windows user. After the user has been authenticated and the identity for ASP.NET requests has been determined, the next line of defense is the ASMX file that implements the Web service itself. You can protect this file with either URL or file authorization. URL authorization is specified within the Web.config file as part of the tag. You saw an example of this earlier in the chapter:
URL authorization allows you to deny access to a resource (in this case, any resource in the Web service application) to unauthenticated users or to grant access to only specified users. If you’re using Windows authentication in IIS, you can also protect the file by using file authorization. For file authorization, right-click the ASMX file in Windows Explorer and select Properties. The Security tab of the Properties dialog box, shown in Figure 12.1, lets you control which Windows users can open the file.
Figure 12.1 Setting file authorization properties for a Web service.
Assuming that the authenticated user can read the ASMX file, the final line of defense is code within the file. You can use imperative or declarative code
306 Chapter 12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
access or role-based security within an ASMX file, just as you can inside of any other assembly.
Configuring Web Services for Security Here are some guidelines for securing your Web services: ➤ If you need to be able to authorize access to resources based on the
caller’s identity, you should set up your server to perform Windows authentication with impersonation. For example, if only some of the authorized users should be able to read access from a particular database table or via a particular COM+ serviced component, you’ll need to take this approach so that the caller’s security context is available to other components. ➤ If all users of your Web service should be able to access the same
resources once they’re authenticated, you should set up your server to perform Windows authentication without impersonation. Then you can use declarative or imperative security to provide resource access to the account under which ASP.NET is running. ➤ You should generally avoid using Windows authentication with a fixed
identity (established by the element in the Web.config file). That’s because this strategy requires storing the password for the fixed identity account in clear text in the configuration file, which is an inherently unsecured situation. ➤ On production servers, you should disable HTTP-GET and HTTP-
POST access to Web services, limiting them to SOAP access. This is most important when the Web service should be only available to clients on your intranet, and those same clients are allowed to browse to the Internet. Under those circumstances, a malicious Web page on the Internet could contain a carefully crafted link that would cause the client to invoke the internal-only Web service. This is only possible through the HTTP-GET and HTTP-POST protocols because Web pages can’t create a SOAP message as part of a link. To disable such access, modify the section of the machine.config file as follows:
307 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Security . . . . .Issues . . .
Remoting Security As with Windows services and Web services, .NET Remoting applications are like any other .NET application and can use the same imperative and declarative security techniques to protect resources. The major difference is that remoting introduces additional “plumbing” to allow your object to be called from client applications on other computers. The objects themselves can still be protected with .NET security, just like any other objects. With remoting applications, the major security-related decision that you need to make is which application will host the remoting server. You have three choices here: ➤ Host in a console application ➤ Host in a Windows service ➤ Host in ASP.NET
Hosting your remoting server in a console application is convenient, but that’s about the only thing you can say in favor of this approach. You might want to use a console application, as I did in Chapter 4, “.NET Remoting,” when you’re developing a new remoting server. Console applications are easier to make changes to and to debug than either Windows services or ASP.NET applications. The problem, from a security standpoint, is that console applications don’t have any built-in authentication or authorization mechanisms. You can write your own custom authentication and authorization code, of course, but such schemes are notoriously difficult to actually make secure. When you host your remoting server in a Windows service, you’re limited to using the TCP channel. This means that you must write custom code to handle authentication and authorization—with the attendant danger of writing code that doesn’t quite work. However, you can use the security of the underlying TCP channel to provide secure communication by making use of the IPSec standard. With a Windows service as your remoting host, it’s easy to limit the damage that a security breach can do by choosing an appropriate account to run the service. You can also use permission refusals to make sure the service cannot perform dangerous actions beyond the scope of its regular operations. For secure communications—for instance, when your remoting server must make objects available to authenticated clients over the Internet—your best bet is to host the server in ASP.NET. That’s because hosting in ASP.NET
308 Chapter 12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
automatically makes all the authentication, authorization, and security features of IIS available to your server, just as they are available to a Web service. Clients must use the HTTP channel to communicate with the server, which is slower than the TCP channel but more secure. You can also use the logging features of IIS to track requests to the remoting server. When the remote object is hosted in ASP.NET, you must specify the credentials to be used for authentication via the credentials property of the channel. This code must exist in the remoting client proxy class. If you neglect to do this, credentials won’t be passed to the remoting server, even if you successfully authenticate with ASP.NET. Fortunately, the code is simple because you can extract the default cached credentials that were used to authenticate in the first place: Dim ChannelProperties As IDictionary = _ ChannelServices.GetChannelSinkProperties( _ RemoteObjectProxy) ChannelProperties(“credentials”) = _ CredentialCache.DefaultCredentials
Reviewing these choices, you can see that ASP.NET is generally the best hosting solution for a remoting server that must provide secure access for authenticated clients. For a remoting server that has no authentication requirements, you’ll probably find that hosting in a Windows service requires fewer resources and is easier to deploy.
Enterprise Services Security Serviced components benefit from a set of authentication and authorization services that are included in the Enterprise Services (COM+) infrastructure. Authentication is provided over the Remote Procedure Call (RPC) channel between client and server, so clients will automatically present the server with their Windows identity. Authorization is provided by Enterprise Services roles, which are identical to COM+ roles. An Enterprise Services role can contain Windows users and Windows groups. You can limit access to applications, components, interfaces, and methods within a serviced component to members of specific roles. You can use these attributes to configure security for a serviced component: ➤ The ApplicationAccessControl attribute—This attribute at the assembly
level enables access checking at the process and component levels. ➤ The SecurityRole attribute—This attribute at the assembly level specifies
the COM+ roles that will be able to use any of the classes from the assembly.
309 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Security . . . . .Issues . . . ➤ The ComponentAccessControl attribute—This attribute at the class level
enables component-level access checking. ➤ The SecurityRole attribute—This attribute at the class level specifies the
COM+ roles that will be allowed to create instances of the class. ➤ The SecureMethod attribute—This attribute at the class level allows you to
use the Component Services tool to configure roles for the class. ➤ The SecurityRole attribute—This attribute at the method level specifies
the COM+ roles that will be allowed to invoke the method.
310 Chapter 12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exam Prep Questions Question 1 You want to check from within your code whether the code has permission to access OLE DB data sources. You also want to allow the CLR to assign you additional permissions. Which SecurityAction flag should you use with the OleDbPermission object? ❍ A. SecurityAction.RequestMinimum ❍ B. SecurityAction.RequestOptional ❍ C. SecurityAction.Demand ❍ D. SecurityAction.RequestRefuse
Answer A is correct. When you make a minimum permissions request, you’ll get at least the permissions you asked for, if permissions can be assigned at all. Answer B is incorrect because an optional permissions request only assigns the requested permissions. Answer C is incorrect because a demand request demands permissions of the code that calls your code. Answer D is incorrect because a refuse permissions request tells the CLR not to assign a particular permission.
Question 2 You are allowing anonymous or Windows integrated authentication on your IIS server. ASP.NET is running with machine-level privileges. Your ASP.NET application uses Windows authentication with impersonation enabled. What account will ASP.NET use when a user attempts to retrieve a page from the application? ❍ A. The user’s own Windows account ❍ B. The ASPNET account ❍ C. The IUSR_ComputerName account ❍ D. The local Administrator account
Answer C is correct. When the IIS server allows anonymous authentication, IIS will present its own credentials to ASP.NET. With impersonation enabled, ASP.NET will use these credentials, the IUSR_ComputerName account. Answer A is incorrect because Windows authentication will not be used when anonymous authentication is enabled. Answer B is incorrect because ASP.NET’s identity won’t be used when impersonation is enabled. Answer D is incorrect because the local Administrator account would only be used if ASP.NET were instructed to impersonate that account.
311 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Security . . . . .Issues . . .
Question 3 Assembly A is a member of the following code groups (and only the following code groups): Level Enterprise Enterprise Enterprise Enterprise
Code Group All Code Corporate Code Web Code Restricted Code
Permission Set Everything LocalIntranet Internet Nothing
Exclusive No No No No
LevelFinal No No No No
What permission does the Common Language Runtime assign to Assembly A? ❍ A. Everything ❍ B. LocalIntranet ❍ C. Internet ❍ D. Nothing
Answer A is correct. Within a single level, the permissions of an assembly are the union of the permissions of all code groups to which the assembly belongs. Therefore, the assembly gets the least-restrictive set of permissions (Everything, in this case). Answers B, C, and D are incorrect because those permission sets are more restrictive than Everything.
Question 4 Assembly B is a member of the following code groups (and only the following code groups): Level Enterprise Enterprise Machine User
Code Group All Code Corporate Code Web Code Restricted Code
Permission Set Everything LocalIntranet Internet Nothing
Exclusive No No No No
LevelFinal No No No No
What permission does the Common Language Runtime assign to Assembly B? ❍ A. Everything ❍ B. LocalIntranet ❍ C. Internet ❍ D. Nothing
Answer D is correct. Across levels, the permissions of an assembly are the intersection of the permissions determined on each individual level. Therefore, the assembly gets the most-restrictive set of permissions
312 Chapter 12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
(Nothing, in this case, because that is the only permission on the User level). Answers A, B, and C are incorrect because those permission sets are less restrictive than Nothing.
Question 5 Assembly C is a member of the following code groups (and only the following code groups): Level Enterprise Enterprise Machine User
Code Group All Code Corporate Code Web Code Restricted Code
Permission Set Everything LocalIntranet Internet Nothing
Exclusive No Yes No No
LevelFinal No No No No
What permission does the Common Language Runtime assign to Assembly C? ❍ A. Everything ❍ B. LocalIntranet ❍ C. Internet ❍ D. Nothing
Answer B is correct. When an assembly is a member of a code group marked with the Exclusive property, the CLR only takes the permissions of that code group into account when determining the permissions of the code. Answers A, C, and D are incorrect because these groups are not considered in this case.
Question 6 Assembly D is a member of the following code groups (and only the following code groups): Level Enterprise Enterprise Machine User
Code Group All Code Corporate Code Web Code Restricted Code
Permission Set Everything LocalIntranet Internet Nothing
Exclusive No No No No
LevelFinal Yes No No No
What permission does the Common Language Runtime assign to Assembly D? ❍ A. Everything ❍ B. LocalIntranet ❍ C. Internet ❍ D. Nothing
313 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Security . . . . .Issues . . .
Answer A is correct. When an assembly is a member of a code group marked with the LevelFinal property, the CLR does not consider code groups below that level when determining the permissions of the code. In this case, that leaves the two code groups on the Enterprise level, and the final permissions are the union (the least-restrictive combination) of those two groups. Answer B is incorrect because LocalIntranet is more restrictive than Everything. Answers C and D are incorrect because these permissions come from levels below the Enterprise level.
Question 7 Your application requires permission to retrieve data from a SQL Server database in order to function properly. Which .NET security feature should you use to ensure that your code has the proper permissions? ❍ A. Code access security ❍ B. Role-based security ❍ C. Authentication ❍ D. Authorization
Answer A is correct. Code access security lets the CLR determine, based on the running code, whether particular permissions should be available. Answer B is incorrect because role-based security determines the permissions of the user rather than of the code. Answer C is incorrect because authentication establishes the identity of the current user. Answer D is incorrect because authorization assigns permissions to authenticated users.
Question 8 Your ASP.NET application contains the following setting in the Web.config file:
You are allowing only digest or Windows integrated authentication in IIS. What identity will ASP.NET use to authorize resources if a user with the Windows account George in the SALES domain logs in? ❍ A. SALES\George ❍ B. ASPNET ❍ C. MAIN\Charles ❍ D. IUSR_ComputerName
314 Chapter 12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Answer C is correct. When you set up impersonation to a particular user in the Web.config file, ASP.NET will use that identity for all authorization. Answers A, B, and D are incorrect because they refer to other identities.
Question 9 Your application requires users to be members of the local Administrators group in order to activate certain features. Which .NET security feature should you use to check whether a user is in this group? ❍ A. Code access security ❍ B. Encryption ❍ C. Role-based security ❍ D. Authorization
Answer C is correct. With role-based security, you can check the group membership of the current user and take appropriate action. Answer A is incorrect because code access security assigns permissions to the code rather than to users. Answer B is incorrect because encryption is used to hide information, not to verify identity. Answer D is incorrect because authorization assigns permissions to users after their identity is established.
Question 10 You have created a Windows service that collects uptime information from various computers around the network and then consolidates this information into a local disk file. The service runs on a Windows Server 2003 computer. The service does not need system-level privileges on the local computer, but it must be able to authenticate to the remote computers as a member of the domain. Which security context should you use for this service? ❍ A. LocalService ❍ B. NetworkService ❍ C. LocalSystem ❍ D. A member of the local Administrators group
Answer B is correct. The NetworkService account presents the computer’s credentials for authentication to remote computers. Answer A is incorrect because LocalService presents anonymous credentials to remote computers. Answer C is incorrect because the LocalSystem account has more privileges than you need in this situation. Answer D is incorrect because local accounts do not authenticate to the domain.
315 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Security . . . . .Issues . . .
Need to Know More? LaMacchia, Brian A., et al. .NET Framework Security. AddisonWesley, 2002. Building Secure ASP.NET Applications:
http://msdn.microsoft.com/
library/en-us/dnnetsec/html/secnetlpMSDN.asp.
13 Practice Exam #1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Do not read Chapters 13 through 16 until you have learned and practiced all the material presented in the earlier chapters of this book. These chapters serve a special purpose; they are designed to test whether you are ready for taking Exam 70-310, “Developing XML Web Services and Server Components with Microsoft Visual Basic .NET and Microsoft .NET Framework.” In these chapters, you will find two practice exams. Each practice exam is followed by an answer key and brief explanation of correct answers along with an explanation as to why the other answers are incorrect. Reading these chapters prior to other chapters is like reading the climax of a story and then going back to find out how the story arrived at that ending. Of course, you don’t want to spoil the excitement, do you?
How to Take the Practice Exams Each practice exam in this book consists of 65 questions, and you should complete it within 120 minutes. The number of questions and the time duration in the actual exam may vary but should be close to this number. Once you have prepared using the material presented in the earlier chapters of this book, you should take Practice Exam #1 to check how prepared you are. After the practice exam is complete, evaluate yourself using the answer key in Chapter 14, “Answer Key for Practice Exam #1.” When you evaluate yourself, note the questions you answered incorrectly, identify their corresponding chapters in the book, and then read and understand that material before taking Practice Exam #2. After taking Practice Exam #2, evaluate yourself again and reread the material corresponding to any incorrect answers. Finally, repeat both practice exams until you correctly answer all the questions. Information in the following section helps you in taking the practice exam and then evaluating yourself.
318 Chapter 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exam-taking Tips You take these sample exams under your own circumstances, but I strongly suggest that when you take this practice exam, you treat it just as you would treat the actual exam at the test center. Use the following tips to get maximum benefit from the practice exam: ➤ Before you start, create a quiet, secluded environment where you are not
disturbed for the duration of the exam. ➤ Provide yourself a few empty sheets of paper before you start. Use some
of these sheets to write your answers, and use the others to organize your thoughts. At the end of the exam, use your answer sheet to evaluate your exam with the help of the answer key that follows. ➤ Don’t use any reference material during the exam. ➤ Some of the questions may be vague and require you to make deduc-
tions to come up with the best possible answer from the possibilities given. Others may be verbose, requiring you to read and process a lot of information before you reach the actual question. ➤ As you progress, keep track of the elapsed time and make sure you’ll be
able to answer all the questions in the given time limit.
319 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#1.
Practice Exam Question 1 You have developed a .NET Remoting server that is used by employees in your organization to place vacation requests. The server makes available a Singleton SAO named VacationRequest. Clients send their employee IDs when they create the object and then later post them with their vacation requests. The server then records the information in a Jet database. You discover that at peak times vacation requests are being mixed. For example, the vacation request from employee ID 3235 is being saved as a request from employee ID 4238. What can you do to fix this issue? ❍ A. Switch from using a Singleton SAO to using a CAO. ❍ B. Switch from using a Singleton SAO to using a SingleCall SAO. ❍ C. Switch the database from Jet to SQL Server. ❍ D. Issue a confirmation number with each call to an object to which the employee can later refer.
Question 2 You are building a .NET Remoting server that exposes the Employee type as a server-activated object. The Employee type is defined as follows: Public Class Employee Inherits MarshalByRefObject Private EmployeeName As String Private m_HireDate As DateTime Public Property HireDate As DateTime Get HireDate = m_HireDate End Get Set m_HireDate = value End Set End Property Private m_Salary As Double Public Function Salary As Double Salary = m_Salary End Function Public Shared DepartmentName As String End Class
320 Chapter 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Which members of Employee will not be available remotely? [Select all that apply.] ❑ A. EmployeeName ❑ B. HireDate ❑ C. Salary ❑ D. DepartmentName
Question 3 You are developing a distributed application using the .NET Remoting infrastructure. The application exposes the Order object as a remote object to its client applications. The Order object consists of order details and an array of Product objects. The Product object consists of four fields: ProductID, Price, Qty, and QtyOnStock. The QtyOnStock field is not used by the client applications. You are expecting that a large number of Product objects will be created by the application. You want to write minimal code as well as minimize the network traffic as much as possible. What should you do? [Select two.] ❑ A. Mark the ProductID, Price, and Qty fields of the Product class with the Serializable attribute. ❑ B. Mark the QtyOnStock field with the NonSerialized attribute. ❑ C. Mark the Product class with the Serializable attribute. ❑ D. Make the Product class implement the ISerializable interface.
Question 4 You want to host a remotable class via the .NET Remoting framework so that remote clients can instantiate the class and invoke methods on it. The system standards require you to use Windows integrated authentication to authenticate users of the object. You want a solution that minimizes additional coding requirements. Which of the following techniques should you use to host the remotable class? ❍ A. Use Internet Information Services (IIS) as a remoting host. ❍ B. Use a console application as a remoting host. ❍ C. Create a Windows service and use that to host the remotable class. ❍ D. Use a Web service application to host the remotable class.
321 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#1.
Question 5 You are developing a distributed application that allows client programs to instantiate a class named Transaction. You want the remote object to be created on the server so that it can access the corporate financial information, which is stored on an intranet. Which of the following options should you implement to make the Transaction class accessible through .NET Remoting? ❍ A. Mark the Transaction class with the Serializable attribute. ❍ B. The Transaction class should inherit from the MarshalByRefObject class. ❍ C. The Transaction class should implement the ISerializable interface. ❍ D. The Transaction class should implement the IActivator interface.
Question 6 You have designed a remotable class that allows the user to retrieve the latest weather information for his or her region. You have stored the configuration settings in a configuration file:
Which of the following methods should you use to load the configuration details from the configuration file? ❍ A. Activator.GetObject ❍ B. Activator.CreateInstance ❍ C. Activator.CreateInstanceFrom ❍ D. RemotingConfiguration.Configure
322 Chapter 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 7 You work for a large chemical manufacturing company that has four production units across the country. Your team has the responsibility of designing a distributed application that allows different production units to share and update material safety information for various products. One of your coworkers is using the following code to create a remoting host to host a server-activated object and is getting an error. What should she do to resolve this error? 01: 02: 03: 04: 04: 05: 06: 07:
Imports Imports Imports Imports
System.Runtime.Remoting System.Runtime.Remoting.Channels System.Runtime.Remoting.Channels.Tcp System.Runtime.Remoting.Channels.Http
Sub Main() ‘ Create and Register channels Dim tcpChannel As TcpServerChannel = _ New TcpServerChannel(7777) 08: Dim httpChannel As HttpServerChannel = _ New HttpServerChannel(8888) 09: RemotingConfiguration.RegisterWellKnownServiceType _ (GetType(MsdsInfo), “MsdsInfo”, _ WellKnownObjectMode.Singleton) 10: End Sub
❍ A. Remove the statement at line 08. ❍ B. Add the following statements just before line 09: ChannelServices.RegisterChannel(tcpChannel) ChannelServices.RegisterChannel(httpChannel)
❍ C. In the statement at line 07, replace TcpServerChannel with TcpChannel. Similarly, in the statement at line 08, replace HttpServerChannel with HttpChannel. ❍ D. Use the same port numbers in the statements at line 07 and line 08.
Question 8 You have used the Web Services Discovery Tool to retrieve information about a Web service named OrderTracker. Which file will contain the URL for any documentation of the OrderTracker Web service? ❍ A. results.discomap ❍ B. OrderTracker.disco ❍ C. Reference.vb ❍ D. OrderTracker.wsdl
323 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#1.
Question 9 You have created a Web service that provides BankAccount details. One of your client applications calls the Web service proxy, which is generated with the wsdl.exe tool, to retrieve bank account information. This information takes some time to generate, and your application is unresponsive while you are waiting for the results. What can you do to fix this problem? ❍ A. Install a faster link to the Internet. ❍ B. Install more memory in the client computer. ❍ C. Use asynchronous calls to invoke the Web service. ❍ D. Use the new proxy generated automatically by adding a Web reference to the Web service. ❍ E. Use the new proxy generated with the wsdl.exe tool using the /proxy option.
Question 10 You want to use a Web service that supplies credit card–verification services from your application. You know the URL of the ASMX file published by the Web service. What step should you take first? ❍ A. Run the Web Services Discovery tool. ❍ B. Open the ASMX file in a Web browser. ❍ C. Run the XML Schema Definition tool. ❍ D. Copy the ASMX file to your client project.
Question 11 You are designing a Web service that will return roughly 300KB of database information to clients on your intranet. How should you declare the Web method? ❍ A. _ Public Function GetData() As Object _
❍ B. _ Public Function GetData() As Object _
❍ C. _ Public Function GetData() As Object _
324 Chapter 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ❍ D. _ Public Function GetData() As Object _
Question 12 You are developing a SOAP extension to run in a Web service client application. The SOAP extension includes a class named MyExtensionAttribute to flag methods to which the extension applies. The client project contains this code: Private Sub btnGetData_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnGetData.Click ‘ Call a Web method on the object Dim I As InvWebService.Inventory = _ New InvWebService.Inv() objWarehouse.Inv = I.GetLatest() End Sub
Where should you apply the MyExtensionAttribute attribute so that it interacts with the SOAP requests generated by this procedure? ❍ A. To the btnGetData_Click method ❍ B. To the GetInitializer method in your SOAP extension ❍ C. To the GetLatest method in the Web service proxy class ❍ D. To the Load event of the form containing the button
Question 13 You have purchased a commercial SOAP extension for use with your Web service. This extension encrypts some attributes in the AfterSerialize event on the client and decrypts the attributes in the BeforeDeserialize event on the server. Now you want to add your own SOAP extension to track some statistics on the incoming XML data. This SOAP extension will need access to the decrypted attributes from the other SOAP extension. How should you implement the new SOAP extension? ❍ A. Add the new SOAP extension in the BeforeDeserialize event with a higher priority than the existing SOAP extension. ❍ B. Add the new SOAP extension in the BeforeDeserialize event with a lower priority than the existing SOAP extension. ❍ C. Add the new SOAP extension in the AfterDeserialize event with a higher priority than the existing SOAP extension. ❍ D. Add the new SOAP extension in the AfterDeserialize event with a lower priority than the existing SOAP extension.
325 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#1.
Question 14 You need to develop a Windows application that accesses the Orders XML Web service provided by your company’s business partner. You know the URL of the Web service. How can you generate client-side proxy classes for the Web service? [Select two.] ❑ A. Use a proxy tool such as the .NET WebService Studio tool. ❑ B. Use the Web Services Description Language tool. ❑ C. Use the Web Services Discovery tool. ❑ D. Set a Web reference to point to the Web service.
Question 15 Your code is making asynchronous calls to two different Web methods. You want to execute other code until you arrive at a point where you require the results from the asynchronous calls. How should your code wait for the results of the asynchronous calls? [Select the two best answers.] ❑ A. Use a pair of delegate callbacks, one for each Web method. ❑ B. Use a WaitHandle.WaitAny method call, specifying both Web methods. ❑ C. Use a WaitHandle.WaitAll method call, specifying both Web methods. ❑ D. Use two WaitHandle.WaitOne method calls, one for each Web method.
Question 16 You are developing a serviced component that manages book sales. Whenever a sale is made, the ProcessSale method of the serviced component is called. The ProcessSale method calls the ValidateCreditCard Web method to validate credit card numbers entered by the user of the CreditCard Web service and then records the sales in the database by calling the RecordSales Web method from the Sales Web service. After calling these Web methods, the ProcessSale method then records the shipping instructions and sales details in the Shipping database. The code of the ProcessSale method is defined as follows: _ Public Class Books Inherits ServicedComponent Implements IBooks _ Public Sub ProcessSale(ByVal abooks As Books()) Dim cc As CreditCard = New CreditCard() If cc.ValidateCreditCard() Then Dim sa As Sales = New Sales()
326 Chapter 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
sa.RecordSales() End If ‘ Record the shipping instructions and sales ‘ detail in the Shipping database End Sub End Class
The ValidateCreditCard and RecordSales Web methods have their TransactionOption property set to Required and RequiresNew, respectively. When the serviced component method is executed, the method throws an exception when it tries to save the shipping instructions in the Shipping database. What would be the state of the transactions? ❍ A. All the transactions are rolled back. ❍ B. The transaction in only the RecordSales method is committed. The transactions in the ValidateCreditCard and ProcessSale methods are rolled back. ❍ C. Transactions in the ValidateCreditCard and RecordSales Web methods are committed. The transaction in the ProcessSale method is rolled back. ❍ D. The transaction in only the ValidateCreditCard Web method is committed. The transactions in the RecordSales and ProcessSale methods are rolled back.
Question 17 You have created a Windows service that monitors email messages on your company’s mail server. The service will execute on the mail server, which is a Windows 2000 Advanced Server machine. To perform its work, the Windows service needs administrative access to the computer. Which security context should you use as the startup account for the service? ❍ A. LocalSystem ❍ B. LocalService ❍ C. NetworkService ❍ D. User
Question 18 You have built a Windows Service application that will monitor network activity on a specified TCP/IP port. You intend to allow the user to specify the port as a parameter from the Services MMC snap-in. Where should you process the user’s selection?
327 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#1. ❍ A. In the Main method of the service ❍ B. In the OnStart method of the service ❍ C. In the Run method of the service ❍ D. In the OnContinue method of the service
Question 19 You are part of a team that is developing a Windows service application to monitor a legacy application for new data. Occasionally your application may encounter errors. You want to develop an error-reporting mechanism that is easy to use for administrators who will monitor and maintain the application on a day-to-day basis. You also want a scheme that is robust and requires a minimal amount of code. Which of the following techniques should you choose? ❍ A. Use the event log ❍ B. Use SQL Server tables ❍ C. Use XML-based log files ❍ D. Use plain-text log files
Question 20 You are building a class for a component that will be registered with COM+. You have defined the interface for the serviced component: Public Interface IPhysicians Function Patients(ByVal PhysicianID As String) _ As DataSet End Interface
You want to register the component only with the IPhysicians interface defined in the preceding code snippet. How should you define the serviced component class? ❍ A. Public Class Physicians Inherits ServicedComponent Implements IPhysicians End Class
❍ B. _ Public Class Physicians Inherits ServicedComponent Implements IPhysicians End Class
328 Chapter 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ❍ C. _ Public Class Physicians Inherits ServicedComponent Implements IPhysicians End Class
❍ D. _ Public Class Physicians Inherits ServicedComponent Implements IPhysicians End Class
Question 21 You have created a component that uses the COM+ object-pooling service via the classes of the System.EnterpriseServices namespace. You have installed the component on the production server. You would like to monitor the usage pattern for the component to determine the optimum size for the object pool. How should you do this? ❍ A. Activate component events and statistics within the Component Services administrative tool. ❍ B. Add code to the class to write messages to the event log whenever an instance of the class is created or destroyed. ❍ C. Add code to the class to maintain a custom performance monitor with object pool statistics. ❍ D. Use a performance monitor to track the committed RAM on the server to deduce the number of instances of the object created.
Question 22 You have been given an assignment to develop the order-processing application for your organization. The application needs to support a large number of users and should perform well during the peak time for receiving and processing orders. Which of the following COM+ services would you use in your application? [Select all that apply.] ❑ A. Queued components ❑ B. Automatic transactions ❑ C. Object pooling ❑ D. Just-in-time activation
329 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#1.
Question 23 You are creating a serviced component named DataConnector. After the component is deployed, the system administrators should be able to configure the component to connect to various data sources by specifying the connection string of the data source. The serviced component will be used by both COM and .NET applications. You want to retrieve the specified connection string in your component and change the behavior of the serviced component. Which of the following techniques should you use to achieve this? ❍ A. Override the Activate method of the serviced component. ❍ B. Override the Construct method of the serviced component. ❍ C. Create a method for the serviced component that receives a connection string as its parameter. Add the method definition in the component’s interface. ❍ D. Create a New method for the serviced component that receives a connection string as its parameter.
Question 24 You are creating a serviced component named Shipping that includes the following code segment: _ Public Class Shipping Inherits ServicedComponent End Class
You want the component to lock the data in such a way that no dirty reads are possible, which means that the same read operation should not retrieve different values for different users. While the data is locked, other users should be able to insert a new row but should not be able to update an existing row. How should you modify your code? ❍ A. Change the Isolation property of the Transaction attribute to IsolationLevel.ReadCommitted. ❍ B. Change the Isolation property of the Transaction attribute to IsolationLevel.ReadUncommitted. ❍ C. Change the Isolation property of the Transaction attribute to IsolationLevel.RepeatableRead. ❍ D. Change the Isolation property of the Transaction attribute to IsolationLevel.Serializable.
330 Chapter 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 25 You are responsible for maintaining a COM component that is used by numerous applications throughout your company. You are not yet ready to convert this COM component to .NET managed code, but you need to make it available to an increasing number of other projects that are being developed under the .NET Framework. What should you do? ❍ A. Set a direct reference to the existing COM component from each .NET project. ❍ B. Use the Type Library Importer tool to create and sign an assembly that will use the COM component. Place the created assembly in the Global Assembly Cache. ❍ C. Use the Type Library Importer tool to create an assembly that will use the COM component. Place the created assembly in the Global Assembly Cache. ❍ D. Obtain a Primary Interop Assembly for the COM component. ❍ E. Set a direct reference from a single .NET project to the COM component. Include this project in each solution that must make use of the component.
Question 26 In which of these situations should you use tlbimp, the Type Library Importer tool? [Select two.] ❍ A. When you must call a COM component that you wrote from Visual Basic .NET code ❍ B. When you must produce a strong-named assembly that calls methods from one of your company’s COM components ❍ C. When you require objects from Microsoft Word in your .NET application ❍ D. When you need to be able to call Windows API functions in kernel.dll from your .NET code
331 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#1.
Question 27 You use Visual Basic .NET to create an assembly named Processor.dll. This assembly contains several complex graphics-manipulation classes and is used by several applications—managed as well as unmanaged. The COM applications are already compiled, and they use late binding to invoke methods from the assembly. What actions should you take to ensure that the assembly is properly deployed on the target machine? [Select all that apply.] ❑ A. Create a strong name for the assembly by using the Strong Name tool (sn.exe). ❑ B. Register the assembly using the Assembly Registration tool (regasm.exe). ❑ C. Create a type library for the application using the Type Library Exporter tool (tlbexp.exe). ❑ D. Import the COM type library definition into an assembly by using the Type Library Importer tool (tlbimp.exe). ❑ E. Deploy the assembly to the Global Assembly Cache (GAC). ❑ F. Deploy the assembly to the Windows system directory.
Question 28 In your .NET application, you use a DataSet object containing a single DataTable object named Customers. The Customers DataTable has all the rows and columns from the Customers table in your database. You would like to bind only selected columns from the Customers table to a DataGrid control. You want a solution that requires minimal programming, and you want to have minimal impact on the functionality and performance of other applications accessing the same SQL Server database. How should you proceed? ❍ A. Create a second DataTable object in the DataSet object. Copy the desired data to the second DataTable object. Bind the second DataTable object to the DataGrid control. ❍ B. Create a Command object to retrieve the desired columns from the DataTable object. Bind the Command object to the DataGrid control. ❍ C. Delete the undesired columns from the DataTable object. ❍ D. Create a DataView object that retrieves only the desired columns from the DataTable object. Bind the DataGrid control to the DataView object.
332 Chapter 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 29 You have recently deployed an expense-reporting system in your company. The application relies heavily on its SQL Server database. All employees in the company have similar access permissions to the database. You have created the application in such a way that it uses an employee’s logon name and password in the connection string to connect to SQL Server. Users of the application are consistently reporting slow performance of the application. Your task is to optimize the performance of this application. You note that another application, which uses the same SQL Server database, is having good performance. Which of the following steps will you take? ❍ A. Compile the application to native code using ngen.exe. ❍ B. Run the SQL Server Index Tuning Wizard. ❍ C. Increase the maximum size of the connection pool in the connection string. ❍ D. Use the same connection string for all users.
Question 30 You are developing a .NET application named VerifyOrders. This application receives data from the Orders application in XML format. The VerifyOrders application enables its users to review the orders and make any changes if required. When the users are done reviewing the orders, the VerifyOrders application must create an output XML file, which is returned to the Orders application. The output XML file must contain the original values as well as the changed values. Which of the following options will you choose to create such an output XML file? ❍ A. Call the DataSet.WriteXmlSchema method and pass an XmlWriter object as a parameter. ❍ B. Call the DataSet.WriteXml method and set the value for XmlWriteMode parameter to IgnoreSchema. ❍ C. Call the DataSet.WriteXml method and set the value for XmlWriteMode parameter to WriteSchema. ❍ D. Call the DataSet.WriteXml method and set the value for XmlWriteMode parameter to DiffGram.
333 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#1.
Question 31 You are writing a Visual Basic .NET application that executes several stored procedures to update a SQL Server database. You use database transactions to ensure that either all updates to the database succeed or the changes are rolled back in case of an error. You used the following code segment to create the database connection and the transaction object in your program: Dim sqlConnection1 As SqlConnection = _ New SqlConnection(strConnString) sqlConnection1.Open() Dim sqlCommand1 As SqlCommand = New SqlCommand() Dim sqlTrans As SqlTransaction
You need to prevent other users from updating or inserting rows into the database until the transaction is complete. Which of the following statements enables you to fulfill this requirement? ❍ A. sqlTrans = sqlConnection1.BeginTransaction( _ IsolationLevel.ReadCommitted)
❍ B. sqlTrans = sqlConnection1.BeginTransaction( _ IsolationLevel.Serializable)
❍ C. sqlTrans = sqlCommand1.BeginTransaction( _ IsolationLevel.ReadCommitted)
❍ D. sqlTrans = sqlCommand1.BeginTransaction( _ IsolationLevel.Serializable)
Question 32 You are developing a .NET application that processes data from a SQL Server database. The application reads the data from the database in a forward-only way and does not perform any update operation. You use the System.Data.SqlClient.SqlConnection object to connect to the SQL Server database. You then use a System.Data.SqlClient.SqlCommand object to run a stored procedure and retrieve the results into a System.Data.SqlClient.SqlDataReader object. The data returned by the SqlCommand object consists of 1,000 rows and one column; the column is defined as nvarchar(20) in the database. You have written the following code to concatenate the column values of the returned result set into a string variable: Dim dr As SqlDataReader = cmd.ExecuteReader() Dim s As String
334 Chapter 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
While(dr.Read()) s = s & dr.GetValue(0) End While
What can you do to optimize the application? [Select two answers.] ❑ A. Replace the stored procedure with a SQL statement. ❑ B. Replace the SqlDataReader object with a DataSet object. ❑ C. Replace the While loop with a For Each loop. ❑ D. Replace the String variable with a StringBuilder object. ❑ E. Replace the GetValue method with the GetString method.
Question 33 Your application uses a SqlDataReader object to retrieve patient information from a medical records database. When you find a patient who is currently hospitalized, you wish to read the names of the patient’s caregivers from the same database. You have created a second SqlDataReader object, based on a second SqlCommand object, to retrieve the caregiver information. When you call the ExecuteReader method of the SqlCommand object, you get an error. What is the most likely cause of this error? ❍ A. You are using the same SqlConnection object for both the SqlDataReader objects and the first SqlDataReader is still open when you try to execute the SqlCommand. ❍ B. You must use a SqlDataAdapter object to retrieve the caregiver information. ❍ C. You must use the OleDbDataReader object instead of the SqlDataReader object to retrieve information. ❍ D. You are using the ExecuteReader method of the SqlCommand object, but you should be using the ExecuteScalar method instead.
Question 34 You are working with this XML file:
335 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#1.
Which XPath expressions can you use to return the second element from the first element? [Select two.] ❑ A. /Orders/Order[1]/Part[2] ❑ B. /Orders/Order[0]/Part[1] ❑ C. (/Orders/Order/Part)[2] ❑ D. (/Orders/Order/Part)[1]
Question 35 You use Visual Basic .NET to develop an application that will be used by the customer service department. Your application receives data from the Orders application. Users of your application get calls from the customers to make changes to their orders. You write the code that allows them to make the changes to the data, but now you want to write code that sends the changed records back to the Orders application. Which of the following methods should you use to accomplish this requirement? ❍ A. DataSet.Clone ❍ B. DataSet.Copy ❍ C. DataSet.GetChanges ❍ D. DataSet.Merge
Question 36 You are a .NET developer for a large warehousing company. You need to develop a Web application that helps users manage the inventory. Inventory data is stored on a SQL Server 2000 machine named WareHouse2 in a database named Inventory. You use a SqlConnection object and Windows integrated authentication to connect with the Inventory database. Which of the following connection strings should you choose in your Visual Basic .NET program? ❍ A. “Provider=SQLOLEDB;Data Source=WareHouse2; ➥Initial Catalog=Inventory; ➥Integrated Security=SSPI;”
❍ B. “Provider=SQLOLEDB;Data Source=WareHouse2; ➥Initial Catalog=Inventory; ➥User Id=sa;Password=Ti7uGf1;”
336 Chapter 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ❍ C. “Data Source=WareHouse2; ➥Initial Catalog=inventory; ➥Trusted_Connection=True;”
❍ D. “Data Source=WareHouse2;User Id=sa; ➥Password=Ti7uikGf1; ➥Initial Catalog=inventory;”
Question 37 You need to develop a database application that interacts with a Jet database. You need to write code to return the total number of customers from the database, and you need to create the fastest solution. Which of the following actions should you take? ❑ A. Write an ad hoc SQL query to return the total number of customers. ❑ B. Create a stored procedure to return the total number of customers. ❑ C. Use the OleDbCommand.ExecuteScalar method. ❑ D. Use the OleDbCommand.ExecuteReader method. ❑ E. Use the OleDbDataAdapter.Fill method.
Question 38 You are developing a .NET application that retrieves data from a SQL Server database to perform analysis of sales history. A large number of users will use your application. The size of the sales history data is huge and your application needs to retrieve this data at a very fast speed. Which of the following techniques would you use to get the maximum performance when retrieving data from the SQL Server database in your Visual Basic .NET application? ❍ A. Use the classes from the System.Data.OleDb namespace. ❍ B. Use the classes from the System.Data.SqlClient namespace. ❍ C. Use the XML Web Services to connect with the SQL Server database. ❍ D. Use COM components to retrieve the data from the SQL Server database.
337 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#1.
Question 39 Your OrderManager application allows users to enter new orders and make changes to the existing orders. The application involves a DataTable named OrdersTable. The column OrderNumber defines a primary key for OrdersTable. Which of the following segments of code should you use to define a primary key for OrdersTable in your Visual Basic .NET program? ❍ A. Dim c As DataColumn() = New DataColumn(1) c(0) = OrdersTable.Columns(“OrderNumber”) OrdersTable.PrimaryKey = c
❍ B. OrdersTable.PrimaryKey = “OrderNumber”
❍ C. OrdersTable.PrimaryKey.Add(OrdersTable.Columns (“OrderNumber”))
❍ D. OrdersTable.PrimaryKey = OrdersTable.Columns(“OrderNumber”)
Question 40 You are attempting to retrieve all orders placed on July 19, 1996 from a SQL Server database. You have written the following SQL statement: SELECT * FROM Orders WHERE OrderDate = 7/19/1996
The statement executes without error but does not return any rows. You are certain that the database contains orders from the specified date. How should you correct the SQL statement? ❍ A. SELECT * FROM Orders WHERE OrderDate = #7/19/1996#
❍ B. SELECT * FROM Orders WHERE OrderDate = July 19, 1996
❍ C. SELECT * FROM Orders WHERE OrderDate = ‘7/19/1996’
❍ D. SELECT * FROM Orders WHERE OrderDate = “7/19/1996”
338 Chapter 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 41 Your Visual Basic .NET application reads an XML file from disk into an XmlDocument object and then it modifies some of the nodes in the document. You need to write minimal code. Which object should you use to write the modified XmlDocument object back to disk? ❍ A. XmlTextWriter ❍ B. FileStream ❍ C. StreamWriter ❍ D. BinaryWriter ❍ E. TextWriter
Question 42 You are developing a .NET application for the purchasing department of your company. The department needs to view, add, edit, and delete the supplier information that is stored in a SQL Server database. You must make sure that when the user updates a supplier record, the information is successfully written to the database. Which of the following pair of method calls should you choose to update the database? ❍ A. DataTable.AcceptChanges() SqlDataAdapter.Update(DataTable)
❍ B. SqlDataAdapter.Update(DataTable) DataTable.AcceptChanges()
❍ C. DataTable.Reset() SqlDataAdapter.Update(DataTable)
❍ D. SqlDataAdapter.Update(DataTable) DataTable.Reset()
339 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#1.
Question 43 Your application needs to load the contents of an XML file into memory. You do not need rich navigation through the XML file; a single pass to locate the data of interest is sufficient for the application. You also want to minimize the use of server resources. Which class should you use to implement this requirement? ❍ A. XPathNavigator ❍ B. XmlReader ❍ C. XmlTextReader ❍ D. XPathExpression
Question 44 You use a SqlDataAdapter object to fill a DataSet object with the contents of the Parts table in your database. The part name of the first part is “Windshield.” You synchronize an XmlDataDocument object with the DataSet object. In the DataSet object, you change the part name of the first part to “Wipers.” After that, in the XmlDataDocument object, you change the value of the corresponding node to “Windshield fluid.” When you call the Update method of the SqlDataAdapter object, what is the effect? ❍ A. The part name in the table remains “Windshield.” ❍ B. The part name in the table is updated to “Wipers.” ❍ C. The part name in the table is updated to “Windshield fluid.” ❍ D. The CLR throws an exception because you’re trying to update the part name using the XmlDataDocument object.
Question 45 You are designing an application that will allow the user to read an XML file from the order’s system and convert the XML file into a HTML file using style sheet DisplayOrders.xsl. Which object should you use to implement this requirement? ❍ A. XPathNavigator ❍ B. XslTransform ❍ C. XmlSchema ❍ D. XmlNode
340 Chapter 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 46 You are developing a contact-management application using Visual Basic .NET. You use the methods of the Trace and Debug classes to log serious error messages encountered during program execution. You want to record all such errors in the Windows event log. You do not want any duplicate entries for error messages in the event log. In what ways can you add a listener to the Windows event log? [Select two.] ❑ A. Dim traceListener As EventLogTraceListener = _ New EventLogTraceListener(“CustomEventLog”) Trace.Listeners.Add(traceListener)
❑ B. Dim traceListener As EventLogTraceListener = _ New EventLogTraceListener(“CustomEventLog”) Trace.Listeners.Add(traceListener) Debug.Listeners.Add(traceListener)
❑ C. Dim traceListener As EventLogTraceListener = _ New EventLogTraceListener(“CustomEventLog”)
❑ D. Dim traceListener As EventLogTraceListener = _ New EventLogTraceListener(“CustomEventLog”) Debug.Listeners.Add(traceListener)
Question 47 You have developed an online shipment-tracking Visual Basic ASP.NET Web application. The ShipmentStatus.aspx page in your application is displaying an incorrect shipping status for shipments. You want to view the tracing information for the page. What should you do? ❍ A. Set the element in the Web.config configuration file of the application to this:
❍ B. Set the element in the Web.config configuration file of the application to this:
341 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#1. ❍ C. Set the element in the Web.config configuration file of the application to this:
❍ D. Set the Trace attribute in the Page directive of the ShipmentStatus.aspx page to this:
❍ E. Set the Trace attribute in the Page directive of the ShipmentStatus.aspx page to this:
Question 48 You use Visual Basic .NET to develop a component that allows developers to create bar graphs in their applications. You name the component BarGraph. The developers need to deploy the BarGraph component with each application that uses the component. How should you package the BarGraph component for deployment? ❍ A. Use a Cab project to package the BarGraph component. ❍ B. Use a Setup project to package the BarGraph component. ❍ C. Use a Web Setup project to package the BarGraph component. ❍ D. Use a Merge Module project to package the BarGraph component.
Question 49 You have created a database-driven Web application. Using Microsoft SQL Server, you have also generated an installation script for your database. This script is stored in a file named InstData.sql. You create a Web Setup project using Visual Studio .NET to deploy this application on your production Web server. Which of the following editors should you choose to create the database when deploying your application on the client’s machine? ❍ A. Custom Actions Editor ❍ B. Launch Conditions Editor ❍ C. File System Editor ❍ D. User Interface Editor
342 Chapter 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 50 Your ASP.NET application contains this setting in the Web.config file:
You are allowing only digest or Windows integrated authentication in IIS. ASP.NET is running under the SYSTEM account. What identity will ASP.NET use to authorize resources if a user with the Windows account Shirley in the CORP domain logs in via digest authentication? ❍ A. CORP\Shirley ❍ B. ASPNET ❍ C. SYSTEM ❍ D. IUSR_Shirley ❍ E. CORP\Auditing
Question 51 You create a serviced component named Books that is activated as a server application. This component is stored in the Books.dll assembly and is registered in the COM+ catalog. You need to debug the GetBooksList method of the serviced component. What should you do? ❍ A. Open the Books solution. Set a breakpoint on the GetBooksList method. Start the debugger. ❍ B. Open the solution for the client program. Set a breakpoint on the statement that calls the Books.GetBooksList method. Start debugging the client program. ❍ C. Attach the debugger to the Books.dll process. Set a breakpoint on the GetBooksList method. ❍ D. Attach the debugger to the dllhost.exe process. Set a breakpoint on the GetBooksList method.
Question 52 You’ve developed a Visual Studio .NET application that helps the shipping department in creating mix-and-match pallets. Users of the application complain that the numbers of cases in the pallet are not displayed correctly. To find the location of the error, you place a breakpoint on the GetCasesInPallet method.
343 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#1.
However, when you execute the program from the Visual Studio .NET environment, the execution does not break at the breakpoint. Which of the following actions should you take to resolve this problem? ❍ A. Select Exceptions from the Debug menu. ❍ B. Select Enable All Breakpoints from the Debug menu. ❍ C. Select Build, Configuration Manager and set the project’s configuration to Debug. ❍ D. Select Build, Configuration Manager and set the project’s configuration to Release.
Question 53 You are debugging your ASP.NET Web application; you are concerned about the amount of time it’s taking to render a particular page. Which class can you use to obtain detailed timing information for the events on the page as it is rendered by the ASP.NET engine? ❍ A. System.Diagnostics.Trace ❍ B. System.Diagnostics.Debug ❍ C. System.Web.TraceContext ❍ D. System.Web.UI.Page
Question 54 Your application contains this code: Dim el As New EventLog() el.Source = “MyLog” el.WriteEntry(“MyLog”, _ “Message”, _ EventLogEntryType.Error)
You have not called EventLog.CreateEventSource(“MyLog”) anywhere in your application, and the MyLog event log does not already exist. What happens when you execute this code? ❍ A. A runtime error occurs. ❍ B. The message is written to the MyLog event log. ❍ C. The message is displayed in a message box. ❍ D. The message is written to the Application event log.
344 Chapter 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 55 You have developed a remoting component that helps manage production schedules for a manufacturing company. The component is packaged as Production.dll. One of your applications uses this component, and you anticipate that in the future, some other applications may use classes from the Production.dll library. You may also need to maintain multiple versions of Production.dll. Which of the following options should you choose to deploy Production.dll? [Select all that apply.] ❑ A. Sign Production.dll with sn.exe. ❑ B. Sign Production.dll with signcode.exe. ❑ C. Install Production.dll in the Windows system directory. ❑ D. Install Production.dll in the application’s bin directory. ❑ E. Install Production.dll in the Global Assembly Cache.
Question 56 You are a programmer for a popular gaming software publishing company. The company has recently designed a series of games using the .NET Framework. All these new game applications share some components. Some of these components are shipped in the box with the application and others are deployed over the Internet. Which of the following commands will you use for these components before packaging it for deployment? ❍ A. Use sn.exe to sign your components. ❍ B. Use signcode.exe to sign your components. ❍ C. Use sn.exe followed by signcode.exe to sign your components. ❍ D. Use signcode.exe followed by sn.exe to sign your components.
Question 57 You develop a Windows-based application using Visual Basic .NET. Your code would like File I/O permission but can run without this permission. You plan to request the permission and trap the error if it is not granted. Which SecurityAction action should you use with the FileIOPermission object? ❍ A. SecurityAction.RequestMinimum ❍ B. SecurityAction.Demand ❍ C. SecurityAction.RequestOptional ❍ D. SecurityAction.RequestRefuse
345 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#1.
Question 58 You would like to give target Web servers the ability to customize your application. In particular, you want to let them specify the file path where the output files need to be placed. You want to write minimal code. How should you add this capability to your application? ❍ A. Let the users edit the text in the Registry and use the Microsoft.Win32.Registry class to retrieve the value that they save. ❍ B. Add another customconfiguration.xml file to store the output file path for the application. ❍ C. Add an element to the application configuration file, Web.config, to store the output file path for the application. ❍ D. Add an element to the element of the application configuration file, Web.config, to store the output file path for the application.
Question 59 Your ASP.NET application requires users to be authenticated with a strong identity. You must allow users with any version browser (4.x or better), and you want passwords to cross the network only with secure encryption. Which authentication should you use? ❍ A. Passport authentication with anonymous IIS authentication ❍ B. Windows authentication with Basic IIS authentication ❍ C. Windows authentication with digest IIS authentication ❍ D. Windows authentication with integrated IIS authentication
Question 60 You have developed an intranet ASP.NET application for your company that uses Microsoft Windows authentication to authenticate the users of the application. Once an employee is authenticated, he can access all the Web pages of the intranet application. However, your application has an Accounting directory that contains details of the salaries and pay checks of the employees. You want only users of the Accounting role to access the pages in this directory. Which of the following pieces of code should you write in the Web.config file of your application? [Select all that apply.]
346 Chapter 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ❑ A. Add the following element in the Web.config file of the application directory:
❑ B. Add the following element in the Web.config file of the application directory:
❑ C. Add the following element in the Web.config file of the Accounting directory:
❑ D. Add the following element in the Web.config file of the Accounting directory:
Question 61 Which of these tasks requires you to use imperative security rather than declarative security? ❍ A. Refusing dangerous permissions such as Registry permission ❍ B. Ensuring that your application has access to an environment variable whose name is not known until runtime ❍ C. Ensuring that your application has access to a specific file whose name is known at design time ❍ D. Ensuring that your application has access to a Jet database as a specific user.
347 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#1.
Question 62 You use Visual Basic .NET to develop a remoting component called MortgageInterest that is packaged in MortgageInterest.dll version 1.0.0.0. MortgageInterest.dll is deployed into the GAC of the production server. After two months, you discover a bug in the assembly. You fix the bug by releasing a new version, 1.0.1.0, of the assembly. You place the newly created assembly in the GAC. What will happen to the applications that use MortgageInterest.dll? ❍ A. The applications using the MortgageInterest.dll assembly will break because the applications will notice two versions of the assembly in the GAC and won’t know which one to execute. ❍ B. The applications using the MortgageInterest.dll assembly will notice a new version of the assembly and will load the new version of the assembly and cause no problems. ❍ C. The applications using the MortgageInterest.dll assembly will not bother about the new version of the assembly in the GAC and will continue to use the older, buggy version of the assembly. ❍ D. The applications using the MortgageInterest.dll assembly will be requested to select the desired assembly version to run for their application.
Question 63 You have developed a remoting assembly named RemoteServices that is a member of code groups as follows: ➤ At the Enterprise level, the RemoteServices assembly is a member of All Code group that has the FullTrust permission set. ➤ At the Machine level, the RemoteServices assembly is a member of All Code group and Sensitive code group. The All Code group has the LocalIntranet permission set, and the Sensitive code group has the Nothing permission set. ➤ At the User level, the RemoteServices assembly is a member of Internet code group, which has the Internet permission set. What permission set will the CLR assign to the RemoteServices assembly? ❍ A. Nothing ❍ B. Internet ❍ C. LocalIntranet ❍ D. FullTrust
348 Chapter 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 64 You have used Visual Basic .NET to build a Windows service to implement a custom networking protocol. Which tool can you use to install the Windows service for testing your program? ❍ A. xcopy ❍ B. Services MMC snap-in ❍ C. gacutil ❍ D. installutil
Question 65 In your company’s monthly meeting, you have been assigned to increase the security in the organization so that malicious code cannot be executed. You have been asked to implement a security policy that allows users to execute applications locally and from the company’s intranet, but users should not be allowed to execute code originating from the Internet. You want to complete this task with minimal effort. Which of the following actions should you take? ❍ A. Modify the enterprise security policy. ❍ B. Modify the machine security policy. ❍ C. Modify the user security policy. ❍ D. Modify the application domain security policy.
14 Answer Key for Practice Exam #1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Answer Key 1. A
17. A
33. A
2. A and D
18. B
34. A and C
3. B and C
19. A
35. C
4. A
20. D
36. C
5. B
21. A
37. B and C
6. D
22. C and D
38. B
7. B
23. B
39. A
8. B
24. C
40. C
9. C
25. B
41. A
10. A
26. A and B
42. B
11. A
27. A, B, and E
43. C
12. C
28. D
44. C
13. A
29. D
45. B
14. B and D
30. D
46. A and D
15. C and D
31. B
47. D
16. C
32. D and E
48. D
350 Chapter 14 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49. A
55. A and E
61. B
50. E
56. C
62. C
51. D
57. C
63. B
52. C
58. D
64. D
53. C
59. A
65. A
54. B
60. A and C
Detailed Answers Question 1 Answer A is correct. With a Singleton SAO, state is persisted, but all clients of the object share the same state. With a CAO, each client can persist its own state, which avoids the problem with clients sharing state. Answer B is incorrect because with a SingleCall SAO, state is not persisted. Answer C is incorrect because you can use any backend to store the data; you should take care to instantiate the remote object in the correct activation mode. Answer D is incorrect because if the object is activated in Singleton mode, all the client requests are serviced by that instance.
Question 2 Answers A and D are correct. Shared and Private members are not available remotely. Therefore, EmployeeName (a Private field) and DepartmentName (a Shared field) cannot participate in remoting. Only nonshared public members (methods, properties, and fields) can participate in remoting, thus making answers B and C incorrect.
Question 3 Answers B and C are correct. The Serializable attribute indicates that the class containing this attribute can be serialized. If you do not want any field of the class to be serialized, you must apply the NonSerialized attribute to that field of the class. Answer A is incorrect because the Serializable attribute is applied
351 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Answer . . . . .Key . . for . .Practice . . . . Exam . . . .#1.
to a class rather than a field in the class. Answer D is incorrect because the Product class does not want to provide its own serialization code.
Question 4 Answer A is correct. When you use IIS to host a remotable class, the full spectrum of IIS authentication and authorization methods are available to the remoting infrastructure. Answer B, C, and D are incorrect because these solutions require you to write additional code to create the security infrastructure.
Question 5 Answer B is correct. By deriving a class from the System.MarshalByRefObject class, you enable the class to be accessed as a remote object. Answer A is incorrect because marking the class with the Serializable attribute does not cause the resulting class to be instantiated as a marshal-by-reference object. Answer C and D are incorrect because implementing the ISerializable or IActivator interface does not allow the object to be activated as a remote object.
Question 6 Answer D is correct. The Configure() method of the RemotingConfiguration class loads the configuration file into memory, parses its contents to locate the section, and based on the settings, calls the relevant methods to register the channels and the remoting objects. Answers A, B, and C are incorrect because these methods are used to create instances of remote objects.
Question 7 Answer B is correct. In this program, although your coworker has created an instance of the TcpServerChannel and HttpServerChannel objects, she hasn’t yet registered them with the remoting framework. The channels should be registered by using the RegisterChannel method of the ChannelServices class. Answer A is incorrect because more than one channel can be registered with the remoting system on the server. Answer C is incorrect because the HttpServerChannel and TcpServerChannel objects can be
352 Chapter 14 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
used to register the channels with the remoting system on the server. HttpChannel and TcpChannel provide the functionality of both server and client channels. Answer D is incorrect because only one channel can be registered to listen on one port.
Question 8 Answer B is correct. The Disco (.disco) file is the only one that contains pointers to non-XML resources. Answer A is incorrect because the results.discomap file shows you the name of the WSDL file and the URL from which its contents were retrieved. Answer C is incorrect because the Reference.vb file is the proxy class that defines the proxy objects to be used with the Web service. Answer D is incorrect because the OrderTracker.wsdl file is an XML file that contains information about the Web service’s interface.
Question 9 Answer C is correct. Using an asynchronous call to invoke a Web Service allows other code in your application to execute while you are waiting for the Web service to return results. When the results are ready, the asynchronous call can invoke a callback method to make them available. Answers A and B are incorrect because these options will still run the Web service synchronously, blocking the application to run any other code until the Web method is executed. Answer D is incorrect because generating the proxy by adding a Web reference will not make the Web method execute asynchronously. Answer E is incorrect because the proxy option is used to specify the URL of the proxy server and will have no impact on making the Web method execute asynchronously.
Question 10 Answer A is correct. The Web Services Discovery tool retrieves copies of the files you need in order to know more information about the Web service. Answer B is incorrect because this action will only display the test page of the Web service; it will not provide any WSDL information or documentation information about the Web service. Answer C is incorrect because the XML Schema Definition tool can be used to generate an XML schema or class file from the source, but it will not provide any information on the URL of the
353 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Answer . . . . .Key . . for . .Practice . . . . Exam . . . .#1.
ASMX file. Answer D is incorrect because you want the details to invoke the Web service from the client and not add the Web service to the client.
Question 11 Answer A is correct. Setting the BufferResponse property to False sends the data in chunks so that the client processes will not time out while waiting for the data. Answer B and C are incorrect because the CacheDuration property specifies how long the response will be cached for succeeding calls, and it doesn’t have any effect on a single call to the method. Answer D is incorrect because the session state does not need to be enabled unless you require the Web service to be stateful.
Question 12 Answer C is correct. SOAP extensions are activated by applying the corresponding attribute to the Web method proxy that you want to intercept. Answers A, B, and D are incorrect because the btnGetData_Click and GetInitializer methods and the Load event are not Web methods.
Question 13 Answer A is correct. SOAP extensions execute in order from lowest priority to highest priority. Because your SOAP extension needs to work with the XML data, it must be invoked in the BeforeDeserialize event rather than in the AfterDeserialize event. Answer B is incorrect because if you set a lower priority for the new SOAP extension, it would not be able to access the decrypted attributes. Answer C and D are incorrect because the AfterDeserialize event occurs when the XML has been converted back to native objects.
Question 14 Answers B and D are correct. You can use either of these options to generate proxy classes for use in a client application. Answer A is incorrect because the .NET WebService Studio tool is used to invoke a Web service for testing. Answer C is incorrect because the Web Services Discovery tool can locate files related to a Web service, but it does not generate any proxy classes.
354 Chapter 14 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 15 Answers C and D are correct. You need to wait after executing the code until both asynchronous calls complete. Therefore, you should call the WaitHandle.WaitAll method to wait for both asynchronous calls to complete. You can also make two calls to the WaitHandle.WaitOne method to wait for both Web methods to complete. Answer A is incorrect because you can’t use delegates—they won’t pause the code at a specified point. Answer B is incorrect because the WaitHandle.WaitAny method is used to coordinate two or more methods and proceed when any one of them completes.
Question 16 Answer C is correct. XML Web services act as a root object in a transaction due to the stateless nature of the HTTP protocol. Therefore, the transactions in the ValidateCreditCard and RecordSales Web methods are committed irrespective of the TransactionOption attribute in the Books serviced component. The ProcessSale method throws an exception and hence the transaction in the method is rolled back. Therefore, this behavior makes answers A, B, and D incorrect.
Question 17 Answer A is correct. The LocalSystem value defines a highly privileged account. Answers B and C are incorrect because the LocalService and NetworkService values provide a lower privilege level for the security context. Answer D is incorrect because the privileges for the User value depend on the specified username and password.
Question 18 Answer B is correct. When a Windows service is started, any startup parameters are passed to the OnStart method, thus making answers A, C, and D incorrect.
355 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Answer . . . . .Key . . for . .Practice . . . . Exam . . . .#1.
Question 19 Answer A is correct. You should use the event log for error reporting from a Windows service. Event logs are easy to use for administrators because they already use event logs for monitoring notifications from other applications. The service base class provides an EventLog property that allows you to use a single line of code to write messages to the Application event log. Answers B, C, and D are incorrect because they would involve writing more code.
Question 20 Answer D is correct. The ClassInterface attribute specifies how the interfaces will be generated for a class. To define your own interfaces, you must explicitly set the ClassInterface attribute to None. Answers A and B are incorrect because, by default, the value of the ClassInterface attribute is AutoDispatch, which generates a late-bound interface. Answer C is incorrect because it generates both late-bound and early-bound interfaces.
Question 21 Answer A is correct. When you check the Activate Component Events and Statistics option within the Component Services administrative tool, you can monitor a variety of statistics on pooled components, including the number of objects in the pool, the number currently activated, and the number of objects currently executing a client request. Answers B, C, and D are incorrect because they involve extra efforts.
Question 22 Answers C and D are correct. For achieving maximum performance, you can use COM+ object pooling and just-in-time activation services. Answer A is incorrect because asynchronous processing of the application is not the requirement. Answer B is incorrect because the question does not require you to maintain transactions across components.
356 Chapter 14 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 23 Answer B is correct. The Construct method of a serviced component enables you to retrieve data entered in the Component Services administration tool. Therefore, you should override the Construct method to receive the connection string specified by the administrator. Answer A is incorrect because the Activate method is invoked whenever a method is invoked if just-in-time activation is enabled for the component. Answer C is incorrect because the custom method defined cannot be invoked automatically like the Construct method. Answer D is incorrect because serviced components cannot have nondefault constructors.
Question 24 Answer C is correct. You should change the Isolation property of the Transaction attribute to IsolationLevel.RepeatableRead. This isolation level will place a type of lock that protects dirty reads and allows new rows to be inserted but prevents other users from updating the data. Answers A and B are incorrect because these options allow dirty reads. Answer D is incorrect because this option will prevent users from inserting new rows.
Question 25 Answer B is correct. Using the Type Library Importer tool (tlbimp.exe) enables you to generate a signed RCW assembly. To place the RCW assembly in the GAC, so that it can be shared by all projects on the computer, you need to use the gacutil.exe tool. Answers A and E are incorrect because you need to use the component in more than one project. Answer C is incorrect because you also need to sign the RCW assembly while generating it from the Type Library Importer tool. Answer D is incorrect because a Primary Interop Assembly is for code from other vendors, not for your own code.
Question 26 Answers A and B are correct. Among the given choices, you would use the Type Library Importer tool when you must call a COM component that you wrote from Visual Basic .NET code and when you must produce a strongnamed assembly that calls methods from one of your company’s COM components. Answer C is incorrect because you should not use tlbimp on code
357 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Answer . . . . .Key . . for . .Practice . . . . Exam . . . .#1.
from another vendor. Rather, you should go to that vendor to get the Primary Interop Assembly (PIA) for the COM library that you wish to call. Answer D is incorrect because tlbimp is not necessary for calling Windows API functions. You can use Platform Invoke to call functions from Win32 API.
Question 27 Answers A, B, and E are correct. Because multiple applications are using this assembly, you need to install the assembly in the GAC. To install the assembly into the GAC, you also need to sign the assembly with a strong name. Finally, to enable COM applications to use the assembly, you need to register the assembly in the Windows Registry. Answer C is incorrect because COM applications that use the components are already compiled and they do not require type libraries to support early binding. Answer D is incorrect because you do not need to use a COM DLL in a .NET application. Answer F is incorrect because shared assemblies should be deployed in the GAC. When an assembly is registered in the Windows Registry, COM applications are able to locate shared assemblies from the GAC.
Question 28 Answer D is correct. The DataView object represents a data-bindable, customized view of a DataTable, which is optimized for sorting, filtering, searching, editing, and navigation. Answers A and C are incorrect because they would involve additional programming. Answer B is incorrect because it will impact SQL Server database with additional hits.
Question 29 Answer D is correct. Using the same connection string enables ADO.NET to reuse existing pooled database connections instead of creating new ones. This improves performance because creating new database connections is a costly operation. Answer A is incorrect because users are facing slow performance consistently and not just during the first execution. Answer B is incorrect because another application that uses the same database is already performing well. Answer C is incorrect because if different connection strings are used, each request for the connection will create a new connection pool. Therefore, increasing the maximum size of the pool will not matter.
358 Chapter 14 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 30 Answer D is correct. When you set the XmlWriteMode parameter of the DataSet.WriteXml method to DiffGram, the output contains both the original and current values. Answer A is incorrect because the DataSet.WriteXmlSchema method writes the DataSet structure as an XML schema instead of writing XML data. Answers B and C are incorrect because setting the XmlWriteMode parameter to IgnoreSchema or WriteSchema writes only the current value of the data to the XML file.
Question 31 Answer B is correct. IsolationLevel.Serializable places a range lock on the database, preventing other users from updating or inserting rows into the database until the transaction is complete. Answer A is incorrect because IsolationLevel.ReadCommitted holds lock while the data is being read, but data can be changed before the transaction is complete. Answers C and D are incorrect because the BeginTransaction method should be called on the SqlConnection object rather than the SqlCommand object.
Question 32 Answers D and E are correct. Strings in Visual Basic .NET are immutable, so concatenating multiple values into a string requires deleting and re-creating the string many times. The StringBuilder object is optimized for changing textual data. The GetString method should be used rather than the GetValue method to retrieve data because the typed methods are faster than the GetValue method. Answer A is incorrect because stored procedures have much higher performance as compared to SQL statements. Answer B is incorrect because for a forward-only, read-only operation, the SqlDataReader object provides the best performance. Answer C is incorrect because a While loop provides better performance when compared to the For Each loop.
Question 33 Answer A is correct. You can only have a single SqlDataReader object open on a single SqlConnection object. If you need a second SqlDataReader
359 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Answer . . . . .Key . . for . .Practice . . . . Exam . . . .#1.
object, you’ll need to open a second SqlConnection object. Answers B and C are incorrect because these options suggest an alternative approach rather than pointing to the cause of the error. Answer D is incorrect because you wish to retrieve multiple values from the database, and the ExecuteScalar method only retrieves the first column of the first row in the result set.
Question 34 Answers A and C are correct. XPath node numbering is 1-based, not 0-based. The expression /Orders/Order[1]/Part[2] explicitly selects the second element under the first element. The expression (/Orders/Order/Part)[2] selects the second element in the entire file, which happens to be under the first element in this case. The parentheses are necessary because the square bracket operator normally takes precedence over the path operators. Answer B and D are incorrect because XML nodes in XPath expressions are based on 1 instead of 0.
Question 35 Answer C is correct. Calling the GetChanges method of a DataSet returns a new DataSet that contains only records that have been changed. Answer A is incorrect because the DataSet.Clone method copies the structure of the DataSet but does not copy any data. Answer B is incorrect because the DataSet.Copy method copies all the data instead of only the changed data. Answer D is incorrect because you do not want to merge two DataSet objects.
Question 36 Answer C is correct. To create a connection string for a SqlConnection object that uses Windows integrated authentication, you need to specify the data source and the initial catalog, as well as indicate that the connection is secure. You can indicate a connection is secure by setting the Trusted_Connection or Integrated Security parameter to True or sspi, respectively. Answers A and B are incorrect because you do not specify the provider in the connection string when connecting through the SqlConnection object. Answer D is incorrect because you need to use Windows authentication instead of SQL Server authentication.
360 Chapter 14 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 37 Answers B and C are correct. To return a single value from the database, you should use the ExecuteScalar method of the OleDbCommand object. The ExecuteScalar method executes the query and retrieves the first column of the first row of the resultset. You should always prefer to use stored procedures rather than the ad hoc SQL statements for speedy delivery. Answer A is incorrect because it uses a SQL query rather than the stored procedure. Answers D and E are incorrect because these solutions involve extra overhead when only a single value needs to be returned from the database.
Question 38 Answer B is correct. The classes in the System.Data.SqlClient namespace provide the best performance when working with SQL Server data because these classes can communicate with the SQL Server database directly using the SQL Server tabular data stream (TDS) packets. Answer A is incorrect because the classes in the System.Data.OleDb namespace call a set of COM components (an OLE DB provider), which constructs the TDS packets to communicate with the SQL Server. Answer C is incorrect because XML Web services will have a lot of additional overhead when compared to a direct connection to the SQL Server database. Answer D is incorrect because calling COM components will involve an extra COM-Interop layer and will slow down the operation.
Question 39 Answer A is correct. The PrimaryKey property of the DataTable object specifies an array of column(s) that functions as the primary keys for the data table. Answer B is incorrect because the data type of the PrimaryKey property is not String. Answer C is incorrect because the PrimaryKey property accepts an array of DataColumn objects that does not provide any Add method. Answer D is incorrect because even if the primary key is a single column, an array of DataColumn(s) must be used with the PrimaryKey property.
Question 40 Answer C is correct. SQL Server uses single quotes to delimit date values. The reason the original SQL did not return an error was that SQL Server
361 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Answer . . . . .Key . . for . .Practice . . . . Exam . . . .#1.
treated the date as a mathematical operation involving two divisions, and it silently converted the result into a date. Therefore, answers A, B, and D are simply incorrect.
Question 41 Answer A is correct. The XmlTextWriter object is specially designed to write XML files. Answers B, C, D, and E are incorrect because when you use these objects, you’ll have to write additional code for writing the XML structure.
Question 42 Answer B is correct. When an application calls the Update method, the SqlDataAdapter object examines the RowState property and executes the required InsertCommand, UpdateCommand, or DeleteCommand statements iteratively for each row of the data. After the changes are written to the database, you need to call the DataTable.AcceptChanges method to remove the deleted rows and then set the RowState property of the added and modified rows to Unchanged. Answer A is incorrect because if you first call the AcceptChanges method, the RowState for all the added and modified rows will be marked Unchanged and all the deleted rows will be removed. Later, when you call the Update method, the SqlDataAdapter object will not be able to update the database because the RowState property of the rows will be Unchanged. Answers C and D are incorrect because the Reset method restores the DataTable to its original state, and the updates made to the table are lost in the DataTable object.
Question 43 Answer C is correct. The XmlTextReader class is optimized for forwardonly, read-only processing of an XML file. Answer A is incorrect because though XPathNavigator provides you with read-only, random access to XML documents, it loads the entire DOM representation of the XML document into memory. Answer B is incorrect because you cannot use the XmlReader class directly in an actual implementation because the XmlReader class is an abstract class. Answer D is incorrect because an XPathExpression class represents a precompiled XPath expression rather than the XML document.
362 Chapter 14 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 44 Answer C is correct. The DataSet object and the XmlDataDocument object are two views of the same data in memory. The last change you make to this data will be saved, regardless of which object you used to make the change. Therefore, answers A and B are incorrect. Answer D is incorrect because you can use an XmlDataDocument object to update XML data.
Question 45 Answer B is correct. You should use the XslTransform object to transform XML data using an XSLT style sheet. Answer A is incorrect because the XPathNavigator object enables you to explore the structure of the XML file. Answer C is incorrect because the XmlSchema object provides the schema definition. Answer D is incorrect because the XmlNode object represents a single node in the document.
Question 46 Answers A and D are correct. The Debug and Trace classes share the same Listeners collection. Therefore, you should add a listener object either to the Trace.Listeners collection or to the Debug.Listeners collection. Answer B is incorrect because this solution will generate double entries in the event log. Answer C is incorrect because the newly created listener object is not attached to the Listeners collection of the Trace and Debug classes.
Question 47 Answer D is correct. To enable tracing for a particular page, you should set the Trace attribute of the Page directive to True. Answers A and B are incorrect because the element in the Web.config file enables or disables tracing for all the Web pages of the application rather than just a single page. Answer C is incorrect because the enabled attribute takes a Boolean value rather than the name of the Web page. Answer E is incorrect because it disables tracing for the Web page.
363 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Answer . . . . .Key . . for . .Practice . . . . Exam . . . .#1.
Question 48 Answer D is correct. Merge Module projects allow you to create reusable setup components by packaging all the required files, resources, Registry entries, and setup logic necessary to install a component. Answer A is incorrect because a Cab project creates a cabinet file for downloading from a Web browser. Answer B is incorrect because a Setup project creates an installer for a Web application. Answer C is incorrect because a Web Setup project creates an installer for a Web application.
Question 49 Answer A is correct. You can use the Custom Actions Editor to take custom actions such as installing a database during application setup. If you have an installer class or program that can create a database, you must override the Install method of the base class and you must add the installer program to the Install node of the Custom Actions Editor. Answer B is incorrect because the Launch Conditions Editor is used to specify the prerequisite conditions that must be met in order to successfully run an installation; it cannot be used to execute custom actions. Answer C is incorrect because the File System Editor only provides a mapping of the file system on the target machine and allows you to place files or folders at specific locations on the target machine. However, the File System Editor cannot be used to execute code to create the database. Answer D is incorrect because the User Interface Editor allows you to customize the user interface displayed during the installation process.
Question 50 Answer E is correct. When you enable impersonation, providing a name and password for impersonation, any authenticated user takes on the credentials of the specified account for the purposes of authorizing resources. Answer A is incorrect because the name and password that ASP.NET will use to authorize resources is already defined by the element. Answers B and C are incorrect because impersonation is not disabled for the application. Answer D is incorrect because the IUSR_Shirley account, the identity of the IIS, will be used by ASP.NET to make requests if the application allows anonymous access.
364 Chapter 14 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 51 Answer D is correct. To debug a serviced component that is a server application, you should place breakpoints in the serviced component code and attach a debugger to the dllhost.exe process in which the desired serviced component is running. Answer A is incorrect because you need to execute serviced component code by running the client application. Answer B is incorrect because setting a breakpoint in the client code debugs only the client application; it does not step into the code of the serviced component. Answer C is incorrect because if the serviced component is a server application, the serviced component runs in a separate process called dllhost.exe.
Question 52 Answer C is correct. Breakpoints are invoked only when the project’s configuration is in Debug mode. Answer A is incorrect because the Exceptions dialog box is used to configure the breakpoint only in the case of an exception. Answer B is incorrect because when you place a breakpoint, it is enabled by default. Answer D is incorrect because the project’s configuration should be Debug instead of Release for debugging to occur (breakpoints to be executed).
Question 53 Answer C is correct. The TraceContext class is responsible for providing detailed timing and other information in the browser window when you activate ASP.NET tracing. Answers A and B are incorrect because the Debug and Trace classes can be used to display messages about a program’s execution, but these classes do not provide timing information. Answer D is incorrect because the Page class cannot provide timing information for the events on the Web page.
Question 54 Answer B is correct. If you attempt to write an event log entry to a log that you have not yet created, the .NET Framework automatically creates the appropriate source. Calling the CreateEventSource method is optional, thus making answers A, C, and D incorrect.
365 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Answer . . . . .Key . . for . .Practice . . . . Exam . . . .#1.
Question 55 Answers A and E are correct. You need to sign a shared assembly with the strong name and then install the assembly in the Global Assembly Cache. Answer B is incorrect because you use sn.exe instead of signcode.exe to sign an assembly with a strong name. Answer C is incorrect because the Windows system directory does not allow multiple versions of an assembly to be maintained. Answer D is incorrect because an assembly that needs to be shared by multiple applications should be stored in a common place such as the GAC rather than the bin directory of the Web application. Further, multiple versions of the assembly can only be placed in the GAC.
Question 56 Answer C is correct. Because the components are being used between several games published by your company, they are good candidates to be placed in the Global Assembly Cache of the target machine. However, before a component can be placed in the GAC, it must be signed using the Strong Name Tool (sn.exe). Your company is also deploying software over the Internet; in this case, it is a good idea to digitally sign your code with a software publisher’s certificate obtained by a respected certification authority. Once you obtain the certificate, you can use signcode.exe to sign your component. When you are using both sn.exe and signcode.exe with your assembly, you must always use sn.exe before using signcode.exe. Answers A and B are incorrect because you need to use both these tools instead of just one of them. Answer D is incorrect because sn.exe must be used before signcode.exe.
Question 57 Answer C is correct. The SecurityAction.RequestOptional action is used to request additional permissions that are optional. Answer A is incorrect because SecurityAction.RequestMinimum requests the minimum permissions required for code to run. Answer B is incorrect because SecurityAction.Demand requires all callers higher in the call stack to have been granted the permission specified by the current permission object. Answer D is incorrect because SecurityAction.RequestRefuse is used to refuse those requests that might be misused.
366 Chapter 14 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 58 Answer D is correct. You can store your custom settings in the element of the application configuration file. The .NET Framework provides the AppSettings property of the System.Configuration.ConfigurationSettings class to access the value of the custom key added to the element. Answer A is incorrect because asking the users to modify the Windows Registry may have undesirable effects. Answer B and C are incorrect because they would involve writing additional code.
Question 59 Answer A is correct. Passport authentication enables users to be authenticated with a strong identity using any browser or version. Answer B is incorrect because Basic IIS authentication does not securely encrypt passwords. Answers C and D are incorrect because Digest and Windows integrated authentication require Internet Explorer as the browser.
Question 60 Answers A and C are correct. You should deny all unauthenticated users with the ? wildcard character at the application level such that only authenticated users can access the application. In the Web.config file of the Accounting directory, you should allow only members of the Accounting role and deny all other users (authenticated as well as unauthenticated) with the * wildcard character. Answer B is incorrect because you should disallow all unauthenticated users. The roles attribute should not contain wildcard characters; it should contain only the names of the Windows roles separated by commas. Answer D is incorrect because the element denies only unauthenticated users and provides access to the authenticated users.
Question 61 Answer B is correct. Declarative code access security can handle only scenarios where you know the details at design time. If the security requirements are finalized at runtime, you must use imperative security. Answers A, C, and D are incorrect because the details for verifying security are known at design time.
367 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Answer . . . . .Key . . for . .Practice . . . . Exam . . . .#1.
Question 62 Answer C is correct. The applications always bind to the assemblies with which they are compiled. If you want to execute a new version of the assembly, then the applications either should recompile the application with the new version of the assembly or should modify the application configuration file to redirect to a new version of the assembly. Therefore, answers A, B, and D are incorrect.
Question 63 Answer B is correct. RemoteServices assembly is a member of code groups that belong to three different levels: Enterprise, Machine, and User. Within a level, the permission set granted to an assembly is the union of all the permission sets of code groups to which the assembly belongs. Therefore, at the Enterprise level, the RemoteServices assembly gets the FullTrust permission set; at the Machine level, the RemoteServices assembly gets the LocalIntranet (union of LocalIntranet and Nothing) permission set; and at the User level, the RemoteServices assembly gets the Internet permission set. Across levels, the permission set granted to an assembly is the intersection of all the permission sets of the levels. Therefore, as the intersection of the FullTrust, LocalIntranet, and Internet permission sets, the Internet permission set is assigned to the assembly, thus making answers A, C, and D incorrect.
Question 64 Answer D is correct. Installing a Windows service requires communicating with the Service Control Manager (SCM). Of the listed tools, only installutil can communicate with the SCM to install a new service. Therefore, answers A, B, and C are incorrect.
Question 65 Answer A is correct. The enterprise security policy affects every computer and user on the network. Answer B is incorrect because this option will require modifying the machine security policy for each machine in the company. Answer C is incorrect because the user security policy only applies to a single logon account. Answer D is incorrect because security policy at the application domain level cannot be administered.
15 Practice Exam #2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
370 Chapter 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 1 You are designing a distributed application for your customers to track their online orders with your company. Thousands of customers will heavily use the application. For greater scalability, you need to make sure the application can be deployed in a load-balanced configuration. How should you host the remotable object in this scenario? ❍ A. As a server-activated object in Singleton activation mode ❍ B. As a server-activated object in SingleCall activation mode ❍ C. As a client-activated object that uses the HTTP channel ❍ D. As a client-activated object that uses the TCP channel
Question 2 You are building a .NET Remoting server that will make an object named Product available to client applications. The client applications are built in .NET, and they include the class file for the Product object. Unfortunately, some of the processing information in the class file is confidential. How should you remove this confidential information from the client applications without breaking their functionality? ❍ A. Rewrite the client applications in C++ so that they do not contain managed code. ❍ B. Create an interface called IProduct that contains all the public members of the Product class. Implement the interface in the Product class. Ship only the interface with the client application. ❍ C. Remove the implementation code from the client’s copy of the Product class. ❍ D. Rewrite the application as a Web service application instead of a remoting application.
Question 3 You are designing a .NET Remoting server that will be hosted by IIS and ASP.NET. This server will make the Employee remotable object available to clients. You do not wish to open ports on the firewall to the remote Employee object. Clients will be deployed on several different operating systems and platforms. Which channel and formatter should you use to implement this server? ❍ A. HttpChannel and SoapFormatter ❍ B. HttpChannel and BinaryFormatter ❍ C. TcpChannel and SoapFormatter ❍ D. TcpChannel and BinaryFormatter
371 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#2.
Question 4 You are developing a .NET Remoting application that allows client programs to instantiate a class named Account. You want the remote object to be created on the server so that it can access the corporate financial information, which is stored on an intranet. However, you want client programs to control the creation and the lifetime of the remote objects. Which of the following methods of the RemotingConfiguration class would you choose to register the remotable class with the remoting system on the client? ❍ A. RegisterWellKnownServiceType ❍ B. RegisterWellKnownClientType ❍ C. RegisterActivatedServiceType ❍ D. RegisterActivatedClientType
Question 5 You are developing a distributed application using the .NET Remoting infrastructure. The application exposes the Order object as a remote object to its client applications. The Order object consists of order details and an array of Product objects. The Product object consists of large number of data members. You want to provide your own code to control the serialization process of the Product object. What should you do? [Select two.] ❑ A. Mark the Product class with the NonSerialized attribute. ❑ B. Mark the Product class with the Serializable attribute. ❑ C. Derive the Product class from the MarshalByRef class. ❑ D. Make the Product class implement the ISerializable interface.
Question 6 You have designed a remotable class that allows the user to retrieve the latest stock price information for the selected stock symbols in her portfolio. You have hosted the remote object in IIS and ASP.NET. The name of the remotable class is MyCompany.StockInfo, and it is stored in an assembly named StockInfo.dll. Which of the following remoting configurations would the client applications use in their configuration file to retrieve stock information correctly?
372 Chapter 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ❍ A.
❍ B.
❍ C.
❍ D.
Question 7 You have designed a Windows application that is used by the shipping department of a large distributing company. The Windows application instantiates a remotable class hosted on Internet Information Services (IIS). The remotable class provides various services to the Windows application, such as address validation and calculation of shipping rates. When you deploy the application, users complain that when they click the Validate Address button, the Windows application freezes and they can’t take further action until the address has been verified. What should you do to improve the application’s responsiveness? ❍ A. Use the binary formatter instead of the SOAP formatter. ❍ B. Use the TCP channel to communicate instead of the HTTP channel. ❍ C. Modify the remotable class to support asynchronous method calls. ❍ D. Modify the Windows application to call the methods asynchronously on the remote object.
373 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#2.
Question 8 The ASMX file in your Web service contains the following code: Imports System.Web.Services _ Public Class Account Inherits System.Web.Services.WebService Public Function Balance( _ ByVal acctNumber As String) As Int32 ‘ Stub to test function Balance = 5 End Function End Class
You compile the Web service and set a Web reference to it from a client application. However, you are unable to call the Balance method from the client application. What must you do? ❍ A. Add the attribute to the Balance method. ❍ B. Rewrite the Balance method as a Sub procedure. ❍ C. Add the Balance method to the WSDL file for the Web service. ❍ D. Register the Web service with a UDDI Registry.
Question 9 You are using the Web Services Description Language tool to create a proxy class for a Web service. The Web service exposes a class named Product. You already have a Product class in your application. What should you do to allow both classes to coexist in the same application? ❍ A. Rename the existing class. ❍ B. Manually edit the generated proxy class to change the class name that it contains. ❍ C. Use the /namespace option of the Web Services Description Language tool to specify a unique namespace for the new class. ❍ D. Use the /out option of the Web Services Description Language tool to specify a unique output filename for the new class.
374 Chapter 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 10 You are invoking a Web service that returns a Hashtable object. Your client application is written in Visual Basic .NET, whereas the Web service itself is written in Visual C# .NET. The Web service is outside your corporate firewall. You receive an “object not found” error when you call the method that returns the Hashtable object. What could be the problem? ❍ A. The client project and the server project are not written in the same language. ❍ B. The firewall is blocking all SOAP calls. ❍ C. The client project does not contain a reference to the System.Collections namespace. ❍ D. The Hashtable object cannot be serialized.
Question 11 You are developing a SOAP extension that requires loading certain settings from the Windows Registry to initialize resources at startup. In which method should you load the settings from the Windows Registry? ❍ A. GetInitializer ❍ B. Initialize ❍ C. ChainStream ❍ D. ProcessMessage
Question 12 You are designing a SOAP extension that will run within a variety of Web service clients. This extension will monitor XML messages for confidential information and will delete such information if it is found. In which message state should you invoke this SOAP extension? ❍ A. BeforeSerialize ❍ B. AfterSerialize ❍ C. BeforeDeserialize ❍ D. AfterDeserialize
375 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#2.
Question 13 The customer service representatives in your company often receive calls from customers inquiring about the shipping status of their orders. You have been assigned to create an application that assists the customer service representatives to easily find the shipping status. You decide to create a Windows-based application that calls the XML Web services provided by the shipping and logistic company to retrieve the latest shipping status. When you test the application, the user of the application complains that the user interface of the application is very slow. You find that your program is waiting for the Web service call to execute. You need to design a solution that is most efficient. What should you do to make your application responsive? ❍ A. Use the WaitHandle.WaitAll method of the IAsyncResult.AsyncWaitHandle object. ❍ B. Call the End method of the XML Web service. ❍ C. Use the WaitHandle.WaitAny method of the IAsyncResult.AsyncWaitHandle object. ❍ D. Supply a callback delegate to the Begin method of the XML Web service. After the XML Web service returns, a thread will invoke the callback method from the thread pool.
Question 14 You are a developer in a company that manufactures chemicals used in a diverse range of targeted markets. You are developing a Web method called GetOrderDetails that will return the order details of an order placed by a customer. The customers usually call this Web service to retrieve and track order details of various orders placed with the company. The Web service needs to return order details for only those orders that are placed within the last six months. It also needs to receive order details from a legacy ERP system over a slow WAN link. The current implementation of the Web service is responding slowly and often gets connection timed out. The Web method of the Web service receives thousands of hits every day. You are responsible for improving the Web service response and for minimizing the hit to the legacy ERP system. What should you do? ❍ A. Use caching to store the GetOrderDetails Web method responses. Set the CacheDuration attribute of the Web method to 1000. ❍ B. Enable buffering to buffer the GetOrderDetails Web method response. Set the BufferResponse attribute of the GetOrderDetails Web method to True. ❍ C. Use session state to store the order details placed within the last six months by the customer. Set the EnableSession property of the GetOrderDetails Web method to True. ❍ D. Use application state to store the order details placed within the last six months by the customer.
376 Chapter 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 15 You are a developer for a manufacturing company. Your company wants to have an XML Web service to share the latest design changes with its partner companies. The design data is confidential and must be transmitted securely over the Internet. You do not want a system that accepts usernames and passwords from the partner companies. Which of the following authentication mechanisms should you choose for this Web service? ❍ A. Basic authentication ❍ B. Digest authentication ❍ C. Windows integrated authentication ❍ D. Client certificate
Question 16 You are performing a final QA pass on a Web service client, and you discover that the name of one of the parameters on the Web service server has changed. All the documentation for the client has been printed, so you do not want to change the name of the client parameter. What should you do to fix this mismatch? ❍ A. Use the SoapDocumentMethod attribute to specify the Bare parameter style for this method. ❍ B. Use a SOAP extension on the client to detect the old parameter name and change it to the new parameter name before the message is sent. ❍ C. Use the SoapDocumentMethod attribute with Use=SoapBindingUse.Literal to specify literal encoding for this method. ❍ D. Use the XmlElement attribute to rename the parameter in the SOAP messages.
Question 17 You are designing an application to monitor your network and log XML messages. This application should run full time, as long as the monitoring computer is running, regardless of whether there is a user logged on. Which sort of application should you design? ❍ A. Web service ❍ B. Serviced component ❍ C. ASP.NET application ❍ D. Windows service
377 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#2.
Question 18 You are designing a network application that depends on several Windows services. You want to allow users to list all the services on the computer and select the ones they want to monitor. Which class can you use to enumerate the running services? ❍ A. ServiceBase ❍ B. ServiceInstaller ❍ C. ServiceController ❍ D. ServiceProcessInstaller
Question 19 You are developing a Windows service by inheriting from the System.ServiceProcess.ServiceBase class. Which of the following handlers must you implement to make your Windows service useable? ❍ A. OnStop ❍ B. OnStart ❍ C. OnPause ❍ D. OnContinue
Question 20 You are developing a serviced component in Visual Basic .NET. You have written code for the component and registered it with COM+ using regsvcs.exe. You later modify the code of the component, rebuild it, and then register it again with COM+. After registration, you notice that the component appears in the COM+ catalog twice. What should you do to make the COM+ component appear only once in the Component Services? ❍ A. Build the component in release mode instead of in debug mode. ❍ B. Disable object pooling for the COM+ component. ❍ C. Use the Guid attribute to assign a constant GUID to the class. ❍ D. Set the ClassInterface attribute with the ClassInterfaceType.None value so that you can hard-code the component’s interfaces.
378 Chapter 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 21 You have created a serviced component that accepts vacation requests from employees for processing by the payroll system. You enable object pooling services for the component and set Minimum Pool Size to 5 and Maximum Pool Size to 10. However, you have underestimated the demand for vacations, and 12 users attempt to use the application simultaneously. What is the result? ❍ A. The first 10 requests for the object are satisfied with new instances. The last two requests are queued until an instance is available, or until the specified timeout period elapses. ❍ B. The first 10 requests for the object are satisfied with new instances. The last two requests fail with an “object not found” exception. ❍ C. The first 10 requests for the object are satisfied with new instances. The last two requests are satisfied by recycling the first two objects, thus disconnecting the first two requests. ❍ D. Component Services increases the pool size to 12 to satisfy all the requests.
Question 22 You have created a component that makes use of COM+ transactions through the System.EnterpriseServices namespace. During the course of its activities, the component calls various methods of the ContextUtil class. Which of these methods can the class use to indicate that its work is finished and that it approves of committing the transaction? [Select the two best answers.] ❑ A. DisableCommit ❑ B. EnableCommit ❑ C. SetAbort ❑ D. SetComplete
Question 23 You create a queued component named ShipPaints, which is used to ship paints whose requests appear in an asynchronous fashion. The ShipPaints class includes the following code: Public Interface IShipPaints Function Ship(ByVal o As Paint) As Boolean End Interface _
379 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#2.
Public Class ShipPaints Inherits ServicedComponent Implements IShipPaints Public Function Ship(ByVal o As Paint) As Boolean ‘ code to update various databases End Function End Class
You get no compilation errors, but when you register this component using the .NET Services Installation Tool (regsvcs.exe), you get the following error message: Queuing not supported on interface ‘IShipPaints’
What should you do to resolve this error? ❍ A. Apply the AutoComplete attribute on the ShipPaints class. ❍ B. Apply the following attribute on the class:
❍ C. Apply the InterfaceQueuing attribute on the IShipPaints interface rather than on the ShipPaints class. ❍ D. Change the interface definition as follows and then change ShipPaints to implement this interface: Public Interface IShipPaints Sub Ship(ByVal o As Paint) End Interface
Question 24 You are developing a client application that needs to invoke an XML Web service. The Web service uses Basic authentication to authenticate the users. You write the following code segment to invoke the Web service (line numbers are for reference only): 01: 02: 03: 04: 05: 06:
‘ Create an instance of the Web service class Dim catServ As ProductMfg.Catalog = _ New ProductMfg.Catalog() ‘ Pass credentials to the Web service ‘ Invoke a Web method on the Web service Dim price As Double = catServ.GetPrice(productID)
Which of the following code segments would you insert between lines 4 and 5 in the preceding code to pass the client credentials to the Web service?
380 Chapter 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ❍ A. Dim cc As CredentialCache = New CredentialCache() Dim credentials As NetworkCredential = _ New NetworkCredential() cc.Add(New Uri(catServ.Url), _ “Basic”, credentials) catServ.Credentials = cc
❍ B. Dim cc As CredentialCache = New CredentialCache() Dim credentials As NetworkCredential = _ New NetworkCredential(“username”,”password”,”domain”) cc.Add(New Uri(catServ.Url), _ “Basic”, credentials) catServ.Credentials = cc
❍ C. Dim cc As CredentialCache = New CredentialCache() Dim credentials As NetworkCredential = _ New NetworkCredential() cc.Add(New Uri(catServ.Url), _ “Basic”, credentials) catServ.Credentials = credentials
❍ D. Dim cc As CredentialCache = New CredentialCache() Dim credentials As NetworkCredential = _ New NetworkCredential(“username”,”password”,”domain”) cc.Add(New Uri(catServ.Url), _ “Basic”, credentials) catServ.Credentials = credentials
Question 25 ComponentWare Inc., supplies a range of COM components to provide advanced communications capabilities to a wide variety of applications. In the last management meeting, company managers decided to create .NET versions of these components. Some of the clients of the company are already porting to .NET and require an RCW for the components immediately. What should ComponentWare do? ❍ A. Use the Type Library Importer tool to create and sign a PIA for the components. ❍ B. Use the Type Library Exporter tool to create and sign a PIA for the components. ❍ C. Set a reference to the components from any Visual Basic .NET project to create an RCW for these components. ❍ D. Create a class that uses Platform Invoke to call functions from the components.
381 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#2.
Question 26 You wrote a COM component to supply weather information from the weather database to the Weather Web page of your Web application. You are porting the Web application to .NET. You now want to call the methods of the COM component from your ASP.NET Web application. The COM component is not used by any other application. Which of the following is the quickest way to use the COM component in the ASP.NET Web application? ❍ A. Set a direct reference from your .NET client to the COM server. ❍ B. Use the Type Library Importer to create an unsigned RCW for the COM component. ❍ C. Use the Type Library Importer to create a signed RCW for the COM component. ❍ D. Use PInvoke to instantiate classes from the COM component.
Question 27 Your project contains the following API declaration: _ Public Shared Function GetComputerName( _ ByVal buffer As String, _ size As Integer) As Integer End Function
The project also contains code to use this API to display the computer name: Public Sub ShowName() Dim buf As String = “” Dim intLen As Integer = 128 Dim intRet As Integer ‘ Call the Win API method intRet = GetComputerName(buf, intLen) Console.WriteLine( _ “This computer is named “ & _ buf.ToString()) End Sub
Users report that no computer name is displayed. What should you do? ❍ A. Use a Declare statement instead of DllImport to declare the API call. ❍ B. Replace the use of String with StringBuilder in the code. ❍ C. Specify ByRef for the buf parameter in the call to GetComputerName. ❍ D. Specify the correct character set in the declaration of the function.
382 Chapter 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 28 You are creating a schema file to represent the Customers table in your database. You need to represent a field named CustomerContact in this schema. Data entered in the CustomerContact field is a string with up to 50 characters. What should you use to represent this field in the XML schema? ❍ A. Attribute ❍ B. Simple type ❍ C. Element ❍ D. Complex type
Question 29 You’ve developed a Visual Basic .NET application that displays supplier data in a DataGrid control. The supplier data is stored in a table named Suppliers within the dsSuppliers DataSet object. The primary key for the Suppliers table is the SupplierID column. You need to display the supplier data in the DataGrid control in the ascending order of the primary key. You write the following code segment to accomplish this task: Dim dvSuppliers As DataView = _ New DataView(dsSuppliers.Tables(“Suppliers”)) dvSuppliers.Sort = “ASC” dvSuppliers.ApplyDefaultSort = True dataGrid1.DataSource = dvSuppliers
However, when you run the program, the results are not as expected. How should you change the preceding code segment to get the intended results? ❍ A. Set the Sort property of the DataView object to an empty string. ❍ B. Set the ApplyDefaultSort property of the DataView object to False. ❍ C. Set the RowFilter property of the DataView object to SupplierID. ❍ D. The code segment is correct. You just need to ensure that the data in the Suppliers table is already sorted on the primary key.
Question 30 You create a .NET application that queries data from a SQL Server database. You use a SqlConnection object to connect to the database. As soon as the database operation is completed, you want to make sure that any pending database transactions are rolled back and the connection is returned to the connection pool. You need to reuse the same SqlConnection object when your program needs to query the database again. Which of the following actions should you take?
383 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#2. ❍ A. Call the Dispose method on the SqlConnection object. ❍ B. Call the Finalize method of the SqlConnection object. ❍ C. Call the Close method on the SqlConnection object. ❍ D. Set the SqlConnection object to Nothing.
Question 31 You develop a .NET application that allows the users to view and modify recently placed orders. Your application needs to display data from OrderHeader and OrderDetails data tables. Information from OrderHeader is displayed in a ListBox control; the information from OrderDetails is displayed in a DataGrid control. Your program must ensure that as soon as a different order is selected in the ListBox control, the DataGrid control displays the details corresponding to that order. Which of the following actions will you take to implement this functionality? ❍ A. Define primary keys on the OrderHeader and OrderDetails table. ❍ B. Create a foreign key constraint in the OrderDetails table. ❍ C. Add a DataRelation object to the Relations collection of the DataSet object. ❍ D. Use the DataSet.Merge method.
Question 32 You develop a .NET application named ProcessOrders. This application receives XML data files from various customers, reads the files, and stores them in a SQL Server database for further processing. The ProcessOrders application uses an XML schema file to define the format and data types of the XML data files. However, not all customers send the XML data file using the same schema. Your application should parse the incoming data files to ensure they conform to the XML schema. Which of the following actions should you take to accomplish this requirement? ❍ A. Implement an XmlDocument object to load the document. Pass the schema file to this object to validate and parse the XML document. ❍ B. Implement an XmlValidatingReader object and program an event handler for the ValidationEventHandler event to parse the data file that does not conform to the XML schema. ❍ C. Read the XML file into a DataSet object and set its EnforceConstraints property to True. ❍ D. Read the XML file and schema into a DataSet object. Program the DataSet.MergeFailed event handler to parse the data file that does not conform to the XML schema.
384 Chapter 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 33 You are working with a SQL Server database that contains a table named Patients and a table named Visits. The Patients table contains the columns PatientID (a unique identifier for the patient and the primary key of the table) and PatientName (the name of the patient). The Visits table contains the columns VisitID (a unique identifier for the visit and the primary key of the table), PatientID (a foreign key that points to the PatientID column in the Patients table), VisitCost (the bill for the visit), and VisitDate (the date of the visit). You want to write a query that returns the number of visits that each patient has made, together with the patient’s name, provided that the total cost of the visits is at least $100. Which SQL statement should you use? ❍ A. SELECT Patients.PatientName, Count(Visits.VisitID) FROM Patients INNER JOIN Visits ON Patients.PatientID = Visits.PatientID GROUP BY Patients.PatientName WHERE Sum(Visits.VisitCost)>=100
❍ B. SELECT Patients.PatientName, Count(Visits.VisitID) FROM Patients INNER JOIN Visits ON Patients.PatientID = Visits.PatientID GROUP BY Patients.PatientName WHERE Visits.VisitCost >=100
❍ C. SELECT Patients.PatientName, Count(Visits.VisitID) FROM Patients INNER JOIN Visits ON Patients.PatientID = Visits.PatientID GROUP BY Patients.PatientName HAVING Sum(Visits.VisitCost)>=100
❍ D. SELECT Patients.PatientName, Count(Visits.VisitID) FROM Patients INNER JOIN Visits ON Patients.PatientID = Visits.PatientID GROUP BY Patients.PatientName HAVING Visits.VisitCost >=100
385 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#2.
Question 34 Your Visual Basic .NET application needs to read data from a SQL Server 6.5 database and write it to a flat file once every 12 hours. A legacy application accesses this file to update its data. Because the data you will read from the database is huge, you want to retrieve it with very least amount of impact on the server resources and you want to maximize the performance. Which object should you use to load the data from the database? ❍ A. DataSet ❍ B. DataTable ❍ C. SqlDataReader ❍ D. OleDbDataReader
Question 35 You allow users to edit product information on a DataGrid control that is bound to a DataSet object. When the users click the Update button on the form, you call the SqlDataAdapter.Update method to cause the changes from the DataSet object to persist to the underlying database. Users report that new records and updated rows are saved properly but that deleted rows are reappearing the next time they run the application. What could be the problem? ❍ A. The users do not have permission to update the underlying table. ❍ B. The Update method does not delete rows. ❍ C. Someone is restoring an old version of the database between the two executions of the program. ❍ D. You have neglected to set the DeleteCommand property of the SqlDataAdapter object.
Question 36 Your SQL Server database contains a table, Sales, with these columns: SalesID (int, identity) StoreNumber (int) Sales (int)
You have created a stored procedure that accepts as input the store number and sales, inserts a new row in the table with this information, and returns the new identity value: CREATE PROCEDURE procInsertSales @StoreNumber int, @Sales int,
386 Chapter 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
@SalesID int OUTPUT AS INSERT INTO Sales (StoreNumber, Sales) VALUES (@StoreNumber, @Sales) SELECT @SalesID = @@IDENTITY
Which statement should you use to define the SqlParameter object for @SalesID parameter for the preceding stored procedure? ❍ A. Dim paramSalesID As SqlParameter = New SqlParameter( _ “@SalesID”, SqlDbType.Int) paramSalesID.Direction = ParameterDirection.Output
❍ B. Dim paramSalesID As SqlParameter = New SqlParameter( _ “@SalesID”, SqlDbType.Int) paramSalesID.Direction = ParameterDirection.ReturnValue
❍ C. Dim paramSalesID As SqlParameter = New SqlParameter( _ “@SalesID”, Int32) paramSalesID.Direction = ParameterDirection.Output
❍ D. Dim paramSalesID As SqlParameter = New SqlParameter( _ “@SalesID”, Int32) paramSalesID.Direction = ParameterDirection.ReturnValue
Question 37 You develop an application named ProcessOrder using Visual Basic .NET. Your application receives orders from customers in an XML file named Orders.xml. The Orders.xml file does not include any schema. Which of the following methods should you use to load the data from Orders.xml into a DataSet object? [Select two.] ❑ A. Dim ds As DataSet = New DataSet(“Orders”) ds.ReadXml(“Orders.xml”, XmlReadMode.Auto)
❑ B. Dim ds As DataSet = New DataSet(“Orders”) ds.ReadXml(“Orders.xml”, XmlReadMode.DiffGram)
❑ C. Dim ds As DataSet = New DataSet(“Orders”) ds.ReadXml(“Orders.xml”, XmlReadMode.Fragment)
387 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#2. ❑ D. Dim ds As DataSet = New DataSet(“Orders”) ds.ReadXml(“Orders.xml”, XmlReadMode.InferSchema)
❑ E. Dim ds As DataSet = New DataSet(“Orders”) ds.ReadXml(“Orders.xml”, XmlReadMode.ReadSchema)
Question 38 You develop a .NET application that allows users to add new regions in the SQL Server Sales database. You use the following Visual Basic .NET code segment to add regions: Dim command As SqlCommand = New SqlCommand(Nothing, sConn) command.CommandText = “INSERT INTO Region (RegionID, “ & _ “RegionDescription) VALUES (@rid, @rdesc)” command.Parameters.Add(“@rid”, rid) command.Parameters.Add(“@rdesc”, rdesc) command.ExecuteNonQuery()
Each time the users run this application, they may add several regions. Which of the following options will you use to ensure the optimum performance of the application? ❍ A. Use the SqlCommand.ExecuteReader method instead of the SqlCommand.ExecuteNonQuery method. ❍ B. Call the SqlCommand.Prepare method before each call to the SqlCommand.ExecuteNonQuery method. ❍ C. Call the SqlCommand.Prepare method before the first call to the SqlCommand.ExecuteNonQuery method. ❍ D. Call the SqlCommand.ResetCommandTimeout method before each call to the SqlCommand.ExecuteNonQuery method.
Question 39 Your application’s database includes a table of orders that contains three million rows of data. Each row includes the order date as well as other information. Your application allows the user to enter a date. Then it will display all the orders placed on that date. Which strategy should you use to retrieve the orders? ❍ A. Create a parameterized stored procedure that accepts the order date as a parameter. ❍ B. Retrieve the orders table to a DataSet object and build a DataView object to contain only the required orders.
388 Chapter 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ❍ C. Create an ad hoc SQL statement that includes the date entered by the user as part of the SQL statement. ❍ D. Create a view on the server that includes only the required orders.
Question 40 You have defined a stored procedure in your database as follows: CREATE PROC GetCustomers @Country varchar(25) AS SELECT * FROM Customers WHERE Country = @Country
The stored procedure executes without error from the SQL Query Analyzer. Now you are using code behind a form with this stored procedure. The form includes a SqlConnection object named cnn, and a DataGrid control named dgCustomers: Dim cmd As SqlCommand = New SqlCommand() Dim ds As DataSet = New DataSet() Dim da As SqlDataAdapter = _ New SqlDataAdapter() cmd.Connection = cnn cmd.CommandText = “GetCustomers” cmd.Parameters.Add(New SqlParameter( _ “@Country”, SqlDbType.VarChar, 25)) cmd.Parameters(“@Country”).Value = “France” da.SelectCommand = cmd da.Fill(ds, “Customers”) dgCustomers.DataSource = ds dgCustomers.DataMember = “Customers”
When you run the code, you receive an unhandled exception of type System.Data.SqlClient.SqlException on the line that calls the Fill method. What should you do to fix this error? ❍ A. Explicitly set the CommandType object of the SqlCommand object to CommandType.StoredProcedure. ❍ B. Replace the stored procedure with an ad hoc SQL statement containing the actual country string. ❍ C. Use a SqlDataReader object instead of a DataSet object to retrieve the data. ❍ D. Call the Open method of the SqlConnection object before calling the Fill method of the DataAdapter.
389 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#2.
Question 41 You develop desktop applications for a large university. Your new project is to write a Visual Basic .NET application that allows professors to maintain the score of their students. You place a DataGrid control on the Windows Form and bind the data grid to a DataView object. You allow professors to make changes in the data grid by adding new rows, by modifying existing rows, and by deleting existing rows. You now want to place a command button that allows professors to view the deleted rows from the original data. How should you program the Click event of the command button? ❍ A. In the event handler for the Click event, set the RowFilter property of the DataView object to DataViewRowState.Deleted. ❍ B. In the event handler for the Click event, set the RowFilter property of the DataView object to DataViewRowState.OriginalRows. ❍ C. In the event handler for the Click event, set the RowStateFilter property of the DataView object to DataViewRowState.Deleted. ❍ D. In the event handler for the Click event, set the RowStateFilter property of the DataView object to DataViewRowState.OriginalRows.
Question 42 Your application contains the following XML file: 1 4 3
Your application uses the ReadXmlSchema method of the DataSet object to create a DataSet object with an appropriate schema for this XML file. Which of the following mappings between XML entities and DataSet object entities will this method create? ❍ A. Trials and Trial will become DataTable objects. Courtroom will become a DataColumn object. TrialID will not be mapped. ❍ B. Trials and Trial will become DataTable objects. TrialID will become a DataColumn object. Courtroom will not be mapped.
390 Chapter 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ❍ C. Trials and Trial will become DataTable objects. TrialID and Courtroom will become DataColumn objects. ❍ D. Trials will become a DataTable object. Trial and Courtroom will become DataColumn objects. TrialID will not be mapped.
Question 43 You are working programmatically with an XML document. You don’t know anything about the structure of this document, other than that it is valid XML. Which of these methods can you use to retrieve the root element of the document? ❍ A. Load the document into an XmlDocument object and retrieve its DocumentElement property. ❍ B. Load the document into an XmlNode object and retrieve its DocumentElement property. ❍ C. Load the document into an XmlDocument object and retrieve its DocumentType property. ❍ D. Load the document into an XmlNode object and retrieve its DocumentType property.
Question 44 You are using XPath to retrieve information from an XML file of electronic components. Some of the components are grouped into assemblies and subassemblies, and this grouping is represented in the hierarchy of the XML file. You wish to write an XPath expression to select every occurrence of the Volts attribute in the XML file, regardless of the level where this attribute appears. Which XPath expression can you use for this purpose? ❍ A. ./@Volts ❍ B. ./Volts ❍ C. //@Volts ❍ D. //Volts
391 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#2.
Question 45 Your application contains the following code to update a SQL Server database via an XML DiffGram: Private Sub btnUpdate_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnUpdate.Click ‘ Connect to the SQL Server database Dim sxc As SqlXmlCommand = _ New SqlXmlCommand( _ “Provider=SQLOLEDB;” & _ “Server=(local);” & _ “database=Northwind;” & _ “Integrated Security=SSPI”) ‘ Set up the DiffGram sxc.CommandType = _ SqlXmlCommandType.DiffGram sxc.SchemaPath = “..\diffgram.xsd” sxc.CommandStream = _ New FileStream(“..\diffgram.xml”, _ FileMode.Open) ‘ And execute it sxc.ExecuteNonQuery() End Sub
The code executes and the data specified in the diffgram.xml file is properly updated when you run the application on your own computer. However, when you deploy the application to a production computer, you receive a System.IO.FileNotFoundException. You have verified that the production computer has the correct installation of SQL Server and the Northwind database. What action should you take to fix this problem? ❍ A. Move the DiffGram files to the root directory on the production computer. ❍ B. Install .NET Framework 1.0 SP2 on the production computer. ❍ C. Install the SQLXML package on the production computer. ❍ D. Modify the connection string to explicitly use the name of the production computer.
392 Chapter 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 46 The configuration file of an application has the following contents:
You are using the following statements to create switch objects in your code: Dim booleanSwitch As BooleanSwitch = _ New BooleanSwitch(“BooleanSwitch”, “Boolean Switch”) Dim traceSwitch As TraceSwitch = _ New TraceSwitch(“TraceLevelSwitch”, “Trace Switch”)
Which of the following options is correct regarding the values of these switch objects? ❍ A. The booleanSwitch.Enabled property is set to False and traceSwitch.Level is set to TraceLevel.Verbose. ❍ B. The booleanSwitch.Enabled property is set to True and traceSwitch.Level is set to TraceLevel.Verbose. ❍ C. The booleanSwitch.Enabled property is set to False and traceSwitch.Level is set to TraceLevel.Error. ❍ D. The booleanSwitch.Enabled property is set to False and traceSwitch.Level is set to TraceLevel.Info.
Question 47 Your application uses version 2.3.0.0 of the FunGraph assembly. The producer of the assembly has issued version 2.3.l.0 of the assembly, together with a publisher policy file that dictates using 2.3.1.0 in place of 2.3.0.0 in all applications. You discover after testing that one of your applications, named DiskGraph, which previously worked with 2.3.0.0, fails with 2.3.1.0. You want only this application to use the old version of the assembly, while letting all other applications use the new version. What should you do? ❍ A. Copy version 2.3.0.0 of the assembly from the GAC to the folder containing DiskGraph.exe. ❍ B. Add an administrator policy specifying that requests for 2.3.0.0 be satisfied with 2.3.0.0. ❍ C. Add the element to the DiskGraph.exe.config file. ❍ D. Delete the publisher policy from your computer.
393 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#2.
Question 48 You need to debug a .NET application by using Visual Studio .NET installed on your local machine. The Web application is deployed on a remote server. When you attempt to debug the application, you get a DCOM configuration error. Which of the following steps should you take to resolve this problem? ❍ A. Add your account to the Main Users group on the local computer. ❍ B. Add your account to the Main Users group on the remote computer. ❍ C. Add your account to the Debugger Users group on the local computer. ❍ D. Add your account to the Debugger Users group on the remote computer.
Question 49 You develop a supplier-evaluation system using Visual Studio .NET. While testing the program, you notice that the value of the TotalShipments variable sometimes becomes zero and causes an exception within the CalculateAvgShipDelay method. You want your program to check the value of the TotalShipments variable and display an error message when the value of TotalShipments is zero. You want the program to display this error message irrespective of how you compile the program. Which of the following code segment should you write before making a call to the CalculateAvgShipDelay method? ❍ A. Trace.Assert(TotalShipments = 0, “TotalShipments is zero”)
❍ B. Trace.Assert(TotalShipments 0, “TotalShipments is zero”)
❍ C. Debug.Assert(TotalShipments = 0, “TotalShipments is zero”)
❍ D. Debug.Assert(TotalShipments 0, “TotalShipments is zero”)
394 Chapter 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 50 You develop an ASP.NET Web application that enables the users to generate shipping labels. The program needs to generate thousands of shipping labels each day. You use the Trace object to monitor the application and log the results in the Windows event log. You need to monitor errors, warnings, and other informational messages generated by the Trace object. You should have flexibility in controlling the amount of information logged for your application, and you want to do this with minimal administrative efforts. What should you do? ❍ A. Compile the application using the /d:TRACE switch. ❍ B. Define an environment variable named TRACE and set its value to True or False. In the program, check the value of the environment variable to indicate the amount of information you want to be logged for your application. ❍ C. Declare a compilation constant named TRACE and set its value to Error, Warning or Info. In your program use #if, #else, and #endif directives to check the level of tracing you want. ❍ D. Use the TraceSwitch class in your program and use the TraceSwitch.Level property to check whether you need to log the performance. Set the level of TraceSwitch by using the application’s configuration file.
Question 51 You are debugging an ASP.NET Web application that you wrote using Visual Studio .NET. Your code uses the Trace class to produce the debugging output. In which configuration(s) will this output be enabled? ❍ A. In the default Release configuration only ❍ B. In the default Debug configuration only ❍ C. In both the default Release configuration and the default Debug configuration ❍ D. In neither the default Release configuration nor the default Debug configuration
Question 52 You are testing a huge Web application running on the main testing server and you have enabled tracing in the application. You find it difficult to test the application from your desktop because the Web application is storing tracing information for only a few requests. You want the Web application to record tracing information for a larger number and you also want the tracing information to be
395 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#2.
displayed in the Web page along with the trace viewer. Which of the following options should you choose? ❍ A. Set the element in the Web.config application configuration file of the application to
❍ B. Set the element in the Web.config application configuration file of the application to
❍ C. Set the element in the Web.config application configuration file of the application to
❍ D. Set the element in the Web.config application configuration file of the application to
❍ E. Set the element in the Web.config application configuration file of the application to
❍ F. Set the element in the Web.config application configuration file of the application to
Question 53 You use Visual Basic .NET to develop a component named ReplicateWarehouseData. This component replicates the data used by the Warehousing application, developed by the Warehouse Development team of your company. The Warehouse Development team needs to deploy the Warehousing application to its first three customers. How should the team deploy the application? [Select all that apply.] ❑ A. Create a Merge Module for the ReplicateWarehouseData component. ❑ B. Create a Setup project to deploy the application and include the Merge Module containing the component into the Setup project. ❑ C. Copy the ReplicateWarehouseData component into the directory of the Warehousing application. ❑ D. Create a Web Setup project to deploy the application that contains the code for the component.
396 Chapter 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 54 You use Visual Basic .NET to create an assembly named Tracker.dll that contains classes for tracking a shipment. You need to deploy the assembly on the target computer in such a way that it can be accessed by multiple .NET applications. Which of the following actions should you take? [Select all that apply.] ❑ A. Create a strong name for the assembly by using the Strong Name tool (sn.exe). ❑ B. Register the assembly using the Assembly Registration tool (regasm.exe). ❑ C. Use XCOPY to deploy the assembly to the Global Assembly Cache. ❑ D. Use FTP to deploy the assembly to the Global Assembly Cache. ❑ E. Use a Setup and Deployment project to deploy the assembly to the Global Assembly Cache.
Question 55 You develop an application that retrieves data from a SQL Server database named Customers. You use the System.Data.SqlClient data provider to connect with the database. You need to log the severity level of the error returned from the SQL Server .NET data provider. Which of the following options should you choose? ❍ A. Catch the SqlException thrown by the SQL Server .NET data provider. Examine the Class property of the SqlException object. ❍ B. Catch the SqlException thrown by the SQL Server .NET data provider. Examine the Source property of the SqlException object. ❍ C. Catch the SqlException thrown by the SQL Server .NET data provider. Examine the Server property of the SqlException object. ❍ D. Catch the SqlException thrown by the SQL Server .NET data provider. Examine the State property of the SqlException object.
Question 56 You have been using version 1.1.0.0 of InterestCalculator, a .NET class library, in your applications from an external vendor. You have developed multiple inhouse applications that reference and use InterestCalculator 1.1.0.0, which is installed in the GAC on your computers. Now the vendor has released InterestCalculator 2.0.0.0, which is not 100% backward compatible with InterestCalculator 1.1.0.0. You would like to start
397 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#2.
using InterestCalculator 2.0.0.0 in new applications, but you want existing applications to continue to use InterestCalculator 1.1.0.0. What should you do? ❍ A. Remove InterestCalculator 1.1 from the GAC. Install InterestCalculator 1.1 in the folder of each application that uses it. Install InterestCalculator 2.0 in the GAC. ❍ B. Install InterestCalculator 2.0 in the GAC. Add a .config file to each existing application, telling it to use InterestCalculator 1.1. ❍ C. Install InterestCalculator 2.0 in the GAC. Make no other changes to the existing configuration. ❍ D. Install InterestCalculator 2.0 in the folder of each new application. Do not install InterestCalculator 2.0 in the GAC until you have retired or rewritten all the existing applications.
Question 57 Your application requires the user to be a member of the Accounting role to access a BalanceSheet object. Which .NET security feature should you use to ensure that your code has this ability? ❍ A. Role-based security ❍ B. Code access security ❍ C. SSL encryption ❍ D. Type safety
Question 58 You design a Visual Basic .NET application that uses the following code to check for membership in the Developer’s group: Private Sub frmSecure_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ‘ Get the current principal object Dim prin As WindowsPrincipal = Thread.CurrentPrincipal ‘ Determine whether the user is an admin Dim fAdmin As Boolean = prin.IsInRole(“Developers”) ‘ Display the results on the UI If fAdmin Then lblMembership.Text = _ “You are in the Developers group” Else lblMembership.Text = _ “You are not in the Developers group” End If End Sub
398 Chapter 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Users report that the code claims they are not in the Developer’s group even when they are. What must you do to fix this problem? ❍ A. Use imperative security to make sure that your code has access to the Windows environment variables. ❍ B. Create a WindowsIdentity object by using the WindowsIdentity.GetCurrent method and then use this object to construct the WindowsPrincipal object. ❍ C. Use the WindowsPrincipal.Name property to retrieve the user’s name and then use that name to make the call to the IsInRole method. ❍ D. Call AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.Windows Principal) to specify the authentication mode.
Question 59 You are developing a proof-of-concept program to evaluate role-based security for your .NET Framework application. You write the following code: Dim pp1 As PrincipalPermission = _ New PrincipalPermission(“User1”, “Role1”) Dim pp2 As PrincipalPermission = _ New PrincipalPermission(“User2”, “Role2”) Dim pp3 As PrincipalPermission = _ New PrincipalPermission(“User3”, “Role3”) Dim perm1 As PrincipalPermission = _ CType(pp1.Union(pp2), PrincipalPermission) Dim perm2 As PrincipalPermission = _ CType(pp3.Union(perm1), PrincipalPermission)
Which of the following statements is correct with respect to the preceding code? [Select all that apply.] ❑ A. The expression perm1.IsSubsetOf(perm2) will evaluate to True. ❑ B. The expression perm1.IsSubsetOf(perm2) will evaluate to False. ❑ C. The expression perm2.IsSubsetOf(perm1) will evaluate to True. ❑ D. The expression perm2.IsSubsetOf(perm1) will evaluate to False.
Question 60 You are developing a serviced component named Controller. You have enabled role-based security for this component. You do not want to invoke any methods of the Controller component if the security of the component is turned off (for example, using the Windows Component Services administrative tool). Which of the following modifications should you make to your serviced component?
399 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#2. ❍ A. Add the following code to the methods of the Controller class: If Not ContextUtil.SecurityEnabled() Then throw new SecurityException( _ “Security must be enabled” & _ “ for this method to execute successfully”) End If
❍ B. Add the following code to the methods of the Controller class: If Not ContextUtil.SecurityEnabled() Then ContextUtil.DisableCommit() End If
❍ C. Apply the following attribute to the Controller class:
❍ D. Apply the following attribute to the Controller class:
Question 61 Your assembly is a member of five code groups, as follows: ➤ EnterpriseA, at the enterprise level, grants Registry, Environment, FileDialog, and FileIO permissions to the code. ➤ EnterpriseB, at the enterprise level, grants FileDialog permissions to the code. ➤ MachineA, at the machine level, grants Registry, Environment, and FileIO permissions to the code. ➤ MachineB, at the machine level, grants Environment and FileIO permissions to the code. This code group has its LevelFinal bit set. ➤ UserA, at the user level, grants FileIO permissions to the code.
Which of these permissions will the code be granted as a result of its membership in these code groups? ❍ A. FileIO ❍ B. Registry, Environment, and FileIO ❍ C. Registry, Environment, FileIO, and FileDialog ❍ D. FileDialog, Environment, and FileIO
400 Chapter 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 62 You have written a serviced component and now need to debug it when it’s being used by a client process. The serviced component is stored in a file named Books.dll and is a Library application. The client process is named OrderBooks.exe. To which process should you attach the debugger to trace calls within the serviced component? ❍ A. Books.dll ❍ B. OrderBooks.exe ❍ C. aspnet_wp.exe ❍ D. dllhost.exe
Question 63 Your serviced component’s method fails when a particular variable equals 197. Unfortunately, you cannot predict when this will happen. You want to write minimal code. Which debugging tool should you use to investigate the problem? ❍ A. Locals window ❍ B. Output window ❍ C. Immediate window ❍ D. Conditional breakpoint
Question 64 You are using IIS to authenticate users of an ASP.NET application. Part of your corporate security guidelines states that passwords must never cross the Internet in clear text. Which authentication methods can you use? [Select two.] ❑ A. Anonymous ❑ B. Basic ❑ C. Digest ❑ D. Windows integrated
401 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Practice . . . . Exam . . . .#2.
Question 65 Your have developed a serviced component named Inventory that is a part of the Warehouse COM+ application. You have applied the SecurityRole attribute on the serviced component to allow access to only the members of the Controller and Vendors roles. As a result of a recent acquisition, you now have a new group of users, named Suppliers, that needs to be assigned to the Vendors role. Which of the following actions should you take? ❍ A. Use the Component Services tool to add a new role named Suppliers. ❍ B. Use the Component Services tool to add the Suppliers group to the existing Vendors role. ❍ C. Add another SecurityRole attribute to the Inventory class for the Suppliers group. ❍ D. Modify the Vendors SecurityRole attribute on the Inventory class to include the Suppliers group.
16 Answer Key for Practice Exam #2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Answer Key 1. B
17. D
33. C
2. B
18. C
34. D
3. A
19. B
35. D
4. D
20. C
36. A
5. B and D
21. A
37. A and D
6. C
22. B and D
38. C
7. D
23. D
39. A
8. A
24. B
40. A
9. C
25. A
41. C
10. C
26. A
42. C
11. A
27. B
43. A
12. B
28. B
44. C
13. D
29. A
45. C
14. C
30. C
46. B
15. D
31. C
47. C
16. D
32. B
48. D
404 Chapter 16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49. B
55. A
61. B
50. D
56. C
62. B
51. C
57. A
63. D
52. D
58. D
64. C and D
53. C and D
59. A and D
65. B
54. A and E
60. A
Detailed Answers Question 1 Answer B is correct. SingleCall SAOs have no state, so they’re easy to loadbalance just by adding new servers. Answer A is incorrect because Singleton SAOs maintain state and therefore are not suited for a load-balancing environment. Answers C and D are incorrect because for a heavily loaded application, SAOs are preferable to CAOs because they do not transmit as much data across the network for each call.
Question 2 Answer B is correct. By creating an interface, you can expose the functionality to the clients without leaking any implementation details. Answer A is incorrect because if the client applications are written in C++, they will lose the benefits provided by the CLR to the managed code. Answer C is incorrect because if you remove the implementation code from the client’s copy of the Product class, the client’s application will not compile because of the missing implementation details of the Product class. Answer D is incorrect because by changing the type of the application, you will also require the client to have the implementation details of the Product class.
Question 3 Answer A is correct. To make efficient use of the features of IIS and ASP.NET from a remoting server and to not open the ports in the firewall for communication, you should use HttpChannel. For maximum interoperability with
405 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Answer . . . . .Key . . for . .Practice . . . . Exam . . . .#2.
clients across platforms and languages, you should use the SoapFormatter. Therefore, answers B, C, and D are incorrect.
Question 4 Answer D is correct. In this scenario, you need to register a client-activated remote object in the client’s application domain, which you can do using the RegisterActivatedClientType method. Answers A and B are incorrect because these options are used for creating server-activated objects. Answer C is incorrect because the RegisterActivatedServiceType method is used to register the CAO with the remoting system on the server rather than the client.
Question 5 Answers B and D are correct. The Serializable attribute indicates that the class containing this attribute can be serialized. If you want to control the serialization process, you should implement the ISerializable interface and provide the serialization logic in the GetObjectData method provided by the ISerializable interface. Therefore, even if you provide your own serialization logic, you need to mark the class with the Serializable attribute. Answer A is incorrect because the NonSerialized attribute is used when you don’t want to serialize a specific field of a class. Answer C is incorrect because the Order remote object consists of the Product object, and you don’t want the Product object to become a marshal-by-reference object.
Question 6 Answer C is correct. Because the remote object is hosted in IIS, the remote object can only be accessed using the HTTP channel, and the remote object can only be activated as a server-activated object. Answers A and B are incorrect because IIS activation does not support the TCP channel. Answer D is incorrect because IIS cannot activate the remote object as a client-activated object.
406 Chapter 16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 7 Answer D is correct. The issue in question is not speed but responsiveness. This behavior occurs because the Windows application is calling the methods on the remote object synchronously. You can make the user interface more responsive by simply calling the remote method asynchronously. Answer A is incorrect because switching to the binary formatter also will make the application nonresponsive until the remote method is executed. Answer B is incorrect because IIS does not support the TCP channel. Answer C is incorrect because no modifications are needed on the remotable object to achieve this behavior.
Question 8 Answer A is correct. The Web methods exposed by a Web service are only those declared Public and are decorated with the WebMethod attribute. Answer B is incorrect because until a method is decorated with the WebMethod attribute and defined as Public, it will not be exposed from the Web service. Answers C and D are incorrect because you are not required to use either UDDI or WSDL with a Web service.
Question 9 Answer C is correct. Specifying a unique namespace for the new object removes the chance that it can clash with a preexisting object name, and this does not require you to change any existing code. Answer A is incorrect because renaming the existing class might break the applications that use this class. Answer B is incorrect because you might lose the changes whenever you regenerate the proxy class. Answer D is incorrect because the /out option will only change the output filename for the generated proxy; it will have no impact on the name of the proxy class generated.
Question 10 Answer C is correct. The .NET Web services can serialize complex objects and pass SOAP messages containing these objects across firewalls and across language boundaries. However, the client application must contain information about how to reconstitute the object, including a reference to the
407 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Answer . . . . .Key . . for . .Practice . . . . Exam . . . .#2.
object’s definition. Answer A is incorrect because the languages in which the Web service and client project are written can be different. Answer B is incorrect because if SOAP calls were blocked by the firewall, you would not be able to call any method on the Web service. Answer D is incorrect because the Hashtable class is defined with the Serializable attribute. Therefore, the Hashtable object can be serialized.
Question 11 Answer A is correct. The GetInitializer method is called once when the SOAP extension is first invoked, and it’s the appropriate event for one-time resource setup. Answer B is incorrect because the Initialize method is called every time the SOAP extension is invoked. Answer C is incorrect because the ChainStream method enables you to intercept the actual SOAP message stream and therefore is not the right place to perform a one-time setup. Answer D is incorrect because the ProcessMessage method is called with actual SOAP message requests and responses.
Question 12 Answer B is correct. This SOAP extension needs to monitor and alter the XML messages that are sent from client to server. These messages are available on the client only in the AfterSerialize stage. Therefore, answers A, C and D are incorrect.
Question 13 Answer D is correct. Using the callback is the most efficient way to manage use of your threads because the callback methods do not block threads while waiting for the response. Answers A and C are incorrect because the WaitAll and WaitAny methods of the WaitHandle object will block the thread until the Web service calls have completed. Answer B is incorrect; the End method will not return until the asynchronous operation is complete because this method uses IAsyncResult.AsyncWaitHandle to check for the Web service completion.
408 Chapter 16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 14 Answer C is correct. To minimize the hit to the ERP system and improve the performance of the Web service, you can use session state to store the order details placed in the last six months by the customer. Answer A is incorrect because enabling the CacheDuration attribute will not reduce the hits to the ERP system; it will only improve the performance of the Web service if the order details of a particular order are requested more than once. Answer B is incorrect because response buffering will make the Web service appear more slow because the response will be buffered until the whole response is created. Answer D is incorrect because the application state cannot be used to store customer-specific data; the application state is global to the application.
Question 15 Answer D is correct. A client certificate contains identification information about the user and the organization that issued the certificate, as well as a public key. You can use client certificate authentication, along with SSL encryption, to implement a highly secure method for verifying the identity of your users. Answers A and B are incorrect because these techniques require passing the authentication information, such as username and password, across the network. Answer C is incorrect because Windows integrated authentication is only useful within a Windows network; in this type of authentication, the username and password are not sent across the network.
Question 16 Answer D is correct. The XmlElement attribute lets you alter the SOAP requests sent to the server without changing any of your code. Answers A and C are incorrect because these options will not alter the name of the parameter in the SOAP messages. Answer B is incorrect because it involves additional effort.
Question 17 Answer D is correct. A Windows service application is a long-running executable application that runs in its own Windows process and therefore enables you to monitor the network on an ongoing basis. Answers A, B, and
409 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Answer . . . . .Key . . for . .Practice . . . . Exam . . . .#2.
C are incorrect because these types of applications need to be explicitly invoked to take an action.
Question 18 Answer C is correct. The ServiceController.GetServices method returns a list of the Windows services installed on the computer. Answers A, B, and D do not allow you to enumerate the list of Windows services installed on the computer.
Question 19 Answer B is correct. You must always handle start requests from the Service Control Manager by implementing an OnStart event handler. The other event handlers are required to be implemented only when you want to provide stop, pause, and continue features to your Windows service. Therefore, answers A, C, and D are incorrect.
Question 20 Answer C is correct. By providing a hard-coded GUID for the component, you prevent the registration process from generating a new GUID each time the component is registered with COM+. Answer A is incorrect because even if the serviced component is built in release mode, it would generate a new GUID for the component unless the Guid attribute is already specified. Answer B is incorrect because object pooling comes into the picture only after the serviced component is registered. Answer D is incorrect because by specifying the ClassInterface attribute as ClassInterfaceType.None, you would register the component with the specified interface but you would also generate a new GUID if the Guid attribute is not specified.
Question 21 Answer A is correct. After the pool of objects is exhausted, further requests are queued until an object is available or until the specified timeout period elapses. If an object cannot be made available within the time specified in the CreationTimeOut property, an exception is thrown. Therefore, answers B, C, and D are incorrect.
410 Chapter 16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 22 Answers B and D are correct. The SetComplete method call sets both the consistent bit and the done bit to True, so the transaction can be committed. The EnableCommit method call sets the consistent bit to True but leaves the done bit set to False, which also allows committing the transaction but does not deactivate the object. Answers A and C are incorrect because these methods set the consistent bit to False, which aborts the transaction.
Question 23 Answer D is correct. The interface that a queued component uses for queuing must have Sub procedures having only pass-by-value parameters. Therefore, you need to change the definition of the Ship method from a Function to a Sub procedure, which does not return any value. Answer A is incorrect because the AutoComplete attribute automatically notifies the COM+ context about its success or failure when the method completes. Answer B is incorrect because the ApplicationQueuing attribute is applied to the assembly to enable queuing support for the COM+ application. Answer C is incorrect because the current InterfaceQueuing attribute definition for the ShipPaints class is correct and required.
Question 24 Answer B is correct. When using the Credentials property, a XML Web service client must instantiate a class implementing ICredentials, such as NetworkCredential, and then set the client credentials specific to the authentication mechanism, such as Basic. Answer A is incorrect because you must pass the authentication information (username and password) to the constructor of the NetworkCredential class. Answers C and D are incorrect because you cannot assign a value of type CredentialCache to a variable of type ICredentials.
Question 25 Answer A is correct. ComponentWare should create a Primary Interop Assembly for the COM components by using the Type Library Importer tool (tlbimp.exe), such that a COM component can be called by .NET.
411 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Answer . . . . .Key . . for . .Practice . . . . Exam . . . .#2.
Answer B is incorrect because the Type Library Exporter tool creates a Type Library Definition for a .NET component to be used by a COM component. Answer C is incorrect because a large number of applications use the COM components. Answer D is incorrect because Platform Invoke is used to call functions from unmanaged libraries rather than COM components.
Question 26 Answer A is correct. Because only one application is using the COM component, the quickest way to create the RCW and have the COM component available in your Visual Basic .NET project is to use the Add Reference dialog box to add a direct reference to the COM component. Answers B and C are incorrect because the COM component is not shared by multiple applications. Therefore, you need not use the Type Library Importer tool to generate an RCW for the COM component. Answer D is incorrect because the PInvoke feature is used to call functions from unmanaged libraries, such as Win 32 API libraries, rather than the COM component libraries.
Question 27 Answer B is correct. In the calls via Platform Invoke, you should use StringBuilder rather than String to hold a string buffer that expects to be modified by the function. Therefore, answers A, C, and D are incorrect.
Question 28 Answer B is correct. A simple type can be modified by facets, which enable you to specify data restrictions such as minimum, maximum, and exact length. Answers A and C are incorrect because when you define a field with an element or an attribute, there are no restrictions on that field beyond those imposed by the data type you choose for the element or attribute. Answer D is incorrect because complex types are used for fields that contain several pieces of information, not a single type.
Question 29 Answer A is correct. The ApplyDefaultSort property is used to automatically create a sort order, in ascending order, based on the primary key of the
412 Chapter 16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
table. The ApplyDefaultSort property only applies when the table has a primary key defined and the Sort property is Nothing or an empty string. Answer B is incorrect because you want to sort using the primary key, and for that you should set the ApplyDefaultSort property to True. Answer C is incorrect because you need to sort the data instead of filtering the data. Answer D is incorrect because the given code segment is incorrect; you must specify the name of a column in the Sort property along with ASC or DESC.
Question 30 Answer C is correct. When you use the Close method on a SqlConnection object, the connection is closed, all pending database transactions are rolled back, and the connection is returned back to the connection pool. Answer A is incorrect because reusing an instance after you have called the Dispose method may result in undesirable effects. In general, you should use the Close method rather than the Dispose method if you might want to reuse the connection instance. Answer B is incorrect because you should generally call the Finalize method only when you need to release unmanaged resources. Answer D is incorrect because setting the SqlConnection object to Nothing will not actually close the connection; instead, the object will continue to exist in memory, waiting for garbage collection.
Question 31 Answer C is correct. A DataRelation object is used to relate two DataTable objects to each other. Once you create a DataRelation object, you can call the GetChildRows or GetParentRows method of the DataRow object to fetch child rows or the parent rows, respectively. Answers A and B are incorrect because just defining primary keys or foreign keys on the table will not relate the tables. Answer D is incorrect because the DataSet.Merge method is used to merge two DataSet objects, which is not a requirement in this case.
Question 32 Answer B is correct. The XmlValidatingReader object allows you to validate an XML document. You use its ValidationEventHandler event to set an event handler for receiving information about the schema-validation errors. Answer A is incorrect because the XmlDocument object cannot validate the XML document on its own. Answer C is incorrect because the
413 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Answer . . . . .Key . . for . .Practice . . . . Exam . . . .#2.
EnforceConstraints property of the DataSet is used to specify whether the database constraint rules are followed when attempting any update operation. Answer D is incorrect because the DataSet.MergeFailed event occurs only when a target and source DataRow have the same primary key value, and EnforceConstraints is set to True.
Question 33 Answer C is correct. You’re interested in the total cost of visits, so you must use the Sum() operator on the VisitCost column. To filter after the sum is taken, you must use a HAVING clause. Answers A and B are incorrect because the WHERE clause is used to filter the data to include only individual rows where the cost is at least $100; the filter is not performed after the data is grouped. Answer D is incorrect because you need to display details for all patient visits for patients spending a total of $100 on these visits, rather than displaying individual visits that cost more than $100.
Question 34 Answer D is correct. OleDbDataReader allows you to read the data one row at a time in a forward-only fashion; therefore, it occupies less memory and improves the performance of your application. The question requires you to read the data in a sequential fashion and write it to the flat file. Therefore, the OleDbDataReader object is the best option. Answer A is incorrect because a DataSet object loads the entire set of retrieved data into memory. Answer B is incorrect because you cannot retrieve the data directly in a DataTable object. Answer C is incorrect because a SqlDataReader object only works with SQL Server 7.0 and later versions.
Question 35 Answer D is correct. Because other operations on the database, such as add and update, are working fine, chances are that the DeleteCommand property is not set. The DeleteCommand property should be set to a command that deletes rows from the database. Answers A and C are incorrect because if either were the case, none of the changes would be saved. Answer B is simply incorrect because if the DeleteCommand property was set correctly, a call to the Update method would also have executed DeleteCommand.
414 Chapter 16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 36 Answer A is correct. While creating a SqlParameter object, you specify SQL Server data types using the SqlDbType enumeration rather than specify the .NET Framework data types. The @SalesID parameter is defined as an output parameter in the stored procedure; therefore, the Direction property of the SqlParameter object should be set to Output. Answer B is incorrect because the Direction property is set to ReturnValue, which specifies that the parameter must represent a return value from a stored procedure. Answers C and D are incorrect because you should specify SQL Server data types when creating a SqlParameter object.
Question 37 Answers A and D are correct. In the current scenario, the XmlReadMode.Auto and XmlReadMode.InferSchema options will infer schema from the data. Answer B is incorrect because the data in the Orders.xml file is not a DiffGram. Answer C is incorrect because when XmlReadMode is set to Fragment, the default namespace is read as the inline schema. Answer E is incorrect because the XML file does not include any schema.
Question 38 Answer C is correct. The SqlCommand.Prepare method creates a prepared version of the command on an instance of SQL Server. Once the command has been prepared, further execution of that command will be comparatively faster. Answer A is incorrect because the SqlCommand.ExecuteReader method is generally used to execute query statements such as SELECT statements rather than nonquery statements such as INSERT statements. Answer B is incorrect because if SQL Server needs to prepare the command with each execution, performance will decrease instead of increase. Answer D is incorrect because the SqlCommand.ResetCommandTimeout method just resets the CommandTimeout property to its default value and does not play any role in optimizing the performance in the given scenario.
415 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Answer . . . . .Key . . for . .Practice . . . . Exam . . . .#2.
Question 39 Answer A is correct. Parameterized stored procedures are faster and more secure than ad hoc SQL statements. Answer B is incorrect because the DataSet object approach would result in all rows of the table being transferred to the client, which would perform very poorly. Answer C is incorrect because an ad hoc SQL statement runs slower when compared to a parameterized stored procedure. Answer D is incorrect because a view cannot contain parameters, so you’d need to build a new view for every request.
Question 40 Answer A is correct. If you do not specify the command type of a SqlCommand object, it defaults to CommandType.Text, which will not work with a stored procedure. Answer B is incorrect because although you could also make the code work by using an ad hoc SQL statement, it is an undesirable solution; the code will run more slowly and be less secure. Answer C is incorrect because the SqlDataReader object will also use the same command for executing the procedure. Therefore, you need to set the right CommandType of the SqlCommand object to CommandType.StoredProcedure for the code to work. Answer D is incorrect because when using the Fill method, you are not required to open the connection explicitly.
Question 41 Answer C is correct. Setting the RowStateFilter property of the DataView object to DataViewRowState.Deleted specifies that you want to view the deleted rows from the original data. Answers A and B are incorrect because the RowFilter property is used to filter rows based on an expression rather than their state. Answer D is incorrect because setting the RowStateFilter property to DataViewRowState.OriginalRows displays the original data of all the rows, including deleted rows.
Question 42 Answer C is correct. The ReadXmlSchema method maps nested elements in the XML file to related DataTable objects in the DataSet object. At the leaf level of the DOM tree, both elements and attributes are mapped to DataColumn objects. Therefore, answers A, B, and D are incorrect.
416 Chapter 16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 43 Answer A is correct. The DocumentElement property of an XmlDocument object returns an XmlNode object that represents the root node in the underlying XML document. Answers B and D are incorrect because the DocumentElement and DocumentType properties are members of the XmlDocument class rather than the XmlNode class. Answer C is incorrect because the DocumentType property returns an XML node containing the DOCTYPE declaration for the XML document rather than its root element.
Question 44 Answer C is correct. Because Volts is an attribute rather than an element, you must refer to it as @Volts in an XPath expression. To select this attribute wherever it appears in the XML file, you should use // as the current context to cause the search to start at the root of the file. Therefore, answers A, B, and D are incorrect.
Question 45 Answer C is correct. The SqlXmlCommand object is supplied as part of the SQLXML download package. It is not installed with the base .NET Framework. Answer A is incorrect because you are using the correct path to refer to the DiffGram files. Answer B is incorrect because .NET Framework SP2 does not contain the SQLXML download package. Answer D is incorrect because the connection string already specifies a connection to the locally running SQL server on the production server.
Question 46 Answer B is correct. For booleanSwitch, a value of 0 corresponds to Off, and any nonzero value corresponds to On. For traceSwitch, any number greater than 4 is treated as Verbose. From the given values in the configuration file, the booleanSwitch object will have its Enabled property set to True, and the traceSwitch object will have its Level property set to TraceLevel.Verbose. Answers A, C, and D are incorrect because the booleanSwitch.Enabled property is set to True instead of False.
417 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Answer . . . . .Key . . for . .Practice . . . . Exam . . . .#2.
Question 47 Answer C is correct. The element allows you to override publisher policy for a single application. Answer A is incorrect because copying the assembly will have no effect on the binding, which is satisfied from the GAC. Answers B and D are incorrect because adding an administrator policy or deleting the publisher policy affects all applications on the computer, not just the one application.
Question 48 Answer D is correct. If you get a DCOM configuration error while debugging, you might not be a member of the Debugger Users group on the remote machine. To resolve this, you add your account on the remote machine to the Debugger Users group. Answers A and B are incorrect because to debug a program remotely using Visual Studio .NET, you should be a member of the Debugger Users group rather than the Main Users group. Answer C is incorrect because you should be a member of the Debugger Users group on the remote computer rather than on the local computer.
Question 49 Answer B is correct. The Assert method checks for the given condition and generates an error when the condition evaluates to False. Answer A is incorrect because this code segment will only generate an error when the value of TotalShipments is not equal to zero. Answers C and D are incorrect because the Debug.Assert method is invoked only when the program is complied using the Debug configuration.
Question 50 Answer D is correct. The TraceSwitch class provides a multilevel switch to control tracing output without recompiling your code. Answer A is incorrect because the /d:TRACE option just enables the tracing; it does not allow multilevel control over tracing output. Answer B is incorrect because modifying environmental variables requires much more administrative effort when compared to a configuration file. Answer C is incorrect because this option requires the program to be recompiled each time the value of TRACE is modified.
418 Chapter 16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 51 Answer C is correct. Answers A, B and D are incorrect because the TRACE symbol is defined in both the default Debug and the default Release configurations. Only the DEBUG symbol is defined in the default Debug configuration.
Question 52 Answer D is correct. To enable tracing for all the pages of the Web application, you should enable tracing in the application configuration file, Web.config. To view the tracing information in the Web page, you should set the pageOutput attribute to True. To store tracing information for more requests, you should set the requestLimit attribute to a larger number. Finally, to be able to access the tracing information from the trace viewer in the tester’s desktop, the localOnly attribute should be set to False. Answers A and B are incorrect because you want to view tracing information for a larger number of requests. Answers C and F are incorrect because they disable tracing for the entire Web application. Answer E is incorrect because the localOnly attribute is set to True. The localOnly attribute indicates whether the tracing information should be available only in hosting Web server or all the clients (local as well as remote).
Question 53 Answers C and D are correct. Because the Warehousing application is the only application that uses the component, the development team should copy the component to the Warehousing application. The development team can now create a Web Setup project to deploy the application and component. Answers A and B are incorrect because the Merge Module projects are used to create reuseable setup components.
Question 54 Answers A and E are correct. If you want multiple applications to use an assembly, you need to sign the assembly with a strong name and place the assembly into the Global Assembly Cache. Answer B is incorrect because a COM application is not using the assembly. Answers C and D are incorrect because assemblies cannot be deployed into the Global Assembly Cache via XCOPY or FTP.
419 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Answer . . . . .Key . . for . .Practice . . . . Exam . . . .#2.
Question 55 Answer A is correct. The SqlException.Class property gets a value from 1 to 25 that indicates the severity level of the error. Answer B is incorrect because the SqlException.Source property gets the name of the provider that generated the error. Answer C is incorrect because the SqlException.Server property gets the name of the computer running an instance of SQL Server that generated the error. Answer D is incorrect because the SqlException.State property gets a numeric error code from SQL Server that represents an error, warning, or “no data found” message.
Question 56 Answer C is correct. Multiple versions of the same assembly can exist side by side in the GAC. In the absence of a policy to the contrary, .NET applications use only the version of an assembly with which they were originally compiled. Therefore, answers A, B, and D are incorrect.
Question 57 Answer A is correct. When you want to check whether a particular user belongs to a particular role, or whether the user has a particular privilege, you need to perform role-based security. Answer B is incorrect because the application requires access to the BalanceSheet object for specific users. Answer C is incorrect because encryption makes the data more difficult to read but does not restrict the code from performing certain operations. Answer D is incorrect because type safety only allows code to access primary memory locations it is authorized to access. Type safety has no control over the application-specific operations.
Question 58 Answer D is correct. You must tell the CLR how users are authenticated, even when you are using a Windows application that automatically employs Windows authentication. Answers A, B, and C are incorrect because they do not specify the authentication mode.
420 Chapter 16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question 59 Answers A and D are correct. The object perm2 is a union of all the three PrincipalPermission objects (pp1, pp2, and pp3). The object perm1 is the union of two PrincipalPermission objects (pp1 and pp2). As a result, perm1 is a subset of perm2 and not vice versa. Answer B is incorrect because perm1 is a subset of perm2. Answer C is incorrect because perm2 is not a subset of perm1.
Question 60 Answer A is correct. This code segment checks whether role-based security is active in the current context and, if it is not, throws a security exception. Answer B is incorrect because the ContextUtil.DisableCommit method only affects the settings of the consistent and done bits in the COM+ context. Answers C and D are incorrect because the value of these attributes will be ignored if the security of the component has been disabled.
Question 61 Answer B is correct. At each level, the permissions are the union of all permissions granted at that level. So this gives you Registry, Environment, FileDialog, and FileIO permissions at the enterprise level; Registry, Environment, and FileIO permissions at the machine level; and FileIO permissions at the user level. The total permissions are the intersection of the level permissions. However, because the MachineB code group has the LevelFinal bit set, this assembly will not consider the user-level permissions. So the final effective permissions are the intersection of the machine and enterprise permissions, thus making answers A, C, and D incorrect.
Question 62 Answer B is correct. A serviced component, which is activated as a Library application, runs in the client application’s process. Therefore, to debug the serviced component, you need to attach a debugger to the client application’s process. Answer A is incorrect because you need to attach a debugger to the client application’s process rather than the service component assembly. Answer C is incorrect because the client application’s process is not a Web
421 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Answer . . . . .Key . . for . .Practice . . . . Exam . . . .#2.
application running under ASP.NET. Answer D is incorrect because the serviced component is activated as a Library application rather than as a Server application.
Question 63 Answer D is correct. A conditional breakpoint lets you pause your code only when a particular condition is True. In this case, you can use that capability to break into the code when the variable has the value of 197. Answers A, B, and C are incorrect because they do not work conditionally.
Question 64 Answers C and D are correct. Digest authentication encrypts the password before it crosses the Internet, and Windows integrated authentication uses either Kerberos or challenge/response to keep passwords off the wire entirely. Answer A is incorrect because Anonymous authentication does not actually authenticate users at all. Answer B is incorrect because Basic authentication transmits passwords in plain text.
Question 65 Answer B is correct. All you need to do is to add the Suppliers group to the existing Vendors role. Answers A, C, and D are incorrect because the existing Vendors role is sufficient for the given requirement. All you need to do is assign the new users to the Vendors role.
A ADO.NET Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
If you just read the objectives for the 70-310 exam, you might think that it doesn’t cover ADO.NET. But even though there are no direct ADO.NET objectives, you’ll find that this knowledge is a prerequisite to passing the exam. In this appendix, I’ll briefly outline ADO.NET. If you haven’t worked with ADO.NET, you should consult some of the references listed at the end of this appendix before taking the exam.
ADO.NET Architecture ADO.NET is the overall name for the set of classes (spread across a number of namespaces, including System.Data, System.Data.Common, System.Data.SqlTypes, System.Data.SqlClient, and System.Data.OleDb) that the .NET Framework provides for working with data in relational databases. The ADO.NET object model is broken up into two distinct sets of objects—data provider objects and DataSet objects—because the .NET Framework separates the task of using data from the task of storing data. The DataSet objects provide a memory-resident, disconnected set of objects that you can load with data. The data provider objects handle the task of working directly with data sources. One of the provider objects, the DataAdapter object, serves as a conduit between the two sets of objects. By using a DataAdapter, you can load data from a database into a DataSet and later save changes back to the original data source. Figure A.1 shows schematically how these two sets of objects fit together in the overall ADO.NET architecture.
424 Appendix A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Provider Objects Connection
Command
Parameter
DataAdapter
DataReader
DataSet Objects DataSet
Relations
Tables
DataRelation
DataTable
DataView
Rows
Columns
Constraints
DataRow
DataColumn
Constraint
Figure A.1 The ADO.NET architecture.
The ADO.NET Object Model ADO.NET consists of two sets of objects: data provider objects and DataSet objects. In generic terms, the data provider objects manage the database for your application, and the DataSet objects manage the data model for the application.
Data Providers and Their Objects The first set of classes in ADO.NET come from the data providers. These classes have specific implementations for each type of data you might work with. You should know about the five main data provider objects: ➤ Connection ➤ Command ➤ Parameter
425 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ADO.NET . . . . . .Basics . . . ➤ DataReader ➤ DataAdapter
These are the generic names for the classes defined in System. Data.Common. In fact, you’ll seldom (if ever) write code that uses these generic objects. Each data provider has implementations of these objects with specific names. A data provider is a namespace that implements these five classes (and some other classes and enumerations) for use with a particular database. For example, you can work with data stored in a SQL Server database by using the SQL Server data provider, which is implemented in the System. Data.SqlClient namespace. In this namespace, the class names are as follows: ➤ SqlConnection ➤ SqlCommand ➤ SqlParameter ➤ SqlDataReader ➤ SqlDataAdapter
But the SQL Server data provider is not the only alternative for retrieving data in ADO.NET. The .NET Framework also ships with the OLE DB data provider, implemented in the System.Data.OleDb namespace. In this namespace, the corresponding class names are as follows: ➤ OleDbConnection ➤ OleDbCommand ➤ OleDbParameter ➤ OleDbDataReader ➤ OleDbDataAdapter
Although from the name it seems that the OLE DB data provider should work with any existing OLE DB provider, that’s not the case. It’s only designed to work with the SQL Server, Jet 4.0, and Oracle OLE DB providers. Other providers might work but are not supported.
Although .NET Framework 1.0 only includes two data providers, other alternatives exist. For example, Microsoft released both an ODBC data
426 Appendix A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
provider and an Oracle data provider as add-ons to .NET Framework 1.0, and included them in .NET Framework 1.1. Third parties are also beginning to release other providers. The exam will likely use SQL Server provider objects in its examples, so I’ll use only those objects for examples in this appendix. But keep in mind that other alternatives exist.
The SqlConnection Class The SqlConnection class represents a single persistent connection to a SQL Server data source. ADO.NET automatically handles connection pooling, which contributes to better application performance by eliminating the overhead involved in constantly creating and destroying connections. When you call the Close method of a SqlConnection object, it is returned to a connection pool. Connections in a pool are not immediately destroyed by ADO.NET. Instead, they’re available for reuse if another part of your application requests a SqlConnection that matches in detail a previously closed SqlConnection.
The SqlCommand and SqlParameter Classes The SqlCommand and SqlParameter classes work together to retrieve data from a data source after you’ve made a connection. The SqlCommand represents something that can be executed. This could be an ad hoc query string or a stored procedure name. A SqlParameter object represents a single parameter to a stored procedure.
The SqlDataReader Class The SqlDataReader class is designed to be the fastest possible way to retrieve a resultset from a database. SqlDataReader objects can only be constructed by calling the ExecuteReader method of a SqlCommand object. The resultset contained in a SqlDataReader is forward-only, read-only. That is, you can only read the rows in the resultset sequentially from start to finish, and you can’t modify any of the data. This behavior, of simply delivering data as quickly as possible, results in the SqlDataReader being called a “fire hose” data connection. You can think of the SqlDataReader as a data structure that can contain one row of data at a time. Each call to the SqlDataReader.Read method loads the next row of data into this structure. When there are no more rows to load, the Read method returns False, which tells you that you’ve reached the end of the data.
427 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ADO.NET . . . . . .Basics . . .
The SqlDataAdapter Class The final data provider class I’ll consider, SqlDataAdapter, provides a bridge between the data provider objects and the DataSet classes I’ll review in the next section. You can think of SqlDataAdapter as a two-way pipeline between the data in its native storage format and the data in a more abstract representation (the DataSet) designed for manipulation in your application.
The DataSet Classes The second set of ADO.NET classes is the DataSet classes, which are all contained in the System.Data namespace. Unlike the data provider classes, there’s only one set of DataSet classes. The DataSet classes represent data in an abstract form that’s not tied to any particular database implementation. In this section, I’ll introduce you to the DataSet and the other classes it contains. There are six objects you should know about: ➤ DataSet ➤ DataTable ➤ DataRelation ➤ DataRow ➤ DataColumn ➤ DataView
The DataSet Object The DataSet itself is a self-contained memory-resident representation of relational data. A DataSet contains other objects, such as DataTables and DataRelations, that hold the actual data and information about the design of the data. The DataSet is designed to be easy to move between components. In particular, specific methods convert a DataSet to an XML file, and vice versa. Because they’re easily serialized, DataSets can also be passed between remoted components or Web service servers and clients. As a part of the .NET Framework, DataSet classes are currently “Microsoft only.” Returning a DataSet from a Web service may make it more difficult for clients written in non-.NET platforms to use.
428 Appendix A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Table A.1 shows the most important members of the DataSet class. Table A.1 Selected DataSet Class Members Member
Type
Description
AcceptChanges
Method
Marks all changes in the DataSet as having been accepted
Clear
Method
Removes all data from the DataSet
GetChanges
Method
Gets a DataSet that contains only the changed data in this DataSet
GetXml
Method
Gets an XML representation of the DataSet
GetXmlSchema
Method
Gets an XSD representation of the DataSet
Merge
Method
Merges two DataSets
ReadXml
Method
Loads the DataSet from an XML file
ReadXmlSchema
Method
Loads the DataSet’s schema from an XSD file
Relations
Property
A collection of DataRelation objects
Tables
Property
A collection of DataTable objects
WriteXml
Method
Writes the DataSet to an XML file
WriteXmlSchema
Method
Writes the DataSet’s schema to an XSD file
The DataTable Object The DataTable class represents a single table within the DataSet. A single DataSet can contain many DataTable objects. You can manipulate a DataTable as either a collection of DataColumn objects or a collection of DataRow objects. The DataTable also provides events that you can use to monitor data changes. For example, you might bind a DataTable to a DataGrid control and use these events to track the user’s operations on the data within the DataGrid.
The DataRelation Object As mentioned earlier, the DataSet can represent an entire relational database. The DataRelation object stores information on the relations between DataTables within a DataSet.
The DataRow Object As you can guess by now, the DataRow represents a single row of data. When you’re selecting, inserting, updating, or deleting data in a DataSet, you’ll normally work with DataRow objects. Table A.2 shows the most important members of the DataRow class.
429 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ADO.NET . . . . . .Basics . . . Table A.2 Selected DataRow Class Members Member
Type
Description
BeginEdit
Method
Starts editing the DataRow
CancelEdit
Method
Discards an edit in progress
Delete
Method
Deletes the DataRow from its parent DataTable
EndEdit
Method
Ends an edit in progress, saving the changes
Item
Property
Returns the data from a particular column in the DataRow
IsNull
Method
Returns True if a specified column contains a Null value
RowState
Property
Returns information on the current state of a DataRow (for example, whether it has been changed since it was last saved to the database)
The DataColumn Object The DataTable also contains a collection of DataColumn objects. A DataColumn represents a single column in the DataTable. By manipulating the DataColumn objects, you can determine and even change the structure of the DataTable.
The DataView Object Finally, the DataView class represents a view of the data contained in a DataTable. A DataView might contain every DataRow from the DataTable, or it might be filtered to contain only specific rows. Filtering can be done by SQL expressions (returning, for example, only rows for customers in France) or by row state (returning, for example, only rows that have been modified).
Using DataSets Now that you’ve seen the ADO.NET objects, it’s time to see what you can do with them. Of course, in a single appendix I can’t possibly cover everything you can do with ADO.NET. Therefore, I’m going to concentrate on some of the basic operations, including the following: ➤ Populating a DataSet from a database ➤ Moving around in DataSets and retrieving data ➤ Using DataSets with multiple tables ➤ Finding and sorting data in DataSets ➤ Editing data with ADO.NET
430 Appendix A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ➤ Updating data ➤ Adding data ➤ Deleting data
Populating a DataSet from a Database Before you can do anything with data in a DataSet, you must get the data into the DataSet. In general, you can follow a four-step pattern to move data from the database to a DataSet object: 1. Create a SqlConnection object to connect to the database. 2. Create a SqlCommand object to retrieve the desired data. 3. Assign the SqlCommand to object the SelectCommand property of a
SqlDataAdapter object. 4. Call the Fill method of the SqlDataAdapter object to actually place the
data in the DataSet. Here’s an example of this pattern in code: ‘ Create a SqlConnection Dim cnn As SqlConnection = _ New SqlConnection(“Data Source=(local);” & _ “Initial Catalog=Northwind;Integrated Security=SSPI”) ‘ Create a SqlCommand Dim cmd As SqlCommand = cnn.CreateCommand() cmd.CommandType = CommandType.Text cmd.CommandText = _ “SELECT * FROM Products ORDER BY ProductName” ‘ Set up the DataAdapter and fill the DataSet Dim da As SqlDataAdapter = New SqlDataAdapter() da.SelectCommand = cmd Dim ds As DataSet = New DataSet() ‘ Display the data on the user interface da.Fill(ds, “Products”)
This example demonstrates a couple shortcuts you can use in your ADO.NET code. First, the constructor for the SqlConnection object has an overloaded form that lets you supply the connection string when you create the object. Second, this code doesn’t call the Open and Close methods of the SqlConnection explicitly. Instead, it lets the SqlDataAdapter make those calls when it needs the data. Doing this not only cuts down the amount of code you need to write, it also improves the scalability of your application by keeping the SqlConnection open for the shortest possible period of time.
431 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ADO.NET . . . . . .Basics . . .
The second parameter to the DataAdapter.Fill method is the name of the DataTable that the method will create. The DataTable is then filled with the data supplied by the SelectCommand. The DataTable name does not have to match the table name in the underlying database. This example would work just as well if you placed data from the Products table into a DataTable named Starship (although that would be a pretty poor idea from the standpoint of code maintainability).
Moving Around in DataSets and Retrieving Data If you’re familiar with classic ADO, you’re used to Recordsets—collections of records that have a pointer to a current record. In classic ADO, you move through a Recordset with code such as this: Do Until rst.EOF rst.MoveNext Loop
DataSets have no equivalent to this code because DataSets have no concept of a current record pointer. Instead, you move through a DataSet by working with the collections that the DataSet contains, as shown in the following code example, which dumps the contents of a DataSet to a ListBox control named lbData: ‘ Create a SqlConnection Dim cnn As SqlConnection = _ New SqlConnection(“Data Source=(local);” & _ “Initial Catalog=Northwind;Integrated Security=SSPI”) ‘ Create a SqlCommand Dim cmd As SqlCommand = cnn.CreateCommand() cmd.CommandType = CommandType.Text cmd.CommandText = _ “SELECT * FROM Customers WHERE Country = ‘France’” ‘ Set up the DataAdapter and fill the DataSet Dim da As SqlDataAdapter = New SqlDataAdapter() da.SelectCommand = cmd Dim ds As DataSet = New DataSet() da.Fill(ds, “Customers”) ‘ Dump the contents of the DataSet Dim dt As DataTable Dim dr As DataRow Dim dc As DataColumn lbData.Items.Add(“DataSet: “ & ds.DataSetName) For Each dt In ds.Tables lbData.Items.Add(“ DataTable: “ & dt.TableName) For Each dr In dt.Rows lbData.Items.Add(“ DataRow”) For Each dc In dt.Columns lbData.Items.Add(“ “ & dr(dc)) Next Next Next
432 Appendix A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
This example shows how to visit every piece of data in a DataSet by a proper selection of nested For Each loops. It also shows a general syntax for retrieving data: Locate the data row and column whose intersection contains the data you’re interested in, and use the dr(dc) syntax to retrieve the actual data value. You can use a variety of other syntaxes to retrieve data. Given a DataTable variable named dt that refers to the data from the Customer table, for example, any of these statements will retrieve the value in the first column of the first row of data in the DataTable: dt.Rows(0).Item(0) dt.Rows(0)(0) dt.Rows(0).Item(“CustomerID”) dt.Rows(0)(“CustomerID”) dt.Rows(0)!CustomerID
DataSets with Multiple Tables The DataSets you’ve seen so far in this appendix have contained a single DataTable. But DataSets are not limited to a single DataTable; in fact, no practical limit exists on the number of DataTables a DataSet can contain. By using multiple DataAdapter objects, you can connect a single DataSet to more than one table in the SQL Server database. You can also define DataRelation objects to represent the relationship between the DataTables in the DataSet. This code demonstrates the use of the DataSet to hold a complex subset of a relational database: ‘ Create a SqlConnection and a DataSet Dim cnn As SqlConnection = _ New SqlConnection(“Data Source=(local);” & _ “Initial Catalog=Northwind;Integrated Security=SSPI”) Dim ds As DataSet = New DataSet() ‘ Add the customers data to the DataSet Dim cmdCustomers As SqlCommand = cnn.CreateCommand() cmdCustomers.CommandType = CommandType.Text cmdCustomers.CommandText = “SELECT * FROM Customers” Dim daCustomers As SqlDataAdapter = New SqlDataAdapter() daCustomers.SelectCommand = cmdCustomers daCustomers.Fill(ds, “Customers”) ‘ Add the Orders data to the DataSet Dim cmdOrders As SqlCommand = cnn.CreateCommand() cmdOrders.CommandType = CommandType.Text cmdOrders.CommandText = “SELECT * FROM Orders” Dim daOrders As SqlDataAdapter = New SqlDataAdapter() daOrders.SelectCommand = cmdOrders daOrders.Fill(ds, “Orders”) ‘ Add the Order Details data to the DataSet Dim cmdOrderDetails As SqlCommand = cnn.CreateCommand() cmdOrderDetails.CommandType = CommandType.Text cmdOrderDetails.CommandText = _
433 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ADO.NET . . . . . .Basics . . . “SELECT * FROM [Order Details]” Dim daOrderDetails As SqlDataAdapter = _ New SqlDataAdapter() daOrderDetails.SelectCommand = cmdOrderDetails daOrderDetails.Fill(ds, “OrderDetails”) ‘ Add Relations Dim relCustOrder As DataRelation = _ ds.Relations.Add(“CustOrder”, _ ds.Tables(“Customers”).Columns(“CustomerID”), _ ds.Tables(“Orders”).Columns(“CustomerID”)) Dim relOrderOrderDetails As DataRelation = _ ds.Relations.Add(“OrderOrderDetails”, _ ds.Tables(“Orders”).Columns(“OrderID”), _ ds.Tables(“OrderDetails”).Columns(“OrderID”))
This code uses three different SqlDataAdapter objects to move data from three different database tables into a single DataSet. The data from each SqlDataAdapter is stored in a separate DataTable. You could also use a single SqlDataAdapter object for the same purpose, by changing its SelectCommand property each time you want to load a separate table. The code then adds DataRelation objects to specify the relationships between these DataTables. The Add method of the DataSet.Relations collection takes three parameters: 1. A name for the DataRelation object to be created 2. The DataColumn object representing the primary key side of the rela-
tionship 3. The DataColumn object representing the foreign key side of the rela-
tionship
Finding and Sorting Data in DataSets The .NET Framework offers several object-oriented ways to find and sort data. You should know about two of these ways: the DataTable.Select method and the filtering and sorting capabilities of the DataView object. The Select method of the DataTable object is a convenient way to find particular DataRow objects within the DataTable. This method extracts an array of DataRow objects that you can work with. Follow these steps to see how: 1. Open a Visual Basic .NET Windows Application project. Add a new
form to the project. 2. Place a Button control named txtCountry,
btnSelect, a TextBox control named and a ListBox control named lbSelected on the form.
434 Appendix A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3. Double-click the Button control to open the form’s module. Enter
these statements at the top of the module: Imports System.Data Imports System.Data.SqlClient
4. Enter this code to handle the Click event of the Button control: Private Sub btnSelect_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnSelect.Click ‘ Create a SqlConnection Dim cnn As SqlConnection = _ New SqlConnection(“Data Source=(local);” & _ “Initial Catalog=Northwind;Integrated Security=SSPI”) ‘ Create a SqlCommand Dim cmd As SqlCommand = cnn.CreateCommand() cmd.CommandType = CommandType.Text cmd.CommandText = “SELECT * FROM Customers” ‘ Set up the DataAdapter and fill the DataSet Dim da As SqlDataAdapter = New SqlDataAdapter() da.SelectCommand = cmd Dim ds As DataSet = New DataSet() da.Fill(ds, “Customers”) ‘ Use the Select method to ‘ get a sorted array of DataRows Dim adr() As DataRow = ds.Tables(“Customers”).Select( _ “Country = ‘“ & txtCountry.Text & _ “‘“, “ContactName ASC”) ‘ Dump the result to the user interface lbSelected.Items.Clear() Dim dr As DataRow For Each dr In adr lbSelected.Items.Add(dr(0) & _ “ “ & dr(1) & “ “ & dr(2)) Next End Sub
5. Set the form as the startup object for the project. 6. Run the project. Enter a country name and click the button. You’ll see
the first three columns from DataRows for customers in that country, as shown in Figure A.2. The Select method of the DataTable constructs an array of DataRows based on up to three factors: a filter expression, a sort expression, and a state constant. Filter expressions are essentially SQL WHERE clauses constructed according to these rules: ➤ Column names containing special characters should be enclosed in
square brackets. ➤ String constants should be enclosed in single quotes.
435 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ADO.NET . . . . . .Basics . . . ➤ Date constants should be enclosed in pound signs. ➤ Numeric expressions can be specified in decimal or scientific notation. ➤ Expressions can be created using
AND, OR, NOT,
parentheses, IN, LIKE, com-
parison operators, and arithmetic operators. ➤ The
+
operator is used to concatenate strings.
➤ Either
* or % can be used as a wildcard to match any number of characters. Wildcards can be used only at the start or end of strings.
➤ Columns in a child table can be referenced with the expression Child.Column.
If the table has more than one child table, use the expression Child(RelationName).Column to choose a particular child table. ➤ The
Sum, Avg, Min, Max, Count, StDev,
and Var aggregates can be used with
child tables. ➤ Supported functions include
CONVERT, LEN, ISNULL, IIF,
and SUBSTRING.
Figure A.2 The results of using the DataTable.Select method.
In the sample code, the filter expression is built by concatenating the text from the txtCountry control with a column comparison. If you don’t specify a sort order in the Select method, the rows are returned in primary key order or in the order of addition if the table doesn’t have a primary key. You can also specify a sort expression consisting of one or more column names and the keyword ASC or DESC to specify an ascending or descending sort, respectively. For example, this is a valid sort expression: Country ASC, CompanyName DESC
436 Appendix A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
This expression will sort first by country in ascending order and then by company name within each country in descending order. Finally, you can also select DataRows according to their current state by supplying one of the DataViewRowState constants. Table A.3 shows these constants. Table A.3 DataViewRowState Constants Constant
Meaning
Added
New rows that have not yet been committed
CurrentRows
All current rows, whether unchanged, modified, or new
Deleted
Deleted rows
ModifiedCurrent
Modified rows
ModifiedOriginal
Original data from modified rows
None
No rows
OriginalRows
Original data, including rows that have been modified or deleted
Unchanged
Rows that have not been changed
You can quickly create an array that holds all the content of a DataTable by calling the Select method with no parameters: Dim adr() As DataRow = dt.Select()
You can also sort and filter data by using a DataView. The DataView has the same structure of rows and columns as a DataTable, but it also lets you specify sorting and filtering options as properties of the DataView object. Typically you’ll create a DataView by starting with a DataTable and specifying options to include a subset of the rows in the DataTable, as in this code: ‘ Create a SqlConnection Dim cnn As SqlConnection = _ New SqlConnection(“Data Source=(local);” & _ “Initial Catalog=Northwind;Integrated Security=SSPI”) ‘ Create a SqlCommand Dim cmd As SqlCommand = cnn.CreateCommand() cmd.CommandType = CommandType.Text cmd.CommandText = “SELECT * FROM Customers” ‘ Set up the DataAdapter and fill the DataSet Dim da As SqlDataAdapter = New SqlDataAdapter() da.SelectCommand = cmd Dim ds As DataSet = New DataSet() da.Fill(ds, “Customers”) ‘ Create a DataView based on the Customers DataTable Dim dv As DataView = _ New DataView(ds.Tables(“Customers”)) dv.RowFilter = “Country = ‘France’” dv.Sort = “CompanyName ASC”
437 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ADO.NET . . . . . .Basics . . .
The constructor for the DataView specifies the DataTable that includes the data from which the DataView can draw. By setting the RowFilter, Sort, and RowStateFilter properties of the DataView, you can control which rows are available in the DataView as well as the order in which they are presented. RowStateFilter allows you to select, for example, only rows that have been changed since the DataTable was loaded.
Editing Data with ADO.NET ADO.NET supports all the normal database operations of updating existing data, adding new data, and deleting existing data. Keep in mind that these changes will not be reflected in the underlying database until and unless you call the Update method of the DataAdapter object.
Updating Data Updating data is easy: Just assign a new value to the item in the data row that you want to change—but there’s more to finishing the job. For the Update method of the SqlDataAdapter to write changes back to the database, you must set its UpdateCommand property to an appropriate SqlCommand object. For example, you might load data and prepare it for updating like this: ‘ Create some ADO.NET objects Dim mcnn As SqlConnection = New SqlConnection( _ “Data Source=(local);” & _ “Initial Catalog=Northwind;Integrated Security=SSPI”) Dim mds As DataSet = New DataSet() Dim mda As SqlDataAdapter = New SqlDataAdapter() ‘ Create a SqlCommand to select data Dim cmdSelect As SqlCommand = mcnn.CreateCommand() cmdSelect.CommandType = CommandType.Text cmdSelect.CommandText = _ “SELECT CustomerID, ContactName FROM Customers” ‘ Create a SqlCommand to update data Dim cmdUpdate As SqlCommand = mcnn.CreateCommand() cmdUpdate.CommandType = CommandType.Text cmdUpdate.CommandText = “UPDATE Customers SET “ & _ “ContactName = @ContactName WHERE “ & _ “CustomerID = @CustomerID” cmdUpdate.Parameters.Add(“@ContactName”, _ SqlDbType.NVarChar, _ 30, “ContactName”) cmdUpdate.Parameters.Add( _ “@CustomerID”, SqlDbType.NChar, _ 5, “CustomerID”) cmdUpdate.Parameters(“@CustomerID”).SourceVersion = _ DataRowVersion.Original ‘ Set up the DataAdapter and fill the DataSet
438 Appendix A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . mda.SelectCommand = cmdSelect mda.UpdateCommand = cmdUpdate mda.Fill(mds, “Customers”)
Later, you could update the data and save the changes: ‘ Prompt the user for a customer ID Dim strCustomerID As String = _ InputBox(“Enter Customer ID to modify:”) ‘ Get just that customer’s DataRow Dim adrEdit() As DataRow = _ mds.Tables(“Customers”).Select( _ “CustomerID = ‘“ & strCustomerID & “‘“) ‘ Make sure there’s some data If UBound(adrEdit) > -1 Then ‘ Prompt for new data and put it in the DataRow adrEdit(0)(“ContactName”) = _ InputBox(“Enter new contact name”, , _ adrEdit(0)(“ContactName”)) ‘ And save the changes mda.Update(mds, “Customers”) End If
The Update method of the SqlDataAdapter is syntactically similar to the Fill method. It takes as its parameters the DataSet to be reconciled with the database and the name of the DataTable to be saved. You don’t have to worry about which rows or columns of data were changed. The SqlDataAdapter automatically locates the changed rows. It executes the SqlCommand specified in its UpdateCommand property for each of those rows.
Adding Data To add data to the database, you must supply a SqlCommand for the InsertCommand property of the SqlDataAdapter: ‘ Create some ADO.NET objects Dim mcnn As SqlConnection = _ New SqlConnection(“Data Source=(local);” & _ “Initial Catalog=Northwind;Integrated Security=SSPI”) Dim mds As DataSet = New DataSet() Dim mda As SqlDataAdapter = New SqlDataAdapter() ‘ Create a SqlCommand to select data Dim cmdSelect As SqlCommand = mcnn.CreateCommand() cmdSelect.CommandType = CommandType.Text cmdSelect.CommandText = _ “SELECT CustomerID, CompanyName, “ & _ “ContactName FROM Customers” ‘ Create a SqlCommand to insert data Dim cmdInsert As SqlCommand = mcnn.CreateCommand() cmdInsert.CommandType = CommandType.Text cmdInsert.CommandText = “INSERT INTO Customers “ & _ “(CustomerID, CompanyName, ContactName) “ & _ “VALUES(@CustomerID, @CompanyName, @ContactName)” cmdInsert.Parameters.Add( _
439 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ADO.NET . . . . . .Basics . . . “@CustomerID”, SqlDbType.NChar, _ 5, “CustomerID”) cmdInsert.Parameters.Add( _ “@CompanyName”, SqlDbType.NVarChar, _ 40, “CompanyName”) cmdInsert.Parameters.Add( _ “@ContactName”, SqlDbType.NVarChar, _ 30, “ContactName”) cmdInsert.Parameters(“@CustomerID”).SourceVersion = _ DataRowVersion.Original ‘ Set up the DataAdapter and fill the DataSet mda.SelectCommand = cmdSelect mda.InsertCommand = cmdInsert mda.Fill(mds, “Customers”)
Adding data is then a matter of adding a new DataRow and calling the Update method of the DataAdapter object: ‘ Create a new DataRow Dim dr As DataRow = mds.Tables(“Customers”).NewRow() ‘ Set values dr(0) = txtCustomerID.Text dr(1) = txtCompanyName.Text dr(2) = txtContactName.Text ‘ And append the new row to the DataTable mds.Tables(“Customers”).Rows.Add(dr) ‘ Now save back to the database mda.Update(mds, “Customers”) MessageBox.Show(“Row added!”)
Deleting Data The DataRow object supports the Delete method, which deletes an entire DataRow from the DataTable. You need to supply the proper DeleteCommand: ‘ Create some ADO.NET objects Dim mcnn As SqlConnection = _ New SqlConnection(“Data Source=(local);” & _ “Initial Catalog=Northwind;Integrated Security=SSPI”) Dim mds As DataSet = New DataSet() Dim mda As SqlDataAdapter = New SqlDataAdapter() ‘ Create a SqlCommand to select data Dim cmdSelect As SqlCommand = mcnn.CreateCommand() cmdSelect.CommandType = CommandType.Text cmdSelect.CommandText = _ “SELECT CustomerID, ContactName FROM Customers” ‘ Create a SqlCommand to delete data Dim cmdDelete As SqlCommand = mcnn.CreateCommand() cmdDelete.CommandType = CommandType.Text cmdDelete.CommandText = “DELETE FROM Customers “ & _ “WHERE CustomerID = @CustomerID” cmdDelete.Parameters.Add( _ “@CustomerID”, SqlDbType.NChar, _ 5, “CustomerID”) cmdDelete.Parameters(“@CustomerID”).SourceVersion = _
440 Appendix A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . DataRowVersion.Original ‘ Set up the DataAdapter and fill the DataSet mda.SelectCommand = cmdSelect mda.DeleteCommand = cmdDelete mda.Fill(mds, “Customers”)
Then you can remove a DataRow from its parent collection and call the Update method: ‘ Prompt the user for a Customer ID Dim strCustomerID As String = _ InputBox(“Enter Customer ID to delete:”) Dim dr As DataRow Dim i As Integer For i = 0 To mds.Tables(“Customers”).Rows.Count - 1 dr = mds.Tables(“Customers”).Rows(i) If dr(0) = strCustomerID Then mds.Tables(“Customers”).Rows(i).Delete() Exit For End If Next ‘ Save the changes mda.Update(mds, “Customers”) MessageBox.Show(“Row deleted!”)
441 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ADO.NET . . . . . .Basics . . .
Need to Know More? Beauchemin, Bob. Essential ADO.NET. Addison-Wesley, 2002. Gunderloy, Mike. ADO and ADO.NET Programming. Sybex, 2002. Vaughn, William R. ADO.NET and ADO Examples and Best Practices for VB Programmers. Apress, 2002. Wildermuth, Shawn. Pragmatic ADO.NET. Addison-Wesley, 2003.
B XML Standards and Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
XML (Extensible Markup Language) is a simple, flexible, powerful, and portable markup language developed by the World Wide Web Consortium (W3C). XML files contain both data and metadata. That is, XML files contain both data and descriptions of that data. XML provides a simple format for describing data. XML does not contain any predefined tags, unlike HTML (Hypertext Markup Language). You can create your own tags in XML. Therefore, depending on the need of your application, you can create specialized tags. For example, for a publishing business, you might create tags such as Author, Title, ISBN, and so on. Because the structure of XML is simple and extensible, it is useful in applications such as the exchange of information between organizations, Web site publishing, object serialization, remote procedure calls, and so on.
Syntax of an XML Document An XML document contains only text data. Therefore, an XML document can be easily created or edited using any simple text editor (although you can also purchase specialized XML editors or use the XML editor built in to Visual Studio .NET). An XML document does not contain any predefined tags, but XML adopts a strict syntax for defining data in the XML document. This section discusses the various rules you should follow while creating an XML document. If an XML document conforms to the XML syntax (as explained in the following sections of this appendix), it is known as a wellformed XML document.
444 Appendix B . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Here’s a concrete example to start with. This XML file represents data for two customers: Lambert Tractor Works Millbank WA Doppel OR
XML Declaration The first thing you find in an XML file is the XML declaration:
The declaration tells you three things about this document: ➤ It’s an XML document. ➤ It conforms to the XML 1.0 specification of the W3C. ➤ It uses the UTF-8 character set (a standard set of characters for the
Western alphabet). The XML declaration is optional. However, the W3C XML recommendation suggests that you include the XML declaration. The XML declaration can help identify the XML version and the character encoding used in an XML document. Lines that begin with a string are called processing instructions (PIs). Processing instructions are used to provide information to the application processing an XML document on how to process it.
XML Comments An XML document can contain comments. Comments are set off by the opening string . Here’s an example:
445 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .XML . . Standards . . . . . . and . . Syntax . . . .
XML Elements XML consists of tags (that is, markup), which are contained within angle brackets, and character data. The character data is the information stored in the XML files, and the tags (markup) record the structure of the XML file. XML tags usually describe the data contained by them rather than describing format or layout information. Tags appear in pairs, with each opening tag matched by a closing tag. The closing tag has the same text as the opening tag, prefixed with a forward slash. For example, if is the opening tag, is the closing tag. An opening tag together with a closing tag and the content between them define an element. Tags in an XML document contain the name of the element. For example, here’s a single element from the sample document: OR
This defines an element whose name is CustomerState and whose data is OR. Elements can sometime contain no content. Such elements are called empty elements. For example, here’s an element with no content:
This defines an element whose name is Citizen. Empty elements can also be defined using a shorter syntax. Here’s an example:
In this case, you do not provide the closing tag, but you end the opening tag with />. Elements can be nested, but they cannot overlap. Nested elements have a logical parent-child relationship. A parent element can contain any number of child elements, but a child element belongs to only one parent element. Every element in an XML document is a child element except one element. This is the root element in the XML document that contains all other child elements. The root element in the sample document is named Customers. The Customer elements in that document are nested within the Customers element.
XML Attributes Elements can contain attributes. An attribute is a piece of data that further describes an element. Attributes appear in a name-value pair in the opening
446 Appendix B . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
tag of an element. For example, the sample document includes this opening tag for an element:
This declares an element named Customer. The Customer element includes an attribute whose name is CustomerNumber and whose value is 1. The value of the attribute must always be enclosed in either single or double quotation marks.
XML Naming Convention If you’re familiar with HTML, you know that in HTML, some elements have names dictated by the HTML specification. For example, the tag specifies a first-level heading. XML takes a different approach. You can make up any name you like for an XML element or attribute, subject to some simple naming rules: ➤ A name can contain any alphanumeric character. ➤ A name can contain underscores, hyphens, and periods. ➤ A name must not contain any whitespace. ➤ A name must start with a letter or an underscore.
The names of the XML elements and attributes can be in uppercase, lowercase, or both, but they are case sensitive. For example, the following is not well-formed XML because the opening and closing tags of the element do not match: OR
Handling Special Characters in XML Data Some characters have special meaning for the programs that process XML. For example, the opening angle bracket indicates the beginning of a tag. Quotation marks enclose the attributes, and so on. But sometime you might also like to use these characters as part of the XML data. XML offers two ways to deal with special characters in data. First, for individual characters, you can use entity references. Five entity references are defined in the XML standard: ➤
—Translates
to > (closing angle bracket)
447 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .XML . . Standards . . . . . . and . . Syntax . . . . ➤
&—Translates
➤
'—Translates
to ‘ (apostrophe)
➤
"—Translates
to “ (quotation mark)
to & (ampersand)
You can also use a CDATA section to hold any arbitrary data, whether the data contains special characters or not. The sample document uses this approach to store a customer name containing an apostrophe, as shown here:
sections are generally used for large amounts of text that may or may not contain special characters. Individual special characters are normally represented by an entity reference.
CDATA
XML Namespaces An XML document can contain one or more namespace declarations. A namespace is a device for uniquely identifying elements. Although the sample document at the beginning of this chapter does not declare a namespace, here’s an example of how to declare one:
The namespace is declared as part of the root tag for the document. In this particular case, the namespace (introduced with the special xmlns characters) defines the prefix tr for tags within the namespace. The urn (uniform resource name) is an arbitrary string whose purpose is to distinguish this namespace from other namespaces. XML namespaces serve the same purpose as .NET namespaces: They help cut down on naming collisions. After declaring the tr namespace, an XML document could use a tag such as this: OR
This example indicates that the CustomerState tag is from the and should not be confused with any other CustomerState tag.
tr
namespace
448 Appendix B . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Need to Know More? Elliotte, Rusty Harold and W. Scott Means. XML in a Nutshell. O’Reilly, 2001. W3C XML Home Page: www.w3.org/XML.
C What’s on the CD-ROM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
This appendix is a brief rundown of what you’ll find on the CD-ROM that comes with this book. For a more detailed description of the PrepLogic Practice Tests, Preview Edition exam simulation software, see Appendix D, “Using the PrepLogic Practice Tests, Preview Edition Software.” In addition to the PrepLogic Practice Tests, Preview Edition, the CD-ROM includes the electronic version of the book in Portable Document Format (PDF), and a set of sample applications demonstrating code concepts from the book.
PrepLogic Practice Tests, Preview Edition PrepLogic is a leading provider of certification training tools. Trusted by certification students worldwide, PrepLogic is, we believe, the best practice exam software available. In addition to providing a means of evaluating your knowledge of the Exam Cram 2 material, PrepLogic Practice Tests, Preview Edition features several innovations that help you to improve your mastery of the subject matter. For example, the practice tests allow you to check your score by exam area or domain to determine which topics you need to study more. Another feature allows you to obtain immediate feedback on your responses in the form of explanations for the correct and incorrect answers. PrepLogic Practice Tests, Preview Edition exhibits most of the full functionality of the Premium Edition but offers only a fraction of the total questions. To get the complete set of practice questions and exam functionality, visit PrepLogic.com and order the Premium Edition for this and other challenging exam titles.
450 Appendix C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Again, for a more detailed description of the PrepLogic Practice Tests, Preview Edition features, see Appendix D.
D Using PrepLogic Practice Tests, Preview Edition Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
This Exam Cram 2 includes a special version of PrepLogic Practice Tests—a revolutionary test engine designed to give you the best in certification exam preparation. PrepLogic offers sample and practice exams for many of today’s most in-demand and challenging technical certifications. This special Preview Edition is included with this book as a tool to use in assessing your knowledge of the Exam Cram 2 material while also providing you with the experience of taking an electronic exam. This appendix describes in detail what PrepLogic Practice Tests, Preview Edition is, how it works, and what it can do to help you prepare for the exam. Note that although the Preview Edition includes all the test-simulation functions of the complete, retail version, it contains only a single practice test. The Premium Edition, available at PrepLogic.com, contains the complete set of challenging practice exams designed to optimize your learning experience.
Exam Simulation One of the main functions of PrepLogic Practice Tests, Preview Edition is exam simulation. To prepare you to take the actual vendor certification exam, PrepLogic Practice Tests, Preview Edition is designed to offer the most effective exam simulation available.
452 Appendix D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Question Quality The questions provided in the PrepLogic Practice Tests, Preview Edition are written to the highest standards of technical accuracy. The questions tap the content of the Exam Cram 2 chapters and help you review and assess your knowledge before you take the actual exam.
Interface Design The PrepLogic Practice Tests, Preview Edition exam-simulation interface provides you with the experience of taking an electronic exam. This enables you to effectively prepare for taking the actual exam by making the test experience a familiar one. Using this test simulation can help eliminate the sense of surprise or anxiety you might experience in the testing center because you will already be acquainted with computerized testing.
Effective Learning Environment The PrepLogic Practice Tests, Preview Edition interface provides a learning environment that not only tests you through the computer but also teaches the material you need to know to pass the certification exam. Each question comes with a detailed explanation of the correct answer and often provides reasons the other options are incorrect. This information helps to reinforce the knowledge you already have and also provides practical information you can use on the job.
Software Requirements PrepLogic Practice Tests requires a computer with the following: ➤ Microsoft Windows 98, Windows Me, Windows NT 4.0, Windows
2000, or Windows XP. ➤ A 166MHz or faster processor is recommended. ➤ A minimum of 32MB of RAM. (As with any Windows application, the
more memory, the better your performance.) ➤ 10MB of hard drive space.
453 . . . . . . . . . . . . . . . . . .Using . . . PrepLogic . . . . . .Practice . . . . Tests, . . . .Preview . . . . Edition . . . . Software . . . . .
Installing PrepLogic Practice Tests, Preview Edition Install PrepLogic Practice Tests, Preview Edition by running the setup program on the PrepLogic Practice Tests, Preview Edition CD-ROM. Follow these instructions to install the software on your computer. 1. Insert the CD-ROM into your CD-ROM drive. The Autorun feature
of Windows should launch the software. If you have Autorun disabled, click Start and select Run. Go to the root directory of the CD and select setup.exe. Click Open and then click OK. 2. The Installation Wizard copies the PrepLogic Practice Tests, Preview
Edition files to your hard drive; adds PrepLogic Practice Tests, Preview Edition to your Desktop and Program menu; and installs test engine components to the appropriate system folders.
Removing PrepLogic Practice Tests, Preview Edition from Your Computer If you elect to remove the PrepLogic Practice Tests, Preview Edition product from your computer, an uninstall process has been included to ensure that it is removed safely and completely. Follow these instructions to remove PrepLogic Practice Tests, Preview Edition from your computer: 1. Select Start, Settings, Control Panel. 2. Double-click the Add/Remove Programs icon. 3. You are presented with a list of software installed on your computer.
Select the appropriate PrepLogic Practice Tests, Preview Edition title you want to remove. Click the Add/Remove button. The software is then removed from your computer.
Using PrepLogic Practice Tests, Preview Edition PrepLogic Practice Tests, Preview Edition is designed to be user friendly and intuitive. Because the software has a smooth learning curve, your time is maximized because you start practicing almost immediately. PrepLogic
454 Appendix D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Practice Tests, Preview Edition has two major modes of study: Practice Test and Flash Review. Using Practice Test mode, you can develop your test-taking abilities as well as your knowledge through the use of the Show Answer option. While you are taking the test, you can expose the answers along with a detailed explanation of why the given answers are right or wrong. This gives you the ability to better understand the material presented. Flash Review is designed to reinforce exam topics rather than quiz you. In this mode, you will be shown a series of questions but no answer choices. Instead, you will be given a button that reveals the correct answer to the question and a full explanation for that answer.
Starting a Practice Test Mode Session Practice Test mode enables you to control the exam experience in ways that actual certification exams do not allow: ➤ Enable Show Answer Button—Activates the Show Answer button, allowing
you to view the correct answer(s) and full explanation(s) for each question during the exam. When this feature is not enabled, you must wait until after your exam has been graded to view the correct answer(s) and explanation(s). ➤ Enable Item Review Button—Activates the Item Review button, allowing
you to view your answer choices and marked questions and facilitating navigation between questions. ➤ Randomize Choices—Randomizes answer choices from one exam session
to the next and makes memorizing question choices more difficult, thereby keeping questions fresh and challenging longer. To begin studying in Practice Test mode, click the Practice Test radio button from the main exam-customization screen. This enables the options detailed in the preceding list. To your left, you are presented with the option of selecting the preconfigured Practice Test or creating your own custom test. The preconfigured test has a fixed time limit and number of questions. Custom Tests allow you to configure the time limit and the number of questions in your exam. The Preview Edition included with this book provides a single, preconfigured Practice Test. Get the compete set of challenging PrepLogic Practice Tests at PrepLogic.com and make certain you’re ready for the big exam. Click the Begin Exam button to begin your exam.
455 . . . . . . . . . . . . . . . . . .Using . . . PrepLogic . . . . . .Practice . . . . Tests, . . . .Preview . . . . Edition . . . . Software . . . . .
Starting a Flash Review Mode Session Flash Review mode provides you with an easy way to reinforce topics covered in the practice questions. To begin studying in Flash Review mode, click the Flash Review radio button from the main exam-customization screen. Select either the preconfigured Practice Test or create your own Custom Test. Click the Best Exam button to begin your Flash Review of the exam questions.
Standard PrepLogic Practice Tests, Preview Edition Options The following list describes the function of each of the buttons you see. Depending on the options, some of the buttons will be grayed out and inaccessible or missing completely. Buttons that are appropriate are active. The buttons are as follows: ➤ Exhibit—This button is visible if an exhibit is provided to support the
question. An exhibit is an image that provides supplemental information necessary to answer the question. ➤ Item Review—This button takes you from the question window to the
Item Review screen. From this screen you will see all the questions, your answers, and your marked items. You will also see correct answers listed here when appropriate. ➤ Show Answer—This option displays the correct answer with an explana-
tion of why it is correct. If you select this option, the current question is not scored. ➤ Mark Item—Check this box to tag a question you need to review further.
You can view and navigate your marked items by clicking the Item Review button (if enabled). When grading your exam, you will be notified if you have marked items remaining. ➤ Previous Item—Used to view the previous question. ➤ Next Item—Used to view the next question. ➤ Grade Exam—When you have completed your exam, click this button to
end your exam and view your detailed score report. If you have unanswered or marked items remaining, you will be asked whether you would like to continue taking your exam or view your exam report.
456 Appendix D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Time Remaining If the test is timed, the time remaining is displayed in the upper-right corner of the application screen. It counts down the minutes and seconds remaining to complete the test. If you run out of time, you will be asked whether you want to continue taking the test or end your exam.
Your Examination Score Report The Examination Score Report screen appears when the Practice Test mode ends—as the result of time expiration, the completion of all questions, or your decision to terminate early. This screen provides you with a graphical display of your test score, with a breakdown of scores by topic domain. The graphical display at the top of the screen compares your overall score with the PrepLogic Exam Competency Score. The PrepLogic Exam Competency Score reflects the level of subject competency required to pass this vendor’s exam. Although this score does not directly translate to a passing score, consistently matching or exceeding this score does suggest you possess the knowledge to pass the actual vendor exam.
Reviewing Your Exam From Your Score Report screen, you can review the exam you just completed by clicking the View Items button. Navigate through the items, viewing the questions, your answers, the correct answers, and the explanations for those answers. You can return to your score report by clicking the View Items button.
Get More Exams The PrepLogic Practice Tests, Preview Edition that accompanies your book contains a single PrepLogic Practice Test. Certification students worldwide trust PrepLogic Practice Tests to help them pass their IT certification exams the first time. Purchase the Premium Edition of PrepLogic Practice Tests and get the entire set of the new, challenging Practice Tests for this exam. PrepLogic Practice Tests—Because You Want to Pass the First Time.
457 . . . . . . . . . . . . . . . . . .Using . . . PrepLogic . . . . . .Practice . . . . Tests, . . . .Preview . . . . Edition . . . . Software . . . . .
Contacting PrepLogic If you would like to contact PrepLogic for any reason, including information about our extensive line of certification practice tests, we invite you to do so. Please contact us online at www.preplogic.com.
Customer Service If you have a damaged product and need a replacement or refund, please call the following phone number: 800-858-7674
Product Suggestions and Comments We value your input! Please email your suggestions and comments to the following address:
[email protected] License Agreement YOU MUST AGREE TO THE TERMS AND CONDITIONS OUTLINED IN THE END USER LICENSE AGREEMENT (“EULA”) PRESENTED TO YOU DURING THE INSTALLATION PROCESS. IF YOU DO NOT AGREE TO THESE TERMS, DO NOT INSTALL THE SOFTWARE.
Glossary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ACID (Atomic, Consistent, Isolated, and Durable) The key properties of a transaction. A transaction executes as a single thing (atomic), always leaves the data in a sensible state (consistent), is not affected by other transactions (isolated), and makes a permanent change (durable).
activation type An activation category for a serviced component application that indicates whether the application runs in or out of its client’s process space (a library or a server application).
ad hoc query
assembly A logical unit of functionality that can contain one or more files. Every type loaded in the Common Language Runtime (CLR) belongs to precisely one assembly.
assembly manifest Stores the assembly’s metadata. The metadata provides selfdescribing information, such as the name and version of the assembly, the files that are part of the assembly and their hash values, the files’ dependencies on other assemblies, and so on. This subset of information in the manifest makes assemblies self-sufficient.
A set of SQL statements that are executed immediately.
attribute
application domain
authentication
A secure unit of processing that the Common Language Runtime (CLR) uses to provide isolation between applications.
The process of determining the identity of a user from his or her credentials.
A property of an XML object.
460 authorization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
authorization
COM+ catalog
The process of allowing a user to use specific resources based on his or her authenticated identity.
A COM+ repository that maintains the configuration information for COM+ components.
binding policy
COM interface
A set of rules that specifies which version of an assembly the Common Language Runtime (CLR) will load.
A collection of related public functions that provide access to a COM object. The set of interfaces on a COM object specifies how programs and other objects can interact with the COM object.
CDATA section Raw data within an XML file.
channel In remoting, a channel has the responsibility of transmitting all messages between the client and object across a process boundary.
CLR (Common Language Runtime) The program that executes all managed code and provides code with various services at runtime, such as automatic memory management, cross-language integration, code access security, and debugging and profiling support.
code access security Security based on the identity of the running code.
COM+ application A primary unit of administration and security for the COM+ Component Services. A COM+ application is a group of components that, generally, perform related functions. These components further consist of interfaces and methods.
conditional compilation A process for determining at compile time whether particular sections of code should be included in a project.
context A set of runtime properties that defines the environment for the objects that reside within it.
DataSet class A server-independent store that can hold multiple tables and their relations. You can think of a DataSet as a memory-resident relational database.
DataSet schema An XML file that describes the structure of a DataSet.
debugging The process of locating logical or runtime errors in an application. It involves finding the cause of the errors and fixing them.
461 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . key . .
delayed signing
DTD (Document Type Definition)
A process that allows an assembly to be given a strong name while withholding the signing keys until after the assembly is compiled. This allows you to guard your private key closely while still securing the assembly.
A reference in an XML file that specifies which nodes are valid in the file.
deployment
FCL (Framework Class Library)
A process by which a Windows application or component is distributed in the form of installation package files to be installed on the other computers.
deserialization The process of converting an XML representation of an object back to the object.
element An XML tag together with its contents. A library of classes, interfaces, and value types that are included in the Microsoft .NET Framework. This library provides access to the system functionality and is the foundation on which the .NET Framework applications, components, and controls are built.
GAC (Global Assembly Cache)
An XML file containing changes to be applied to a DataSet.
The Global Assembly Cache is an area for the storage of assemblies that can be shared by many applications on the computer.
Disco
identity
A Microsoft standard for Web service discovery.
An identity column in a database is one with a value that is automatically assigned by the server when a new row is entered.
DiffGram
DOM (Document Object Model) An Internet standard for representing the information contained in an HTML or XML document as a tree of nodes.
DTC (Distributed Transaction Coordinator) A Windows service that manages transactions and transaction-related communications that are distributed across two or more resource managers on one or more systems to ensure ACID properties.
just-in-time activation The capability for a COM+ object to be activated only as needed for executing requests from its client.
key A key column in a database stores keys that uniquely identify a row (primary key) or that refer to a row in another table (foreign key).
462 managed code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
managed code
object pooling
Code that runs under the Common Language Runtime (CLR).
A performance optimization based on using collections of already created objects. Pooling results in more efficient resource allocation.
marshaling Packaging and sending interface method calls across thread or process boundaries via serialization and deserialization.
Merge Module A Merge Module allows you to create reusable components that help in deploying shared components. Merge Modules cannot be directly installed. They need to be merged with installers of applications that use the component packed into a Merge Module.
metadata Data that describes other data.
namespace A naming scheme that provides a way to logically group related types. Namespaces have two benefits: They are used to avoid naming conflicts, and they make it easier to browse and locate classes.
native compilation The process of precompiling assemblies in the processor-specific machine code.
.NET Framework A platform for building, deploying, and running XML Web services and applications. The .NET Framework consists of three main parts: the Common Language Runtime (CLR), the Framework Class Library (FCL), and a set of language compilers.
parameter A piece of information that is passed to a stored procedure at runtime or that is returned by the stored procedure to the calling code.
PInvoke (Platform Invoke) The feature of the .NET Framework that allows you to call Windows API and other DLL procedures from managed code.
private assembly An assembly available only to clients in the same directory tree as the assembly.
proxy An interface-specific object that packages parameters for that interface in preparation for a remote method call. A proxy runs in the address space of the sender and communicates with a corresponding stub in the receiver’s address space.
queued components A COM+ service that provides an easy way to invoke and execute components asynchronously. Message processing can occur without regard to the availability of either the sender or the receiver.
463 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SQL-92 . . . .
RCW (runtime callable wrapper)
shared assembly
A proxy that allows .NET code to make use of COM classes and members.
An assembly that can be referenced by more than one application. An assembly must be explicitly built to be shared by giving it a cryptographically strong name. Shared assemblies are stored in the machinewide Global Assembly Cache.
remoting The .NET Remoting system is an architecture designed to simplify communication between objects running in different application domains, whether they’re on the same computer.
role-based security Security based on the authenticated identity of the user running the code.
runtime host The environment in which the Common Language Runtime (CLR) is started and managed. When you install the .NET Framework, you get three runtime hosts already configured: the Windows shell, ASP.NET, and Internet Explorer. The runtime hosts create application domains, which run the managed code on behalf of the user.
schema The structure of a database or XML file.
SCM (Service Control Manager) The part of the Windows operating system that manages Windows services.
serialization The process of converting one or more objects to their XML representation.
side-by-side execution The ability of .NET to load more than one version of an assembly simultaneously.
signing The process of assigning a cryptographically strong name to an assembly.
SOAP (Simple Object Access Protocol) A standard for transmitting objects as XML over HTTP.
SOAP extension A class that is invoked during the serialization or deserialization of SOAP messages.
SOAP request A SOAP message sent from client to server to invoke a Web method.
SOAP response A SOAP message sent from server to client with the results of a Web method.
SQL-92 The official ANSI specification for the Structured Query Language.
464 stored procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
stored procedure
transaction
A set of SQL statements stored on the server for later execution.
A unit of work that is done as an atomic operation—that is, the operation succeeds or fails as a whole.
strong name The combination of a simple text name, a version number, and culture information (if provided) that is signed by a digital signature and contains a public key of the assembly. Strong names provide security for assemblies by making it very difficult to forge the identity of an assembly.
strongly typed DataSet A DataSet class that allows you to use early binding for table and column names.
testing The process of executing programs and determining whether they worked as expected.
trace listener A class that can receive trace messages from the Trace or Debug classes.
trace switch A class that dictates whether trace messages from the Trace or Debug classes should be emitted by an application being executed.
tracing The process of displaying informative messages in an application at the time of execution. Tracing is a noninteractive process, unlike interactive debugging.
T-SQL (Transact-SQL) The SQL-92 dialect used in Microsoft SQL Server.
UDDI (Universal Description, Discovery, and Integration) A standard for discovering details of Web services and other business services available via the Internet.
unmanaged code Code written in a non-.NET environment that does not benefit from the services of the Common Language Runtime (CLR).
Web method A method of a Web service that can be invoked by client applications.
Web reference Information in a Visual Studio .NET project that allows you to use objects supplied by a Web service.
Web service A Web service is an application that makes one or more objects available to clients over the Internet. Web services communicate with clients using standard protocols such as SOAP and WSDL.
465 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .XPath . . .
Windows service A Windows process that runs in the background, usually without any user interaction. A Windows service must conform to the interface provided by the Windows Service Control Manager. Windows services may run for the entire time the operating system is loaded or can be started and stopped by the Service Control Manager.
WSDL (Web Services Description Language) An XML language that describes the interface of a Web service.
XML Extensible Markup Language. XML is a general language consisting of metadata tags that can contain data.
XML declaration The line in an XML file that identifies the file as XML.
XML namespace An XML namespace defines a set of XML tags that are uniquely identified so that they cannot be confused with XML tags in another namespace.
XML wire format The structure of the actual XML messages passed between Web services servers and clients.
XPath A query language for XML documents.
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
* (asterisk) wild card SELECT statements, 36 XPath queries, 69 ^ (caret) wild card, 39 % (percent) wild card, 38 _ (underscore) wild card, 38-39 —! XML closing string, 444 !— XML opening string, 444
A abort bits, 206-207 AcceptChanges method (DataSet class), 428 access code access security, 290-292 code groups, 292-293 computing permissions, 295-297 granting/denying permissions, 293-294 imperative security, 295 permission sets, 293 requesting permissions, 292, 297 Simple Access Object Protocol. See SOAP XML files, 58 DOM (Document Object Model), 58-59 XmlDocument class, 63-65 XmlNode class, 62-63
XmlReader class, 59-62 XPathNavigator class, 71-75 Account property (ServiceProcessInstaller class), 174 Activate method (ServicedComponent class), 191 activating remote objects, 102-103 serviced components, 194-195 ActiveX components, packaging, 276 ad hoc T-SQL queries, 34 cross-product queries, 36 DELETE statement, 44-45 INSERT statement, 42-43 running, 34-35 SELECT statement, 35-42 GROUP BY clause, 40-41 HAVING clause, 41-42 INNER JOIN clause, 37 ORDER BY clause, 39-40 querying multiple tables, 36-37 required clauses, 36 WHERE clause, 37-39 UPDATE statement, 43-44 adaptive certification exams, 13-15, 18 Add Web Reference dialog box, 125-126 ADO.NET, 423-424 data providers, 424-427 SqlCommand class, 426 SqlConnection class, 426
468 ADO.NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SqlDataAdapter class, 427 SqlDataReader class, 426 SqlParameter class, 426 DataSet objects, 427-428 adding data, 438-439 deleting data, 439-440 DataColumn, 429 DataRelation, 428 DataRow, 428-429 DataTable, 428 DataView, 429, 436-437 finding data, 433-436 moving through, 431-432 with multiple tables, 432-433 populating, 430-431 sorting data, 436-437 updating data, 437-438 aggregate functions, T-SQL, 40-41 anonymous authentication (IIS), 300 AppendChild method (XmlNode class), 62 Application logs, 256 ApplicationAccessControl attribute, 308 ApplicationQueuing attribute, 208 applications COM+ applications, 193 deploying, 265-266 .NET Remoting objects, 281-282 packaging .NET applications, 274-276 private assemblies, 266-269 serviced components, 280-281 shared assemblies, 270-274 Web services, 279-280 Windows services, 280 distributed applications, 98 testing, 236 ASP.NET authentication, 298-299 tracing, 242-246 assemblies, deploying, 266 private assemblies, 266-269 adding probing locations, 269 binding policy, 266-267 locating privately deployed assemblies, 267-269
shared assemblies, 270-274 adding assemblies to GAC, 272-273 assigning strong names, 270-271 binding policy, 273-274 delay signing, 272 Assembly Binding Log Viewer, 269 Assembly Registration (regasm.exe) tool assembly-registration process, 189 exporting .NET components as COM libraries, 190 assembly-registration process, 189-190 assembly signing, 190 Assert method Debug class, 237 Trace class, 237 assertions, 238 associating file extensions, 278 asynchronous Web service calls, 126-127, 149-151 callback functions, 127, 150 WaitHandle object, 150-151 attributes DataSet schema attributes, 26-27 DOM attributes, 59 XML attributes, 445-446 Attributes property (XmlNode class), 62 authentication, 297-298 ASP.NET authentication, 298-299 forms authentication, 301 IIS authentication, 298-300 no authentication, 298 passport authentication, 300-301 providers, 299 serviced components, 308-309 Authenticode signatures, 272 authorization, 301 element, Web.config, 305 serviced components, 308-309 auto mode, FOR XML clause, 82 AutoFlush property Debug class, 237 Trace class, 237 AutoLog property, ServiceBase class, 170 Autos window, debugging code, 249 AVG() function, T-SQL, 40
469 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .CLR . .
B bare parameters, 158 basic authentication (IIS), 300 BeginEdit method (DataRow class), 429 binary formatters, 101-102 BinaryFormatter class, 101 binding policies, 266 private assemblies, 266-269 shared assemblies, 273-274 BooleanSwitch class, 239-240 breakpoints, 248 BufferResponse property (WebMethod attribute), 129
C CAB Project template, 276 CacheDuration property (WebMethod attribute), 129 Call Stack window, debugging code, 249 callback functions, 127, 150 CanBePooled method (ServicedComponent class), 191 CancelEdit method (DataRow class), 429 CanPauseAndContinue property ServiceBase class, 170 ServiceController class, 179 CanShutdown property ServiceBase class, 170 ServiceController class, 179 CanStop property ServiceBase class, 170 ServiceController class, 179 CAOs (client-activated objects), 103 creating, 108-110 instantiating, 109-110 case studies, 4, 13, 15 exhibits, 4 strategies for, 15-16 CategoryName property (PerformanceCounter class), 257 CCW (COM-callable wrapper), 190 CDATA sections, 447
certification exams, 1-2 adaptive tests, 13-15 strategies for, 18 assessing readiness for, 2 case studies, 4, 13-15 exhibits, 4 strategies for, 15-16 fixed-length tests, 13 number of questions, 15 strategies for, 16-17 PrepLogic Practice Tests, Preview Edition, 449-457 questions, 4-5 build-list-and-reorder, 6-8 case studies, 4 create-a-tree, 8-9 drag-and-connect, 10-11 hot-area questions, 12 multiple choice, 5-6 select-and-place, 11 strategies for, 19-20 resources, 20-22 short-form tests, 14-15 strategies for, 16-17 testing centers, 3-4 channels, 101-102 ChildNodes property (XmlNode class), 62 Clear method (DataSet class), 428 client-activated objects (CAOs), 103 creating, 108-110 instantiating, 109-110 client-side scripts, debugging, 252-253 Clone method (XPathNavigator class), 72 CloneNode method (XmlNode class), 62 Close method Debug class, 238 PerformanceCounter class, 257 ServiceController class, 179 Trace class, 238 closing tags, XML, 445 CLR (Common Language Runtime) private assembly binding policies, 266-269 shared assembly binding policies, 273-274
How can we make this index more useful? Email us at
[email protected] 470 code access security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . code access security, 290-292 code groups, 292-293 computing permissions, 295-297 granting/denying permissions, 293-294 imperative security, 295 permission sets, 293 requesting permissions, 292, 297 code groups, 292-293 columns, identity, 49 COM components, 218 direct references, 222 registering COM DLLs, 220 runtime callable wrappers, 219 Type Library Importer tool, 220-222 COM libraries, exporting .NET components as, 190 COM+ applications, 193 COM+ catalogs, 194 COM+ components authentication, 308-309 authorization, 308-309 just-in-time activation, 188, 203-205 object pooling, 188, 201-203 queued components, 188, 208-209 role-based security, 188 transaction processing, 188, 205-207 COM-callable wrapper (CCW), 190 Command class, 426 comments, XML, 444 ComparePosition method (XPathNavigator class), 72 Compile method (XPathNavigator class), 72 Component Services (regsvcs.exe) tool, 280-281 ComponentAccessControl attribute, 309 components COM components, 218 direct references, 222 registering COM DLLs, 220 runtime callable wrappers, 219 Type Library Importer tool, 220-222 COM+ components authentication, 308-309 authorization, 308-309
just-in-time activation, 188, 203-205 object pooling, 188, 201-203 queued components, 188, 208-209 role-based security, 188 transaction processing, 188, 205-207 .NET components assembly-registration process, 189-190 exporting as COM type libraries, 190 serviced components, 191 activating, 194-195 consuming, 198, 200-201 context, 194-195 creating, 196-199 declarative programming model, 191-193 deploying, 280-281 runtime requirements, 194 security, 308-309 concat function (XPath), 70 Conditional attribute, 242 ConditionalAttribute class, 242 configuration files .NET Remoting, 110-112 Web.config file tag, 305 tag, 112 tag, 245-246 configuring authentication, 297-298 ASP.NET authentication, 298-299 forms authentication, 301 IIS authentication, 298-300 no authentication, 298 passport authentication, 300-301 providers, 299 authorization, 301 remoting framework, 110-112 Connection class, 426 consistent bits, 206-207 #Const directive, 242 Construct method (ServicedComponent class), 191 consuming serviced components, 198-201
471 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Deactivate . . . . . . method . . . . contains function (XPath), 70 context, 194-195 ContextUtil class, 195 Continue method (ServiceController class), 179 ConvertAssemblyToTypeLib method (TypeLibConverter class), 190 count function (XPath), 70 COUNT() function, T-SQL, 40 CounterHelp property (PerformanceCounter class), 257 CounterName property (PerformanceCounter class), 257 CounterType property (PerformanceCounter class), 257 CREATE PROCEDURE statement (T-SQL), 45-46 CreateAttribute method (XmlDocument class), 65 CreateElement method (XmlDocument class), 65 CreateEventSource method (EventLog class), 256 CreateNavigator method (XPathDocument class), 72 CreateNode method (XmlDocument class), 65 CreationTimeout property (ObjectPooling class), 202 cross-product queries, 36 current context (XPath), 68-69 Custom Actions Editor, 279 customizing setup and deployment projects, 278-279 Web services, 129
D data providers, 423-427 SqlCommand class, 426 SqlConnection class, 426 SqlDataAdapter class, 427 SqlDataReader class, 426 SqlParameter class, 426 DataAdapter class, 423, 427
databases adding data, 42-43 deleting data, 44-45 retrieving data, 35-42 updating data, 43-44 Windows services database, 168, 173 DataColumn class, 429 DataReader class, 426 DataRelation class, 428 DataRow class, 428-429 DataSet property (XmlDataDocument class), 66 DataSet schema, 23-24 attributes, adding, 26-27 creating from scratch, 24 with Server Explorer, 27-28 elements, adding, 25-27 relationships, 28-31 adding keys, 29 deleting keys, 29 nested relationships, 30-31 one-to-many relationships, 29-30 DataSets, 423-424, 427 adding data, 438-439 DataColumn, 429 DataRelation, 428 DataRow, 428-429 DataTable, 428 DataView, 429, 436-437 deleting data, 439-440 finding data, 433-436 members, 428 moving through, 431-432 with multiple tables, 432-433 populating, 430-431 sorting data, 436-437 strongly typed DataSets, 31-33 synchronizing with XML files, 65-68 updating data, 437-438 DataTable class, 428 DataView class, 429, 436-437 Deactivate method (ServicedComponent class), 191
How can we make this index more useful? Email us at
[email protected] 472 DeactivateOnReturn property . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . DeactivateOnReturn property (ContextUtil class), 195 Debug class, 237-238 Debug project configuration, 237 debugging, 247 analyzing program state, 248-249 breakpoints, setting, 248 client-side scripts, 252-253 DLL files, 252 on exceptions, 249-250 .NET Remoting objects, 254-255 remote processes, 251-252 running processes, 250-251 serviced components, 253-254 stepping through programs, 247-248 Web service projects, 128 Web services, 255 Windows services, 253 declarative programming model, 191-193 security, 295 Decrement method (PerformanceCounter class), 257 delay signing assemblies, 272 Delete method DataRow class, 429, 439-440 EventLog class, 256 DELETE statement (T-SQL), 44-45 DeleteEventSource method (EventLog class), 256 deleting DataSet data, 439-440 denying permissions, 293-294 deployment, 265-266 .NET Remoting objects, 281-282 packaging applications, 274-276, 279 private assemblies, 266-269 adding probing locations, 269 binding policy, 266-267 locating privately deployed assemblies, 267-269 serviced components, 280-281 shared assemblies, 270-274 adding assemblies to GAC, 272-273 assigning strong names, 270-271
binding policy, 273-274 delay signing, 272 Web services, 279-280 Windows services, 280 Depth property (XmlReader class), 59 Description property TraceSwitch class, 240 WebMethod attribute, 129 deserialization, 142. See also SOAP, extensions DiffGrams, 86-88 digest authentication (IIS), 300 DisableCommit method (ContextUtil class), 195 Disco, 125, 130-131 disco.exe (Web Service Discovery Tool), 130-131 discovering Web services, 125, 130-131 DisplayName property ServiceController class, 179 ServiceInstaller class, 174 TraceSwitch class, 240 DisposeObject method (ServicedComponent class), 191 distributed applications, 98 DLL files debugging, 252 registering COM DLLs, 220 DllImport attribute, 223-225 Document Object Model (DOM), 58-59 Document Type Definitions (DTDs), 79-80 DocumentElement property (XmlDocument class), 65 DocumentType property (XmlDocument class), 65 DOM (Document Object Model), 58-59 done bits, 206-207 DTDs (Document Type Definitions), 79-80
E elements, 445 DataSet schema elements, 25-27 empty elements, 445 namespaces, 447
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . FOR . . .XML . . .clause . . . naming conventions, 446 nested elements, 445 #Else directive, 242 #ElseIf directive, 242 empty XML elements, 445 EnableCommit method (ContextUtil class), 195 Enabled property (ObjectPooling class), 202 EnableRaisingEvents property (EventLog class), 256 EnableSession property (WebMethod attribute), 129 encoded parameter formatting, 155-156 #End ExternalSource directive, 242 #End If directive, 242 #End Region directive, 242 EndEdit method (DataRow class), 429 enterprise services, 201 declarative programming model, 191-193 just-in-time activation, 188, 203-205 object pooling, 188, 201-203 queued components, 188, 208-209 role-based security, 188 security, 308-309 transaction processing, 188, 205-207 entity references, 446-447 Entries property (EventLog class), 256 EntryWritten event (EventLog class), 256 EOF property (XmlReader class), 59 Evaluate method (XPathNavigator class), 72 event logs, 255-257 EventClass class, 192 EventLog class, 256-257 EventLog property (ServiceBase class), 170 EventTrackingEnabled class, 192 exams, certification, 1-2 adaptive tests, 13-15, 18 assessing readiness for, 2 case studies, 4, 13-16 fixed-length tests, 13, 15-17 PrepLogic Practice Tests, Preview Edition, 449-457
questions, 4-5 build-list-and-reorder, 6-8 case studies, 4 create-a-tree, 8-9 drag-and-connect, 10-11 hot-area questions, 12 multiple choice, 5-6 select-and-place, 11 strategies for, 19-20 resources, 20-22 short-form tests, 14-17 testing centers, 3-4 exceptions, debugging on, 249-250 ExecuteCommand method (ServiceController class), 179 ExecuteNonQuery method (SqlCommand class), 47 ExecuteXmlReader method (SqlCommand class), 85-86 Exists method (EventLog class), 256 explicit mode, FOR XML clause, 83-84 exporting .NET components as COM type libraries, 190 #ExternalSource directive, 242
F Fail method Debug class, 238 Trace class, 238 file extensions, associating, 278 File Signing (signcode.exe) tool, 272 File System Editor, 278 File Types Editor, 278 filtering DataSet data, 436-437 T-SQL query results, 41-42 finding data in DataSets, 433-436 FirstChild property (XmlNode class), 62 Flush method Debug class, 238 Trace class, 238 FOR XML clause auto mode, 82 explicit mode, 83-84
How can we make this index more useful? Email us at
[email protected] 473
474 FOR XML clause . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . raw mode, 81 XMLDATA option, 84-85 formatters, 101-102 forms authentication, 301 Forms authentication provider, 299 fully qualified names, 36 functions callback functions, 127, 150 calling functions with PInvoke, 223-226 T-SQL aggregate functions, 40-41 XPath functions, 70 fuslogvw.exe (Binding Log Viewer), 269
G GAC (Global Assembly Cache), 270 adding assemblies, 272-273 gacutil.exe, 273 GetAttribute method (XmlReader class), 59 GetChanges method (DataSet class), 428 GetElementFromRow method (XmlDataDocument class), 66 GetEventLogs method (EventLog class), 256 GetRowFromElement method (XmlDataDocument class), 66 GetServices method (ServiceController class), 179 GetXml method (DataSet class), 428 GetXmlSchema method (DataSet class), 428 Global Assembly Cache. See GAC granting permissions, 293-294 GROUP BY clause, SELECT SQL statement, 40-41
H HasAttributes property XmlReader class, 59 XPathNavigator class, 72 HasChildNodes property (XmlNode class), 62 HasChildren property (XPathNavigator class), 72 HasValue property (XmlReader class), 59 HAVING clause, SELECT SQL statement, 41-42
HTML DOM (Document Object Model), 58-59 HTTP channel objects, 101-102
I IChannelReceiver interface, 101 IChannelSender interface, 101 identity columns, 49 @@IDENTITY variable, 49 #If directive, 242 IFormatter interface, 101 IIS (Internet Information Services) authentication, 298-300 as .NET Remoting activation agent, 112-114 ILease interface, 103 Immediate window, debugging code, 249 imperative security, 295 impersonation, 302 ImportNode method (XmlDocument class), 65 Increment method (PerformanceCounter class), 257 IncrementBy method (PerformanceCounter class), 257 Indent method Debug class, 238 Trace class, 238 IndentLevel property Debug class, 238 Trace class, 238 IndentSize property Debug class, 238 Trace class, 238 indexing XPath collections, 71 INNER JOIN clause, SELECT SQL statement, 37 InnerText property (XmlNode class), 62 InnerXml property (XmlNode class), 63 INSERT statement (T-SQL), 42-43 InsertAfter method (XmlNode class), 63 InsertBefore method (XmlNode class), 63 InsertCommand property (SqlDataAdapter class), 438-439
475 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . LogNameFromSourceName . . . . . . . . . . . . . . . method . . . . installation. See also deployment PrepLogic Practice Tests, Preview Edition, 453 SQLXML, 86 Windows service applications, 173 adding installer classes, 175 customizing installation, 175 Installer class, 173, 175 installutil.exe, 175 ServiceInstaller class, 169, 173-174 ServiceProcessInstaller class, 169, 173-174 zero-impact installations, 275 Installer class, 173, 175 installutil.exe, 175 InstanceName property (PerformanceCounter class), 257 instantiating CAOs (client-activated objects), 109-110 remote objects, 102-103 SAOs (server-activated objects), 106-108 serviced components, 198, 200-201 integration testing, 236 InterfaceQueuing attribute, 208 InterfaceQueuing class, 192 interfaces IChannelReceiver, 101 IChannelSender, 101 IFormatter, 101 ILease, 103 Internet Information Services (IIS) authentication, 298-300 as .NET Remoting activation agent, 112-114 IsCallerInRole method (ContextUtil class), 195 IsEmptyElement property XmlReader class, 59 XPathNavigator class, 72 IsEnabled property (TraceContext class), 243 IsInTransaction property (ContextUtil class), 195 IsNull method (DataRow class), 429
IsSecurityEnabled property (ContextUtil class), 195 IsStartElement method (XmlReader class), 59 Item property DataRow class, 429 XmlReader class, 59
J-K JIT (just-in-time) activation, 188, 203-205 JustInTimeActivation class, 192, 204 keys adding to DataSet schema, 29 deleting from DataSet schema, 29 key pairs, 270-271
L last function (XPath), 70 LastChild property (XmlNode class), 63 Launch Conditions Editor, 279 lazy registration, 280 Level property (TraceSwitch class), 240 library applications, running COM+ applications as, 193 lifetime leases, 103-104 listeners, 238-239 Listeners property Debug class, 238 Trace class, 238 literal parameter formatting, 153-155 Load method XmlDataDocument class, 66 XmlDocument class, 65 LoadXml method (XmlDocument class), 65 Locals window, debugging code, 249 Log property (EventLog class), 256 LogDisplayName property (EventLog class), 256 LogNameFromSourceName method (EventLog class), 256
How can we make this index more useful? Email us at
[email protected] 476 logs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . logs application logs, 256 Assembly Binding Log Viewer, 269 event logs, 255-257
M MachineName property EventLog class, 256 PerformanceCounter class, 257 ServiceController class, 179 managed code, 219 MarshalByRefObject class, 100 Matches method (XPathNavigator class), 72 MAX() function, T-SQL, 41 MaxPoolSize property (ObjectPooling class), 202-203 MBR (marshal-by-reference) objects, 100 CAOs, 103 creating, 108-110 instantiating, 109-110 SAOs, 102 activation modes, 102-103 creating, 105-108 MBV (marshal-by-value) objects, 100 remote object activation, 102 Me window, debugging code, 249 Merge method (DataSet class), 428 merge modules, 282 Merge Module Project template, 276 MessageName property (WebMethod attribute), 129 methods asynchronous Web methods, creating, 149-151 callback functions, 127, 150 WaitHandle object, 150-151 channel objects, 101 marking as conditional, 242 translating in XML, 124 Microsoft certification exams, 1-2 adaptive tests, 13-15, 18 assessing readiness for, 2 case studies, 4, 13, 15-16 fixed-length tests, 13, 15-17
PrepLogic Practice Tests, Preview Edition, 449-457 questions, 4-5 build-list-and-reorder, 6-8 case studies, 4 create-a-tree, 8-9 drag-and-connect, 10-11 hot-area questions, 12 multiple-choice, 5-6 select-and-place, 11 strategies for, 19-20 resources, 20-22 short-form tests, 14-17 testing centers, 3-4 Microsoft Message Queuing (MSMQ), 208 Microsoft SQL Server. See SQL Server Microsoft Windows Installer, 275-276 MIN() function, T-SQL, 41 MinPoolSize property (ObjectPooling class), 202-203 MoveToElement method (XmlReader class), 60 MoveToFirst method (XPathNavigator class), 72 MoveToFirstAttribute method XPathNavigator class, 73 XmlReader class, 60 MoveToFirstChild method (XPathNavigator class), 73 MoveToNext method (XPathNavigator class), 73 MoveToNextAttribute method XPathNavigator class, 73 XmlReader class, 60 MoveToParent method, 73 MoveToPrevious method (XPathNavigator class), 73 MoveToRoot method (XPathNavigator class), 73 MSMQ (Microsoft Message Queuing), 208 MustRunInClientContext class, 192 MyTransactionVote property (ContextUtil class), 195
477 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .ObjectPooling . . . . . . . class . . .
N Name property XmlNode class, 63 XmlReader class, 60 XPathNavigator class, 73 Namespace property (WebService attribute), 128 namespaces for distributed applications, 98 System.Data, 427-429, 436-437 System.Data.Common, 425 System.Data.OleDb, 425 System.Data.SqlClient, 425-427 System.Diagnostics, 238-239 System.EnterpriseService, 192-193, 195 System.MarshalByRefObject, 100 System.Net, 98 System.Runtime.InteropService, 189190 System.Runtime.Remoting, 98 System.Runtime.Remoting.Lifetime, 103 System.Web.Services, 98 System.Xml, 62-68, 78-80 System.Xml.XPath, 71-75 XML namespaces, 447 nested relationships, 30-31 XML elements, 445 .NET components assembly-registration process, 189-190 exporting as COM type libraries, 190 .NET Remoting, 97-98 application domain communication, 98-99 CAOs (client-activated objects) creating, 108-110 instantiating, 109-110 channels, 101-102 configuring remoting framework, 110-112 debugging remoting objects, 254-255 deploying remoting objects, 281-282 formatters, 101-102
IIS as activation agent, 112-114 lifetime leases, 103-104 MBR (marshal-by-reference) objects, 100 MBV (marshal-by-value) objects, 100 remotable classes, creating, 104-105 remote object activation, 102 SAOs (server-activated objects) activation modes, 102-103 creating, 105-108 security, 307-308 net.exe, 177-178 NextSample method (PerformanceCounter class), 257 NextSibling property (XmlNode class), 63 NextValue method (PerformanceCounter class), 258 NodeChanged event (XmlDocument class), 65 NodeChanging event (XmlDocument class), 65 NodeInserted event (XmlDocument class), 65 NodeInserting event (XmlDocument class), 65 NodeRemoved event (XmlDocument class), 65 NodeRemoving event (XmlDocument class), 65 NodeType property XmlNode class, 63 XmlReader class, 60 normalize-space function (XPath), 70 not function (XPath), 70 NT services. See Windows services number function (XPath), 70
O object marshalling MBR (marshal-by-reference) objects, 100-103, 105-110 MBV (marshal-by-value) objects, 100-102 object pooling (COM+), 188, 201-203 ObjectPooling class, 192, 201-202
How can we make this index more useful? Email us at
[email protected] 478 objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . objects activating remote objects, 102-103 deploying .NET Remoting objects, 281-282 CAOs (client-activated objects), 103, 108-110 DOM (Document Object Model), 58-59 HTML DOM (Document Object Model), 58-59 HTTP channel objects, 101-102 proxy objects, 98-99, 131-132 SAOs (server-activated objects), 102-103, 105 translating objects in XML, 124 OnContinue method (ServiceBase class), 170-171 one-to-many relationships, 29-30 OnPause method (ServiceBase class), 170-171 OnStart method (ServiceBase class), 170 OnStop method (ServiceBase class), 170-171 opening tags, XML, 445 ORDER BY clause, SELECT SQL statement, 39-40 OuterXml property (XmlNode class), 63 OwnerDocument property (XmlNode class), 63
P packaging applications, 274-276, 279 Parameter class, 426 parameterized stored procedures, 47-48 ParentNode property (XmlNode class), 63 Passport authentication provider, 299 Passport authentication service, 300-301 Passport Software Development Kit, 300 Password property (ServiceProcessInstaller class), 174 Pause method (ServiceController class), 179 pausing Windows services, 169 percent (%) wild card, 38 perfmon.exe, 258 Performance Counter Builder Wizard, 258 performance counters, 257-258
Performance Monitoring (perfmon.exe) tool, 258 PerformanceCounter class, 257-258 permissions, 290-292 code groups, 292-293 computing, 295-297 granting/denying, 293-294 imperative security, 295 permission sets, 293 requesting, 292, 297 PIAs (Primary Interop Assemblies), 222 PIs (processing instructions), 444 Platform Invoke (PInvoke), 223-226 Pooling Manager, 202-203 position function (XPath), 70 PrependChild method (XmlNode class), 63 PrepLogic Practice Tests, Preview Edition, 449-457 contacting PrepLogic, 457 Flash Review mode, 455 installation, 453 license agreement, 457 obtaining additional exams, 456 option buttons, 455 Practice Test mode, 454 removing, 453 reviewing exams, 456 score reports, 456 software requirements, 452 time remaining, 456 preprocessing directives, 241-242 PreserveWhitespace property (XmlDocument class), 65 PreviousSibling property (XmlNode class), 63 Primary Interop Assemblies (PIAs), 222 primary keys, 29 private assemblies, deploying, 266-269 adding probing locations, 269 binding policy, 266-267 locating privately deployed assemblies, 267-269 private UDDI registries, 130 PrivateComponent class, 192
479 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .ReplaceChild . . . . . . . method . . . . processing instructions (PIs), 444 programmatic configuration, 110 properties. See also specific properties translating in XML, 124 proxy objects creating with wsdl.exe, 131-132 .NET Remoting and, 98-99 public UDDI registries, 130 publisher policy, 273
Q queries ad hoc T-SQL queries, 34 cross-product queries, 36 DELETE statement, 44-45 INSERT statement, 42-43 running, 34-35 SELECT statement, 35-42 UPDATE statement, 43-44 stored procedures, 45 creating, 45-46 executing from .NET, 46-47 parameterized procedures, 47-48 queued components, 188, 208-209
R raw mode, FOR XML clause, 81 RawValue property (PerformanceCounter class), 258 RCWs (runtime callable wrappers), 219-222 Read method (XmlReader class), 60 ReadOnly property (PerformanceCounter class), 258 ReadXml method (DataSet class), 428 ReadXmlSchema method (DataSet class), 428 Recordsets, 431 Refresh method (ServiceController class), 179 regasm.exe (Assembly Registration) tool assembly-registration process, 189 exporting .NET components as COM libraries, 190
#Region directive, 242 registering COM DLLs, 220 remotable classes as SAOs SingleCall Activation mode, 105-106 SingleTon activation mode, 108 serviced components, 280-281 RegistrationHelper class, 280-281 RegistrationServices class, 189 Registry Editor, 278 regsvcs.exe (Component Services tool), 280-281 Relations property (DataSet class), 428 Release project configuration, 237 remote processes, debugging, 251-252 Remoting (.NET), 97-98 application domain communication, 98-99 channels, 101-102 CAOs (client-activated objects) creating, 108-110 instantiating, 109-110 configuring remoting framework, 110-112 debugging .NET Remoting objects, 254-255 deploying .NET Remoting objects, 281-282 formatters, 101-102 IIS as activation agent, 112-114 lifetime leases, 103-104 MBR (marshal-by-reference) objects, 100 MBV (marshal-by-value) objects, 100 remotable classes, creating, 104-105 remote object activation, 102 security, 307-308 SAOs (server-activated objects) activation modes, 102-103 creating, 105-108 RemoveAll method (XmlNode class), 63 RemoveChild method (XmlNode class), 63 RemoveInstance method (PerformanceCounter class), 258 ReplaceChild method (XmlNode class), 63
How can we make this index more useful? Email us at
[email protected] 480 repression testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . repression testing, 236 role-based security, 188, 290 authentication, 297-301 authorization, 301 impersonation, 302 rows deleting, 44-45 inserting, 42-43 updating, 43-44 RowState property (DataRow class), 429 RPC-style body formatting, 156-157 Run method (ServiceBase class), 170 runtime callable wrappers (RCWs), 219-222
S SAOs (server-activated objects), 102-103 activation modes, 102-103 creating, 105 Save method (XmlDocument class), 65 sc.exe (Service Control utility), 178 schema DataSet schema, 23-24 attributes, adding, 26-27 creating from scratch, 24 creating with Server Explorer, 27-28 elements, adding, 25-27 keys, adding, 29 nested relationships, 30-31 one-to-many relationships, 29-30 XSD schema creating, 76-78 validating XML files, 78-80 SCM (Service Control Manager), 168-171 SecureMethod attribute, 309 security, 290 authentication, 297-298 ASP.NET authentication, 298-299 forms authentication, 301 IIS authentication, 298-300 no authentication, 298 passport authentication, 300-301 providers, 299 authorization, 301
code access security, 290-292 code groups, 292-293 computing permissions, 295-297 granting/denying permissions, 293294 imperative security, 295 permission sets, 293 requesting permissions, 292, 297 impersonation, 302 .NET Remoting, 307-308 serviced components, 308-309 Web services, 304-306 Windows services, 302-303 Security logs, 256 SecurityRole attribute, 308-309 Select method DataTable class, 433-436 XPathNavigator class, 73 SELECT statement (T-SQL), 35-42 FOR XML clause, 81-85 GROUP BY clause, 40-41 HAVING clause, 41-42 INNER JOIN clause, 37 ORDER BY clause, 39-40 querying multiple tables, 36-37 required clauses, 36 WHERE clause, 37-39 SelectNodes method XmlDocument object, 71 XmlNode class, 63 SelectSingleNode method (XmlNode class), 63 Self-Assessment, 2 Serializable attribute, MBV objects, 100 serialization, 142. See also SOAP, extensions server applications, running COM+ applications as, 193 Server Explorer DataSet schema, creating, 27-28 Windows services, controlling, 177 server-activated objects (SAOs), 102-103 activation modes, 102-103 creating, 105 Service Control (sc.exe) utility, 178
481 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SQL . . Server . . . . Service Control Manager (SCM), 168-171 ServiceBase class, 169-170 ServiceController class, 169, 178-180 serviced components, 191 activating, 194-195 COM+ applications, 193 COM+ catalogs, 194 consuming, 198, 200-201 context, 194-195 creating, 196-199 debugging, 253-254 declarative programming model, 191193 deploying, 280-281 queued components, 188, 208-209 registering with COM+ catalog, 280-281 runtime requirements, 194 security, 308-309 ServicedComponent class, 191 ServiceInstaller class, 169 properties, 173-174 ServiceName property ServiceBase class, 170 ServiceController class, 179 ServiceInstaller class, 174 ServiceProcessInstaller class, 169 properties, 173-174 Services MMC snap-in, 176-177 ServicesDependedOn property ServiceController class, 179 ServiceInstaller class, 174 ServiceType property (ServiceController class), 179 session state, using in Web services, 129 SET clause, UPDATE SQL statement, 43 SetAbort method (ContextUtil class), 195 SetComplete method (ContextUtil class), 195 setup and deployment projects. See also deployment Cab Project template, 276 customizing, 278-279 Merge Module Project template, 276 Setup Project template, 276-278 Web Setup Project template, 276
Setup Project template, 276-278 shared assemblies, deploying, 270-274 adding assemblies to GAC, 272-273 assigning strong names, 270-271 binding policy, 273-274 delay signing, 272 short-form certification exams, 14-17 signcode.exe (File Signing tool), 272 signing assemblies, 190 Simple Object Access Protocol. See SOAP SingleCall activation mode, 102 registering remotable classes, 105-106 Singleton activation mode, 103 registering remotable classes, 108 Skip method (XmlReader class), 60 sn.exe (Strong Name) tool, 190, 270-272 SOAP (Simple Object Access Protocol), 98, 101, 124 authentication, 304-305 extensions, 142-143 creating, 143-148 examples of use, 143 priority, 142 required tasks, 143-144 testing, 148-149 formatting messages, 152-153 bare parameter formatting, 158 encoded parameter formatting, 155-156 literal parameter formatting, 153-155 RPC-style body formatting, 156-157 wrapped parameter formatting, 158 XmlElement attribute, 159 SoapDisplayExtension class, 148 SoapFormatter class, 101 sorting DataSet data, 436-437 Source property (EventLog class), 256 SourceExists method (EventLog class), 256 SQL Server ad hoc queries, 34 cross-product queries, 36 DELETE statement, 44-45 INSERT statement, 42-43 running, 34-35
How can we make this index more useful? Email us at
[email protected] 482 SQL Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SELECT statement, 35-42 UPDATE statement, 43-44 data providers, 425 SqlCommand class, 426 SqlConnection class, 426 SqlDataAdapter class, 427 SqlDataReader class, 426 SqlParameter class, 426 generating XML with, 81-86 stored procedures, 45 creating, 45-46 executing from .NET, 46-47 @@IDENTITY variable, 49 parameterized stored procedures, 47-48 updating data with DiffGrams, 86-88 SqlCommand class, 426 ExecuteNonQuery method, 47 ExecuteXmlReader method, 85-86 SqlConnection class, 426 SqlDataAdapter class, 427 SqlDataReader class, 426 SqlParameter class, 48, 426 SQLXML, installation, 86 stack walks, 296 Start method (ServiceController class), 179 starting Windows services, 169-171 starts-with function (XPath), 70 StartType property (ServiceInstaller class), 174 static discovery, 130 Status property (ServiceController class), 179 stepping through programs, 247-248 Stop method (ServiceController class), 180 stopping Windows services, 169 stored procedures, 45 creating, 45-46 executing from .NET, 46-47 @@IDENTITY variable, 49 parameterized stored procedures, 47-48 string-length function (XPath), 70 Strong Name (sn.exe) tool, 190, 270-272 strong names, assigning to assemblies, 270-272
strongly typed DataSets, 31-33 creating, 31-32 using, 33 StructLayout attribute, 225-226 substring function (XPath), 70 SUM() function, T-SQL, 40 Synchronization class, 193 System logs, 256 System.Data namespace, 427 DataColumn class, 429 DataRelation class, 428 DataRow class, 428-429 DataSet class, 427-428. See also DataSets DataTable class, 428 DataView class, 429, 436-437 System.Data.Common namespace, 425 System.Data.OleDb namespace, 425 System.Data.SqlClient namespace, 425 SqlCommand class, 426 SqlConnection class, 426 SqlDataAdapter class, 427 SqlDataReader class, 426 SqlParameter class, 426 System.Diagnostics namespace, 238-239 System.EnterpriseServices namespace attributes, 192-193 ContextUtil class, 195 ServicedComponent class, 191 System.MarshalByRefObject namespace, 100 System.Net namespace, 98 System.Runtime.InteropService namespace RegistrationServices class, 189 TypeLibConverter class, 190 System.Runtime.Remoting namespace, 98 System.Runtime.Remoting.Lifetime namespace, 103 System.Web.Services namespace, 98 System.Xml namespace XmlDataDocument class, 65-68 XmlDocument class, 63-65 XmlNode class, 62-63 XmlReader class, 59-62 XmlValidatingReader class, 78-80 System.Xml.XPath namespace, 71-75
483 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . unmanaged . . . . . . code . . .
T T-SQL, 33 ad hoc queries, 34 cross-product queries, 36 running, 34-35 aggregate functions, 40-41 CREATE PROCEDURE statement, 45-46 DELETE statement, 44-45 INSERT statement, 42-43 SELECT statement, 35-42 FOR XML clause, 81-85 GROUP BY clause, 40-41 HAVING clause, 41-42 INNER JOIN clause, 37 ORDER BY clause, 39-40 querying multiple tables, 36-37 required clauses, 36 WHERE clause, 37-39 stored procedures, 45 creating, 45-46 executing from .NET, 46-47 @@IDENTITY variable, 49 parameterized procedures, 47-48 UPDATE statement, 43-44 tables identity columns, 49 rows deleting, 44-45 inserting, 42-43 updating, 43-44 Tables property (DataSet class), 428 tags, XML, 445 TCP (Transmission Control Protocol), channel objects, 101-102 testing applications, 236 SOAP extensions, 148-149 testing centers, 3-4 tlbexp.exe (Type Library Exporter), 190 tlbimp.exe (Type Library Importer), 220-222 Trace class, 237-238
TraceContext class, 242-243 element, Web.config file, 245-246 TraceError property (TraceSwitch class), 240 TraceInfo property (TraceSwitch class), 240 TraceListener class, 238-239 TraceMode property (TraceContext class), 243 TraceSwitch class, 239-241 TraceVerbose property (TraceSwitch class), 240 TraceWarning property (TraceSwitch class), 240 tracing ASP.NET tracing, 242-246 Debug class, 237-238 preprocessing directives, 241-242 Trace class, 237-238 trace listeners, 238-239 trace switches, 239-241 Transact-SQL. See T-SQL Transaction class, 193 transaction processing, 188, 205-207 Transaction property (ContextUtil class), 195 TransactionOption property (WebMethod attribute), 129 translating objects in XML, 124 type libraries, 220-222 Type Library Exporter (tlbexp.exe), 190 Type Library Importer (tlbimp.exe), 220-222
U-V UDDI (Universal Description, Discovery, and Integration), 125, 130 Unindent method Debug class, 238 Trace class, 238 unique keys, 29 unit testing, 236 unmanaged code, 217-226 COM components, 218 direct references, 222 registering COM DLLs, 220
How can we make this index more useful? Email us at
[email protected] 484 unmanaged code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . runtime callable wrappers, 219 Type Library Importer tool, 220-222 Platform Invoke (PInvoke), 223-226 Update method (SqlDataAdapter class), 437-438 UPDATE statement (T-SQL), 43-44 URL authorization, 305 User Interface Editor, 278-279 user interfaces, customizing, 278-279 Username property (ServiceProcessInstaller class), 174 validating XML files, 78-80 Value property XmlReader class, 60 XPathNavigator class, 73
W W3C (World Wide Web Consortium), 58 WaitForStatus method (ServiceController class), 180 WaitHandle class, 150-151 Warn method (TraceContext class), 243 Watch window, debugging code, 249 Web methods, asynchronous calls, 149-151 callback functions, 127, 150 WaitHandle object, 150-151 Web references, 132-133 Web Service Discovery Tool (disco.exe), 130-131 Web services, 123-124 asynchronous calls, 126-127, 149-151 callback functions, 127, 150 WaitHandle object, 150-151 creating, 127-128 customizing, 129 debugging, 255 deploying, 279-280 discovering, 125, 130-131 invoking, 125-126 protocols, 124. See also specific protocols Disco, 125, 130 SOAP, 124 UDDI, 125, 130 WSDL, 125, 131-132
security, 304-306 session state use in, 129 SOAP extensions, 142-143 creating, 143-148 testing, 148-149 testing projects, 128 Web references, 132-133 XML wire format, 152-153 bare parameter formatting, 158 encoded parameter formatting, 155-156 literal parameter formatting, 153-155 RPC-style body formatting, 156-157 wrapped parameter formatting, 158 XmlElement attribute, 159 Web Services Description Language Tool (wsdl.exe), 131-132 Web Services Description Language (WSDL), 125 Web Setup Project template, 276 Web.config file tag, 305 tag, 112 tag, 245-246 WebMethod attribute, 129 well-formed XML documents, 443 WHERE clause (SQL) DELETE statement, 44 SELECT statement, 37-39 UPDATE statement, 43-44 Windows API, calling unmanaged functions, 223-226 Windows authentication provider, 299 Windows Installer, 275-276 Windows integrated authentication (IIS), 300 Windows services, 167-168 architecture, 168-169 controlling Windows service applications using net.exe, 177-178 using Server Explorer window, 177 using Service Control utility, 178 using ServiceController class, 178-180 using Services MMC snap-in, 176-177
485 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . XmlNode . . . . . class . . . creating Window service applications, 169-173 database, 168, 173 debugging, 253 deploying, 280 installing applications, 173 adding installer classes, 175 customizing installation, 175 Installer class, 173, 175 installutil.exe, 175 ServiceInstaller class, 169, 173-174 ServiceProcessInstaller class, 169, 173-174 .NET Framework support for, 169 pausing, 169 security, 302-303 starting, 169-171 stopping, 169 World Wide Web Consortium (W3C), 58 wrapped parameters, 158 Write method Debug class, 238 Trace class, 238 TraceContext class, 243 WriteContentTo method (XmlNode class), 63 WriteEntry method (EventLog class), 256 WriteIf method Debug class, 238 Trace class, 238 WriteLine method Debug class, 238 Trace class, 238 WriteLineIf method Debug class, 238 Trace class, 238 WriteTo method XmlDocument class, 65 XmlNode class, 63 WriteXml method (DataSet class), 428 WriteXmlSchema method (DataSet class), 428 WSDL (Web Services Description Language), 125 wsdl.exe, 131-132
X-Z XCOPY command, 275 XML, 443 accessing XML files, 58 DOM (Document Object Model), 58-59 XmlDocument class, 63-65 XmlNode class, 62-63 XmlReader class, 59-62 XPathNavigator class, 71-75 DiffGrams, 86-88 generating with SQL Server, 81-86 processing instructions (PIs), 444 synchronizing DataSets, 65-68 syntax, 443-447 attributes, 445-446 comments, 444 declarations, 444 elements, 445 namespaces, 447 naming conventions, 446 special characters, 446-447 tags, 445 translating objects into, 124 validating XML files, 78-80 Web services. See Web services well-formed XML documents, 443 wire format, controlling, 152-159 bare parameter formatting, 158 encoded parameter formatting, 155-156 literal parameter formatting, 153-155 RPC-style body formatting, 156-157 wrapped parameter formatting, 158 XmlElement attribute, 159 XPath queries. See XPath XSD schemas creating programmatically, 76-78 validating XML files, 78-80 XmlDataDocument class, 65-68 XmlDocument class, 63-65 XmlElement attribute, 159 XmlNode class, 62-63
How can we make this index more useful? Email us at
[email protected] 486 XmlReader class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . XmlReader class, 59-62 XmlValidatingReader class, 78-80 XPath, 68-71 current context, 68-69 filtering capability, 69-70 indexing collections, 71 XPathDocument class, 72 XPathNavigator class, 71-75 navigating nodes, 74-75 selecting nodes, 72-73 XPathNodeIterator class, 73 XSD schemas creating, 76-78 validating XML files, 78-80 zero-impact installations, 275