Tải bản đầy đủ (.pdf) (654 trang)

microsoft reporting services in actionmanning publications

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (16.54 MB, 654 trang )

Teo Lachev
MANNING
Microsoft
Reporting
Services
IN ACTION
TEAM LinG
Microsoft Reporting Services in Action

Microsoft Reporting
Services in Action
TEO LACHEV
MANNING
Greenwich
(74° w. long.)
For online information and ordering of this and other Manning books, please go to
www.manning.com. The publisher offers discounts on this book when ordered in
quantity. For more information, please contact:
Special Sales Department
Manning Publications Co.
209 Bruce Park Avenue Fax: (203) 661-9018
Greenwich, CT 06830 email:
©2005 by Manning Publications Co. All rights reserved.
No part of this publication may be reproduced, stored in a retrieval system, or transmitted,
in any form or by means electronic, mechanical, photocopying, or otherwise, without prior
written permission of the publisher.
Many of the designations used by manufacturers and sellers to distinguish their products are
claimed as trademarks. Where those designations appear in the book, and Manning
Publications was aware of a trademark claim, the designations have been printed in initial
caps or all caps.
Recognizing the importance of preserving what has been written, it is Manning’s policy to have


the books we publish printed on acid-free paper, and we exert our best efforts to that end.
Manning Publications Co. Copyeditor: Linda Recktenwald
209 Bruce Park Avenue Typesetter: Denis Dalinnik
Greenwich, CT 06830 Cover designer: Leslie Haimes
ISBN 1-932394-22-2
Printed in the United States of America
12345678910–VHG–0807060504
To my beautiful wife, Elena,
and our lovely children, Maya and Martin,
for your sacrifices in making this book a reality
To my parents
for supporting my decisions to take the road less traveled
and for always being very proud of me

vii
brief contents
1 Introducing Microsoft Reporting Services 1
2 Report authoring basics 39
3 Working with data 63
4 Designing reports 102
5 Using expressions and functions 142
6 Using custom code 183
7 Managing the Reporting Services environment 215
8 Securing Reporting Services 260
9 On-demand report delivery 299
10 Reporting for Windows Forms applications 337
11 Reporting for web-based applications 377
12 Reporting for OLAP applications 416
13 Enterprise reporting 456
14 Subscribed report delivery 483

15 Extending Reporting Services 517
16 Performance and scalability 566

ix
contents
foreword xix
preface xxi
acknowledgments xxiii
roadmap xxv
source code xxviii
author online xxxiii
about the title and cover xxxiv
1 Introducing Microsoft Reporting Services 1
1.1 What is RS? 2
Why do we need RS? 2 ✦ How is RS implemented? 4
RS and the Microsoft BI platform 5
1.2 RS at a glance 6
Authoring features 7 ✦ Management features 8
Delivery features 9
✦ Extensibility features 9
Scalability features 10
✦ Security features 10
Deployment features 11
1.3 RS architecture 11
The Report Server 13 ✦ The Report Server database 14
The Report Manager 15
1.4 Understanding Report Processing 17
Execution stage 18 ✦ Rendering stage 18
1.5 Delivering reports 20
On-demand delivery 20 ✦ Subscribed delivery 21

1.6 What is the report lifecycle? 22
1.7 RS in action 23
About the Adventure Works Reporter 23 ✦ Your first
report 24
1.8 Evaluating RS 33
x CONTENTS
1.9 Summary 35
1.10 Resources 35
Part 1 Authoring reports 37
2 Report authoring basics 39
2.1 The report-authoring process: step by step 40
Analysis 41 ✦ Construction 42 ✦ Testing 42
Deployment 42
2.2 Authoring reports in VS.NET 43
Authoring reports with the Report Wizard 43 ✦ Authoring
reports with the Report Designer 44
✦ Importing reports
from Microsoft Access 53
2.3 Creating reports programmatically 55
The AW Ad Hoc Reporter sample 56 ✦ Implementation
details 58
2.4 Creating reports with third-party tools 60
Cizer’s Quick Query 60 ✦ Hitachi’s RDL Generator 62
2.5 Summary 62
2.6 Resources 62
3 Working with data 63
3.1 Working with data sources 63
Connecting to the database 64 ✦ Choosing an authentication
mechanism 69
✦ Deploying data sources 77

3.2 Working with report datasets 77
Understanding the dataset definition 78 ✦ Creating a report
dataset 79
✦ Using multiple datasets 83
3.3 Authoring dataset queries 84
Using the Graphical Query Designer 84 ✦ Using the Generic
Query Designer 86
3.4 Parameter-driven reports 89
The role of parameters 89 ✦ Building parameter-driven
queries 90
✦ Setting up the report-level parameters 92
Working with stored procedures 95
3.5 Data limitations 100
Data source limitations 100 ✦ Parameter limitations 101
3.6 Summary 101
3.7 Resources 101
CONTENTS xi
4 Designing reports 102
4.1 Anatomy of a report 103
Getting started with a new report 104 ✦ Understanding report
sections 104
✦ Understanding report items 105
Understanding data regions 107
4.2 Designing tabular reports 109
Parameterized tabular reports 113 ✦ Tabular reports with
interactive features 117
✦ Table region limitations 119
4.3 Designing freeform reports 119
Freeform reports with nested regions 119 ✦ Grouping freeform
data 121

✦ Freeform reports with side-by-side data
regions 123
4.4 Designing Chart Reports 124
The chart data region 124 ✦ Working with charts 126
Nesting chart regions 127
4.5 Designing crosstab reports 129
Matrix region advantages 129 ✦ Working with the matrix
region 130
✦ Adjusting the report layout 134
4.6 Designing Subreports 135
Laying out the report 136 ✦ Synchronizing the subreport with
the master report 137
4.7 Designing multicolumn reports 138
Setting up multiple columns 139 ✦ Testing multicolumn
reports 139
4.8 Summary 140
4.9 Resources 141
5 Using expressions and functions 142
5.1 Understanding expressions 143
Using the Expression Editor 143 ✦ Expression syntax 145
Determining expression execution order 145
✦ Understanding
expression scope 146
✦ Dealing with expression errors 147
5.2 Exploring the Report Object Model 148
Using the ReportItems collection 151 ✦ Using the Fields
collection 155
✦ Using the Parameters collection 157
Using the Globals collection 159
✦ Using the User

collection 159
5.3 Working with functions 160
Referencing external functions 160 ✦ Using aggregate
functions 161
✦ Using other internal functions 165
xii CONTENTS
5.4 Designing reports with navigational features 167
Reports with hyperlinks 168 ✦ Reports with document
maps 170
5.5 Report rendering considerations 173
Exporting reports to HTML 173 ✦ Exporting reports to
MHTML 174
✦ Exporting reports to HTML with Office Web
Components 174
✦ Exporting reports to other formats 176
5.6 Designing localized reports 177
Report localization basics 177 ✦ Localization techniques 179
5.7 Summary 181
5.8 Resources 182
6 Using custom code 183
6.1 Understanding custom code 184
Using embedded code 184 ✦ Using external
assemblies 187
6.2 Custom code in action: implementing report forecasting 191
Forecasting with OpenForecast 192 ✦ Implementing report
forecasting features 192
6.3 Using XML-based reports 204
Understanding XML exporting 205 ✦ Exposing the report
content as an RSS feed 205
6.4 Summary 210

6.5 Resources 211
Part 2 Managing reports 213
7 Managing the Reporting Services environment 215
7.1 Managing RS with the Report Manager 216
How the Report Manager works 216 ✦ Managing Report Server
settings 219
✦ Managing content 223 ✦ Managing report
execution 230
✦ Managing linked reports 240
7.2 Managing RS with the Web service 242
Understanding the Web service management API 242
Tracing calls to the SOAP API 242
✦ Deploying reports
programmatically 245
✦ Batching methods together 249
7.3 Managing RS with the WMI provider 249
Understanding the WMI provider 250 ✦ Implementing an RS
management console 251
CONTENTS xiii
7.4 Other ways to manage Reporting Services 253
Managing RS with the script host 253 ✦ Using other
management utilities 254
7.5 Analyzing report execution 255
Analyzing the Report Server execution log 255 ✦ Analyzing
trace log files 257
7.6 Summary 259
7.7 Resources 259
8 Securing Reporting Services 260
8.1 Exploring Reporting Services role-based security 261
How Windows authentication works 262 ✦ Using role-based

authorization 266
✦ Managing role-based security with the
Report Manager 272
✦ Managing role-based security with the
Web service 277
8.2 Understanding code access security 281
Defining code access terminology 281 ✦ Exploring the RS
default security policy 285
✦ Managing RS code access
security 286
8.3 Best practices for securing reports 290
Filtering data 291 ✦ Using dynamic dataset queries 292
Implementing custom security models 294
✦ Enforcing a
secured connection to the Report Server 294
8.4 Summary 295
8.5 Resources 295
Part 3 Delivering reports 297
9 On-demand report delivery 299
9.1 How RS provides on-demand report delivery 300
9.2 URL-based report access 301
Understanding URL syntax 302 ✦ Requesting resources
by URL 303
✦ Requesting reports by URL 305 ✦ Working
with report commands 306
✦ Working with the HTML
Viewer 309
✦ URL access in action 312
9.3 Web service-based report access 317
Requesting reports with SOAP 318 ✦ Rendering images 321

Handing report sessions 324
✦ Automating the report
generation process 327
xiv CONTENTS
9.4 Evaluating URL and Web service access options 331
Evaluating URL access 332 ✦ Evaluating Web service
access 334
✦ Choosing an integration approach 334
9.5 Summary 335
9.6 Resources 336
10 Reporting for Windows Forms applications 337
10.1 Rich client wanted 338
Report-enabling rich clients 338 ✦ Using the Client-to-Report
Server model 339
✦ Using the Client-to-Façade-to-Report
Server model 341
10.2 Introducing the Adventure Works Report Wizard 342
Designing the Report Wizard 343 ✦ The Report Wizard step-
by-step 344
10.3 Behind the scenes of the Adventure Works Report Wizard 348
Implementing the application framework 349 ✦ Selecting
reports 354
✦ Dealing with snapshot reports 359
Handling report parameters 359
✦ Specifying the export
format 368
✦ Confirming the report request 368
10.4 Enhancing application performance 370
Using in-memory caching 371 ✦ Using multithreading 372
10.5 Summary 375

10.6 Resources 376
11 Reporting for web-based applications 377
11.1 Understanding web reporting 378
Reporting for intranet applications 378 ✦ Reporting for
Internet applications 379
✦ Reporting for extranet
applications 382
✦ Introducing the Adventure Works Web
Reporter 383
11.2 Client-side reporting techniques 384
Requesting reports from hyperlinks 384 ✦ Creating write-back
reports 388
✦ Using HTTP-POST 390 ✦ Calling the RS
Web service on the client side 392
11.3 Server-side reporting techniques 395
Using the ReportViewer control 396 ✦ Using the Adventure
Works ReportViewer control 399
✦ Reporting off application
datasets 407
✦ Business-to-consumer reporting 409
Business-to-business reporting 412
11.4 Summary 414
11.5 Resources 415
CONTENTS xv
12 Reporting for OLAP applications 416
12.1 Understanding OLAP 417
OLTP vs. OLAP 417 ✦ How Reporting Services and Analysis
Services compare 418
✦ Understanding the OLAP storage
model 419

✦ Designing OLAP solutions 422
12.2 Implementing an OLAP solution: AW Data Miner 424
Implementing the data warehouse 426 ✦ Implementing the
OLAP cube 427
✦ Authoring OLAP-based reports
with RS 440
✦ Implementing AW Data Miner 443
12.3 Summary 453
12.4 Resources 454
13 Enterprise reporting 456
13.1 Understanding enterprise reporting 457
Evaluating enterprise reporting 457 ✦ Introducing the
Adventure Works Enterprise Reporter 458
13.2 Behind the scenes of the Adventure Works Enterprise Reporter 461
Implementing the Report Configuration Store 462
Implementing the presentation layer 463
✦ Implementing the
Enterprise Reporting Façade 466
✦ Designing for
scalability 470
13.3 Implementing custom application authorization 472
Understanding the Windows Authorization Manager 472
Securing the AW Enterprise Reporter 478
13.4 Summary 481
13.5 Resources 481
14 Subscribed report delivery 483
14.1 Understanding subscribed report delivery 484
Subscription-based reporting scenarios 484 ✦ The subscriber-
publisher design pattern 484
✦ How the Reporting Services

subscription-based model works 485
14.2 Configuring subscribed report delivery 488
Creating a new subscription 489 ✦ Choosing the subscription
type 490
✦ Configuring delivery extensions 493
Managing subscriptions 495
14.3 Subscribed report delivery in action 497
“Pushing” reports via standard e-mail subscriptions 497
Archiving reports to a file share 499
✦ Sending reports to a data-
driven list of recipients 503
✦ Triggering subscriptions
programmatically 509
xvi CONTENTS
14.4 Summary 513
14.5 Resources 513
Part 4 Advanced reporting 515
15 Extending Reporting Services 517
15.1 Understanding Reporting Services extensibility 518
Understanding interface-based programming 518 ✦ Working
with interface inheritance 519
15.2 Reporting off ADO.NET datasets with a custom dataset data
extension 523
Design goals and tradeoffs 525 ✦ Authoring dataset-bound
reports 526
✦ Implementing the custom dataset
extension 533
✦ Debugging dataset extensions 537
15.3 Distributing reports to Web services using custom delivery extensions 537
Design goals and tradeoffs 538 ✦ Using the custom delivery

extension 539
✦ Implementing the custom delivery
extension 540
✦ Debugging custom delivery extensions 544
15.4 Implementing custom security 546
Design goals and tradeoffs 549 ✦ Intranet reporting with
custom security 550
✦ Implementing the custom security
extension 553
✦ Debugging the custom security
extension 560
15.5 Using custom HTTP modules 560
The HTTP module design goals and tradeoffs 561
Implementing the custom HTTP module 561
15.6 Considerations for custom rendering extensions 563
15.7 Summary 563
15.8 Resources 564
16 Performance and scalability 566
16.1 Understanding capacity planning 567
Capacity planning fundamentals 567 ✦ The capacity planning
process 572
16.2 Capacity planning with Reporting Services in action 577
Determining requirements 577 ✦ Setting up the testing
environment 580
✦ Performance testing 584
Analyzing performance results 585
✦ Identifying resource
constraints 587
✦ Eliminating resource constraints 589
CONTENTS xvii

16.3 Summary 592
16.4 Resources 593
appendix Installing Reporting Services 594
A.1 Choosing components to install 595
A.2 Selecting the service account 596
A.3 Specifying RS virtual folders 597
A.4 Configuring the Report Server database 599
A.5 Configuring Reporting Services for e-mail delivery 600
A.6 Setting up the RS samples 601
A.7 Configuring RS licensing mode 601
A.8 Post-installation steps 603
Installing RS sample reports 603 ✦ Backing up the
encryption key 604
A.9 Resources 604
index 605

xix
foreword
Let me let you in on a little secret: creating software at Microsoft is pretty similar to
creating software at any other company. I think many people’s perception is that
Microsoft designs products by having an army of market researchers carefully exam-
ining competitive products and surveying consumers to determine exactly what fea-
tures to put in the next release.
The reality is that most of the ideas that go into Microsoft products are the result
of small teams of people brainstorming in front of whiteboards or chatting in hall-
ways. I’m not saying we don’t know what competitors are doing or what customers
are asking for, but the process of translating real-world scenarios to requirements and
designs is much more organic than you might think. This flexible approach allows
teams to take a fresh look at existing problems as well as adapt to industry trends and
customer demands.

Case in point: when we started building Reporting Services, we didn’t set out to
copy what other companies had already done. Instead, we asked questions like “What
does it mean to build an enterprise reporting product?” “How do we enable people to
create powerful data visualizations without writing code?” and, most important of all,
“How can we build a platform that people can leverage in their own applications?” The
answer to this final question ended up driving a major part of the product’s design.
Building a platform is not something to be taken lightly. It requires that you spend
extra time factoring and documenting the interfaces between software components. It
means that your components should not use any “back doors” that are not available
to other developers using the platform. It also can change the order in which you build
the product—you have to focus on the nonvisual parts of the product before you work
on the user-facing ones. For example, the Reporting Services report processing engine
was up and running about a year before the graphical report design tool was ready.
During this time, report definition files had to be hand-coded in order to test any new
report processing features.
The decision to build a platform also means that you will have to spend time on
infrastructure and interfaces at the expense of end-user features. We knew that this
trade-off would mean the first version of Reporting Services might look less feature-rich
than other more “mature” reporting products. We felt like this was the right long-term
xx FOREWORD
strategy, as a strong platform would enable others to fill the gaps instead of having to
wait for us to add every feature. When asked about this approach, I sometimes pose
the question, “Is it better to build a car with a powerful engine and fewer lights on the
dashboard or one with lots of lights that can’t go anywhere?”
One decision we made for our new platform was to bet on another new platform:
.
NET. As we had no legacy code to support, we decided early on to make Reporting
Services a 100 percent .
NET application. While this may seem like a no-brainer today,
when we started building Reporting Services the

CLR and the .NET Framework had
not yet been released. Although building an enterprise-quality server product on such
a new technology stack was a little risky at the time, the decision has paid major div-
idends in developer productivity and product quality.
Ultimately, the barometer of whether we have succeeded is what our customers and
partners are able to build on the platform. Since we released the first version of the
product earlier this year, I have seen applications built by customers leveraging the
Reporting Services platform in ways I never imagined. But a platform isn’t useful if
all developers don’t have the know-how to take advantage of it. Because the product
is so new, detailed information and good examples have been sparse and hard to find.
That’s where resources like Teo’s excellent book come in. This book starts by pro-
viding a solid foundation for using the built-in tools included with Reporting Services
but quickly takes you to the next level by focusing on the programmability and exten-
sibility aspects of the product. The focus on these parts of Reporting Services will help
you leverage and extend the product feature set in your own applications. Teo’s
approach is to provide real-world examples and useful scenarios that walk you through
the details and give you new ideas to explore. Teo has the ability to take complex topics
and break them into smaller sections that can be easily understood. I enjoyed being
one of the book’s technical reviewers as I was able see how various parts of the product
came to life on the page. I encourage you to use the ideas in this book and take Report-
ing Services to the next level.
B
RIAN WELCKER
Group Program Manager
Microsoft
SQL Server Reporting Services
xxi
preface
In archeology, the Rosetta stone was the key that solved the mysteries of Egyptian
hieroglyphics. I believe that with the release of Microsoft

SQL Server 2000 Reporting
Services, code-named Rosetta, Microsoft gives organizations the key they need to
unlock the secrets of enterprise data and unleash the power hidden within.
Looking retrospectively, Microsoft’s reporting strategy has been confusing, at least
for me. Microsoft Access debuted in the early 90s with a powerful report designer that
made desktop reporting child’s play.
Enterprise developers, however, have not been that lucky. The lack of comprehen-
sive native reporting capabilities continues even today in the .
NET framework. True,
some progress has been made with the advent of print-related controls, such as Print-
Document, PrintPreviewControl, and so on, but still, dealing with the
GDI+ (Graph-
ics Device Interface)
API is usually the last thing a developer wants to tackle when
creating the next line-of-business application. For reasons such as these, report-
enabling Microsoft-centric solutions has been traditionally regarded as a tedious chore.
To address this problem, many of us defected to third-party tools. Others chose to
fill the void with homegrown, customized solutions. While these solutions address par-
ticular needs, they can also be costly, time-consuming, and difficult to implement.
I remember with nostalgia a project that I worked on about five years ago. It called
for developing a reporting solution for a major Fortune 100 company. I implemented
the solution as a server-based framework, following a design pattern similar to the one
discussed in chapter 13. I used Microsoft Access as a reporting tool to generate reports
and save them as snapshot files. Once the report was ready, the Report Server would
e-mail it back to the user or send the user a link to the snapshot file.
Implementing this solution was a lot of fun, but it took a significant development
effort. I wouldn’t have had to do all of this if I had had Reporting Services back then.
Instead of implementing a homegrown solution, I could have used
RS to report-enable
the applications.

For this reason, I was very excited when I heard about Reporting Services in late
2003. Finally, there was an easy way to report-enable different types of applications.
Subsequently, I was involved in a project where I was able to confirm to myself that,
indeed,
RS was the reporting platform I had been dreaming about for years.
xxii PREFACE
To share my enthusiasm I decided to write a book about Reporting Services. While
I contemplated what the book’s scope would be, it dawned on me that I could bring
the most value by following my heart and approaching Reporting Services from a
developer’s point of view. I put myself in a position that many developers could relate
to. Here I am, a developer, consultant, and architect, who is tasked with adding report-
ing features to a given application. How would I go about this?
To answer this question, my book takes a solution-oriented approach, and more
than half of it is devoted to integrating different types of applications with
RS. As you
read this book, you will discover a common pattern. It starts by discussing the require-
ments and design goals of a given reporting scenario. Then it discusses the implemen-
tation choices, and finally it explains how the solution is implemented.
I firmly believe that a technical book should go beyond rehashing the product doc-
umentation. I tried my best to follow this path and take up where the
RS documenta-
tion (which, by the way, is excellent) leaves off. For this reason, my book should be used
in conjunction with it. When you read the book, you will notice that sometimes, when
I believe I can’t explain things any better, I refer you to the product documentation.
Microsoft Reporting Services in Action is written for report authors, administrators, and
developers who need a detailed and practical guide to the functionality provided by
RS.
In the first half, report authors will master the skills they need to create versatile reports.
Administrators will learn the ropes of managing and securing the report environment.
The second half of the book is primarily aimed at intermediate-to-advanced .

NET
developers who are planning to leverage RS to add reporting capabilities to their Win-
dows Forms or web-based applications. However, because of the service-oriented
architecture of Reporting Services, the book will also benefit developers who target
other platforms but want to integrate their applications with
RS.
Microsoft
SQL Server 2000 Reporting Services is a great piece of technology. With
RS, report authors can create reports as easily as you would do it in Microsoft Access.
Make no mistake, though.
RS is a sophisticated server-based platform, and its feature
set goes well beyond that of a desktop reporting tool. To use
RS effectively, you need
to have a solid grasp of how it works and how it can be integrated with different types
of client applications. I hope this book makes this endeavor easier.
xxiii
acknowledgments
Writing this book has been a lot of fun and a lot of work. Although you see only my
name on the front cover, this book has been a team effort involving many people.
First and foremost, I would like to acknowledge my family for their kind support
in making this book a reality. My wife, Elena, contributed directly to the book by
helping me recover what was lost in the process of translation. To my family I owe my
greatest thanks.
Thanks to the Reporting Services team at Redmond for giving us this great product
and working hard to make it even more successful. You can judge by yourself Microsoft’s
commitment to customer satisfaction by looking at the number of messages answered by
Microsoft engineers on the
RS discussion list (microsoft.public.sqlserver.reportingsvcs).
Brian Welcker, Microsoft Group Product Manager for
SQL Server Business Intel-

ligence, has been phenomenal in helping me with my project on several fronts, includ-
ing reviewing the book and providing valuable technical feedback, as well as writing
the foreword.
Thanks go to several Microsoft engineers—Brian Hartman, Bryan Keller, Daniel
Reib, and Tudor Trufinescu—for reviewing parts of this book. Not only did these folks
not mind my constant pestering, but they were even more eager to help make this book
as technically accurate as possible.
I am grateful to the Manning team for publishing Microsoft Reporting Services in
Action and demanding my best to ensure that this book meets the highest standards.
Thanks to Dr. Marjan Bace for giving a chance to an aspiring author. Thanks to my
development editors, Ann Navarro and Lianna Wlasiuk, for not losing faith that my
incoherent writings could turn into something readable. As project editor, Mary Pier-
gies has been outstanding in orchestrating the production process. My copy editors,
Liz Welch and Linda Recktenwald, did a great job in polishing my manuscript. Kudos
to my tech editor, Todd Meister, for verifying that the book is technically correct, and
to Susan Forsyth for proofreading the manuscript. Thanks also to Dr. Dave Roberson
for organizing the technical review process and to my technical reviewers, Alexzander
Nepomnjashiy and Mark Monster, for reviewing the manuscript. Thanks to the
book’s publicist, Helen Times, for getting the word out. I am grateful to the rest of
the Manning production team for their many contributions to this book.
xxiv ACKNOWLEDGMENTS
I must also acknowledge my coworkers from Extreme Logic, now part of the
Hewlett-Packard Enterprise Services group, for the productive and competitive
environment that I found so exciting and invigorating. I consider myself very fortu-
nate for having been part of this community for the past four years.
There are a few other people who contributed indirectly to the book. Thanks to
Steven Gould for his Open Source OpenForecast package that I used in chapter 6 for
the report-forecasting example. Thanks to Dino Esposito for his CodeDom sample.
Kudos to Peter Bromberg for the
ASP.NET menu control and to Christian Weyer for

the dynamic Web services invocation sample.
My thanks also to the many unnamed developers for their altruistic support on the
.
NET discussion lists. I admire your willingness to help. Your contributions kept me
sane during many dire moments in my career! Thanks also to Google for archiving the
newsgroup content and making it easily accessible.
I would especially like to acknowledge my parents, Zlatka and Stefan Lachev, for
supporting me in my choice of studying computer engineering, despite the fact that
a career in medicine or in the army looked much more promising at the time.
Finally, thank you for purchasing this book! I sincerely hope that you will find it
as enjoyable to read as it has been for me to write!
Thanks and happy reporting!

×