100% found this document useful (19 votes)
3K views

The Complete Reference To Professional SOA With Visual Studio 2005 Dot NET 3.0

SOA with Visual Studio 2005 .

Uploaded by

varunkaushish
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (19 votes)
3K views

The Complete Reference To Professional SOA With Visual Studio 2005 Dot NET 3.0

SOA with Visual Studio 2005 .

Uploaded by

varunkaushish
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 789

The Complete Reference To Professional SOA

With Visual Studio 2005


(C# & VB 2005) .NET 3.0

Tom Yuan Gao


Published By
LULU Press
Copyright © 2007 by Tom Yuan Gao

All rights reserved. No part of the content of this book may be reproduced or transmitted in any form or
by any means without the written permission of the author.
About The Author

Tom Yuan Gao has been developing software for over ten years. Having completed Unisys Scholarship at
University of Sydney at the age of 16. He is current a Microsoft Certified Application Developer (MCAD),
Microsoft Certified Solution Developer (MCSD), Microsoft Certified Database Administrator (MCDBA),
Microsoft Certified Trainer (MCT) as well as Nationaly Accredited IT Trainer within Australia. He has also
given lecture at universities on the benefits of Service Orientated Architecture. Tom is currently completing his
Doctorate in Distributed Software Security. In his spare time he can be found on his Windows Communication
Foundation Community Center at http://www.mswcf.com ran for solution/enterprise architects. Tom is currently
working as the National Technical Manager for EuroRSCG World Wide.
Letter from the Author

The concept of service orientation has been around for a very long time. The idea of service orientation is about
developing structured reusable solutions that can be used over and over again. Although the concept itself is
simplistic there has been no consistent and uniform means of achieving service orientation until recently when
Microsoft has targeted the service orientation area with the release of ASP.NET.
Microsoft’s support for service orientation through ASP.NET XML Web service has generated
overwhelming support within the industry. The .NET framework coupled with the revolutionary development
environment Visual Studio 2005 will revolutionize the way you view and develop future applications.
In this book I will take you through the hype and myth of service orientation and into the real world of
experience that will help you understand and transform the way you view and develop applications within your
enterprise architecture. We will investigate the reasons to why service oriented architecture can help application
infrastructures in terms of flexibility, interoperability, and integration.
The book is divided into two parts. The first part deals with theory and concepts of service orientation. We
will be exploring the risks and trade offs that are required. We will also learn how to meet enterprise
requirements for availability, scalability and security. For IT managers and business stakeholders we will explore
the concept of generating additional customer base through the previously taboo subject of exposing and yet
protecting your intellectual property.
The second part of the book focuses on the application of service orientation through ASP.NET XML Web
Services. You will learn to use and take advantage of the newly released Visual Studio 2005 development
environment, through step by step guides for each and every example in both Visual C# and Visual Basic .NET.
You will also learn to develop XML Web Services to supplement the concepts you have learnt in part one of the
book.
This book is a worthwhile investment and I thank you for purchasing it. I thank you for taking the effort to
take one step beyond everyone else, beyond your competitors.

Tom Yuan Gao


MCAD, MCSD, MCDBA, MCT, Accredited Trainer
Voting Member of OASIS for Web Service Standards
Founder of Microsoft Windows Communication Foundation Community Center (www.mswcf.com)
Acknowledgement

I have to say that this book would not have been possible without the support from my family and friends. To my
dad, who was my role model in persistence and hard work. To my mum, who has always taught to be efficient
and smart.
There are a few that I would be enternally grateful to. I would have to thank Todd Meister and Fabio
Claudio Ferracchiati for their relentless effort in technical review and in getting every detail perfect as it were
intended. Thanks to Peter Hovany, Bill Heish, David Abraham and Marlon Deleon for their encouragements
during some very difficult times.

Chinese proverb – “The journey of 1000 miles begins with a single step.”
Resource

As a reward for purchasing this book I have also made The Complete Reference to Professional SOA with
Visual Studio 2005 (Visual C# & VB 2005) available for you to download. You will be able to find the book on
http://www.mswcf.com/BookSOA.zip
Source code for both series can be found on

http://www.mswcf.com/source.zip
Foreword

The concepts behind SOA has been with us for many years, but it’s not until recent times with advances in
Microsoft .NET and Sun’s Java that some of the services that architects, business decision takers and visionaries
have envisioned, can finally be implemented in a reusable and platform agnostic manner.
The hype behind SOA in recent years has helped increase the knowledge and the request for Service-
oriented solutions; which in essence is all about moving away from data silos (where information often are
proprietary and hard to access), to open and interchangeable services that deliver the data you need, when you
need it, and allowing you to form these services to fit your business processes and create tangible benefits.
Government, military and private customers are rapidly increasing their demand for service-oriented
platforms that are secure and easy-to-use. This means it has become more important to learn and understand the
concepts and gain the technical skills to implement service-oriented solutions.
This book delivers great content for developers and it can empower you (as a developer and architect) to
better educate others about the benefits and reality behind Service-oriented solutions. It also delivers
comprehensive technical content that is easily understood by business people and decision makers. This is a
book I will promote to everyone involved in business and IT process improvement.
The book can enable you to become better at providing new and innovative solutions that help solve your
customer’s most challenging problems, and can give you inspiration to look at your own internal business
processes in a new light.
Tom delivers the content in a clear and concise way. Tom will guide you through how to start building a
Web Service, how to consume it, how to debug it, and how to finally deploy it into your testing, staging or
production environments. This book is a book for professionals who want to develop quality service-oriented
solutions.
Tom starts out by explaining the core concepts of SOA, allowing you to better understand and start learning
some of the new and innovative ways of thinking. Then going through and giving you a real description what
Web Services is all about without the hype.
If you are new to the whole concept of Web Services, Tom explains the basics of XML based technologies
like XML Schema, SOAP and WSDL which are the foundations of Web Services.
You will learn some of the more advanced topics with building Web Services, important topics like security
and logging. Tom will show you how to use some of the WS-* standard specification, especially WS-Security
with encryption and signing of messages, how to make a custom username service on WSE 3.0 (Web Service
Enhancements), and much more.
There is a special chapter dedicated to Windows Communication Foundation which is the new and unified
communication platform coming with the release of Microsoft .NET Framework 3.0, released around Windows
Vista timeframe. This can prepare you for the future changes for developing communication solutions with
Visual Studio.
Microsoft released a version of Visual Studio for software architects, where they introduced some new
features that can help you plan your overall architecture of your distributed service-oriented solutions. Part of
this initiative is the Distributed System Designers that Tom covers comprehensively in this book. These give you
capabilities to model and manage distributed solutions directly from Visual Studio, making deployment
packages and validating them against your server-farms amongst other things.
Look no further for a full in-depth review of Service-oriented architecture and technologies. Tom has
written an excellent book for professionals, that will guide you through the process of building services the way
they where meant to be.

Hope you all enjoy this book as much as I did!


Sondre Bjellås
Microsoft Regional Director

Software Architect & Product Manager


Table of Contents
ABOUT THE AUTHOR ................................................................................................................................................. 3
LETTER FROM THE AUTHOR .................................................................................................................................. 4
ACKNOWLEDGEMENT............................................................................................................................................... 5
RESOURCE ..................................................................................................................................................................... 6
FOREWORD.................................................................................................................................................................... 7
PART 1 CORE CONCEPTS......................................................................................................................................... 21
CHAPTER 1: INTRODUCTION TO SERVICE ORIENTED ARCHITECTURE ................................................ 21
WHAT IS SERVICE ORIENTED ARCHITECTURE?............................................................................................ 22
EXPLAINING SERVICE ORIENTED ARCHITECTURE USING METROPOLIS ....................................................................... 22
Cities as Software Vendors..................................................................................................................................... 23
Factories and Buildings as Applications................................................................................................................ 23
Transportation as Communication ......................................................................................................................... 23
Manufactured Goods as Standardization ............................................................................................................... 24
Manufactured Components as Virtual Enterprises ................................................................................................ 24
Urban Infrastructure as IT Infrastructure Evolution ............................................................................................. 24
ENTERPRISE ARCHITECTURE............................................................................................................................... 25
ARCHITECTURAL TRADEOFF TRIANGLE ....................................................................................................................... 25
ARCHITECTURAL TRADEOFF MATRIX .......................................................................................................................... 26
UNDERSTANDING BUSINESS BENEFITS OF SOA.............................................................................................. 26
BETTER VISIBILITY INTO OPERATIONS AND PERFORMANCE ........................................................................................ 27
MORE EFFICIENT OPERATIONS .................................................................................................................................... 27
BETTER BUSINESS AGILITY ......................................................................................................................................... 27
WHAT IS A WEB SERVICE? ..................................................................................................................................... 28
LOOSE COUPLING ........................................................................................................................................................ 28
SERVICES ..................................................................................................................................................................... 29
XML WEB SERVICES ................................................................................................................................................... 29
XML and XML Schema........................................................................................................................................... 29
XPath...................................................................................................................................................................... 30
SOAP ...................................................................................................................................................................... 30
WSDL ..................................................................................................................................................................... 31
UDDI ...................................................................................................................................................................... 31
SERVICE ORIENTED ARCHITECTURE WITH WEB SERVICE ............................................................................................ 32
WEB SERVICE AND SOA TECHNOLOGY SOUP ................................................................................................. 32
SERVICE ORIENTED ENTERPRISE ARCHITECTURE...................................................................................... 33
ADOPTING THE LEGACY ENTERPRISE ARCHITECTURE BEAST...................................................................................... 33
ENTERPRISE ARCHITECTURE USING SOA .................................................................................................................... 34
SO IS SERVICE ORIENTED ARCHITECTURE A BREAKTHROUGH? ........................................................... 36
CASE STUDIES............................................................................................................................................................. 37
WHICH INDUSTRY IS BEST FOR SOA........................................................................................................................... 37
The Drive for SOA .................................................................................................................................................. 37
CASE STUDY: STARWOOD HOTELS USES SOA TO IMPROVE GUEST SERVICES AND CUT COSTS .................................. 38
CASE STUDY: HARLEY-DAVIDSON .............................................................................................................................. 39
CASE STUDY: IBM TOWARDS SOA ............................................................................................................................. 39
CASE STUDY: MICROSOFT SOA (MILTON KEYNES GENERAL HOSPITAL) ................................................................... 40
CASE STUDY: GFK MARKET RESEARCH ...................................................................................................................... 41
CASE STUDY: PUREPROFILE ........................................................................................................................................ 42
CASE STUDY: AMAZING PEOPLE .................................................................................................................................. 42
CASE STUDY: SUNSHINE SUGAR .................................................................................................................................. 43
CASE STUDY: INTELLIFIELD ......................................................................................................................................... 43
SUMMARY .................................................................................................................................................................... 43
CHAPTER 2 IMPLEMENTING SERVICE ORIENTED ARCHITECTURE ....................................................... 45
SOA ARCHITECTURAL ROADMAP ....................................................................................................................... 45
WHAT IS A SOA ROADMAP AND WHY DO YOU NEED ONE? ....................................................................................... 45
HOW TO BUILD A SOA ROADMAP ................................................................................................................................ 45
SOA planning ......................................................................................................................................................... 47
SOA maturity assessment ....................................................................................................................................... 47
SOA future vision.................................................................................................................................................... 48
SOA roadmap definition ......................................................................................................................................... 48
Iterative Quality Assurance .................................................................................................................................... 48
SOA GOVERNANCE ..................................................................................................................................................... 48
ENTERPRISE SERVICE ENABLING ARCHITECTURES.................................................................................... 49
SERVICE TYPES ............................................................................................................................................................ 49
Basic services ......................................................................................................................................................... 49
Data-Centric Services ............................................................................................................................................ 49
Logic-Centric Services ........................................................................................................................................... 50
Transitional Services .............................................................................................................................................. 50
Public Services ....................................................................................................................................................... 50
SOA WEB SERVICE TRANSFORMING LOGICAL LAYERS TO PHYSICAL TIERS............................................................... 50
STARTING YOUR ENTERPRISE SOA WITH ENTITY AGGREGATION ............................................................................... 51
Single View of Entity .............................................................................................................................................. 52
Horizontal Partitions.............................................................................................................................................. 53
Cross Entities Query............................................................................................................................................... 53
ENTERPRISE APPLICATION INTEGRATION (EAI) .......................................................................................................... 54
Web Service Choreography Interface (WSCI)........................................................................................................ 55
Business Process Execution Language for Web Services (BPEL4WS) .................................................................. 56
Coordination Services ............................................................................................................................................ 56
DISTRIBUTED EVENT DRIVEN ARCHITECTURE AND SOA ............................................................................................ 57
ENTERPRISE SERVICE BUS & SERVICES ....................................................................................................................... 57
Mediation support .................................................................................................................................................. 60
Protocol independence ........................................................................................................................................... 60
Web Service Management Orchestration ............................................................................................................... 60
SECURITY IN SERVICE ORIENTED ARCHITECTURE ....................................................................................................... 61
Security Basics ....................................................................................................................................................... 62
Web Service Security .............................................................................................................................................. 63
Message Reliability in Service Oriented Architecture............................................................................................ 70
SUMMARY .................................................................................................................................................................... 71
CHAPTER 3 BUSINESS ADAPTATION OF SOA ................................................................................................... 73
SERVICE ORIENTATION AND ITS ROLE IN OUR CONNECTED SYSTEM STRATEGY ........................... 73
WHY DO WE NEED FLEXIBILITY?.................................................................................................................................. 74
AGILITY ....................................................................................................................................................................... 74
Technology ............................................................................................................................................................. 75
Communication & Location Issue .......................................................................................................................... 75
Business Process .................................................................................................................................................... 75
Business Functionality............................................................................................................................................ 76
Integration .............................................................................................................................................................. 76
Support ................................................................................................................................................................... 76
REDUCTION IN COST OF DEVELOPMENT ...................................................................................................................... 76
IT Cost Savings....................................................................................................................................................... 77
Business Cost Saving from SOA ............................................................................................................................. 77
OPENING OUR INTELLECTUAL PROPERTY...................................................................................................... 77
SUPPLIERS .................................................................................................................................................................... 78
CONSUMERS................................................................................................................................................................. 78
PROMOTING INTER-PLATFORM CONNECTION .............................................................................................. 79
MEASURING A SOA.................................................................................................................................................... 80
ORGANIZATIONAL ROADMAP .............................................................................................................................. 82
IDENTIFYING STAKEHOLDERS AND CONFLICTS ............................................................................................................ 82
Business and IT ...................................................................................................................................................... 83
Internal Politics...................................................................................................................................................... 83
ORGANIZATION VISION ................................................................................................................................................ 83
BUDGET CONSIDERATION ............................................................................................................................................ 84
GATHERING INTERNAL SUPPORT ................................................................................................................................. 84
SOA DRIVEN PROJECT DEVELOPMENT USING MSF ...................................................................................... 84
CHALLENGES AND OPPORTUNITIES .............................................................................................................................. 85
MSF TRACKS ............................................................................................................................................................... 85
MSF CMMI............................................................................................................................................................. 86
MSF Agile............................................................................................................................................................... 86
ENVISIONING TRACK ................................................................................................................................................... 87
PLANNING TRACK ........................................................................................................................................................ 87
DEVELOPING TRACK .................................................................................................................................................... 88
STABILIZING TRACK .................................................................................................................................................... 88
DEPLOYING TRACK ...................................................................................................................................................... 88
GOVERNANCE .............................................................................................................................................................. 89
OPERATIONAL MANAGEMENT ..................................................................................................................................... 89
CONTINUOUS TRACK ................................................................................................................................................... 89
PROJECT TEAMS ........................................................................................................................................................... 89
Program Management............................................................................................................................................ 90
Architecture ............................................................................................................................................................ 91
Development........................................................................................................................................................... 91
Test ......................................................................................................................................................................... 92
Release/Operations................................................................................................................................................. 92
User Experience ..................................................................................................................................................... 93
Product Management ............................................................................................................................................. 93
MSF RISK MANAGEMENT............................................................................................................................................ 93
SIMPLIFYING SOA DEVELOPMENT USING .NET AND VISUAL STUDIO 2005........................................... 94
USING VISUAL STUDIO 2005 TO CREATE A WEB SERVICE ............................................................................................ 95
USING VISUAL STUDIO 2005 TO CONSUME A WEB SERVICE ...................................................................................... 100
SUMMARY .................................................................................................................................................................. 103
PART 2 USING .NET WEB SERVICE 2.0 WITH VISUAL STUDIO 2005.......................................................... 104
CHAPTER 4 INTRODUCING .NET 2.0................................................................................................................... 104
.NET FRAMEWORK.................................................................................................................................................. 104
FEATURES OF THE COMMON LANGUAGE RUNTIME .................................................................................................... 106
MANAGED DEVELOPMENT ......................................................................................................................................... 107
.NET FRAMEWORK 2.0............................................................................................................................................ 108
VISUAL STUDIO 2005 TEAM ROLES.................................................................................................................... 108
VISUAL STUDIO 2005 EDITIONS........................................................................................................................... 110
THE VISUAL STUDIO IDE....................................................................................................................................... 111
WEB SERVICE TEMPLATE .................................................................................................................................... 111
VISUAL STUDIO 2005 PROJECTLESS DEVELOPMENT .................................................................................. 116
MIGRATING TO VISUAL STUDIO 2005 PROJECT............................................................................................ 116
VISUAL STUDIO IDE ................................................................................................................................................ 118
SOLUTION EXPLORER................................................................................................................................................. 120
DOCUMENT WINDOW................................................................................................................................................. 122
TOOLBOX ................................................................................................................................................................... 122
ERROR LIST................................................................................................................................................................ 123
TASK LIST .................................................................................................................................................................. 124
SERVER EXPLORER .................................................................................................................................................... 126
CODE WINDOW .......................................................................................................................................................... 127
Outlining............................................................................................................................................................... 127
IntelliSense Code Member List............................................................................................................................. 128
Error Underlining ................................................................................................................................................ 129
SUMMARY .................................................................................................................................................................. 130
CHAPTER 5 XML WEB SERVICES STANDARDS AND CONCEPTS .............................................................. 131
.NET WEB SERVICE MESSAGE FLOW................................................................................................................ 132
HTTP............................................................................................................................................................................. 134
THE GET AND POST METHODS ................................................................................................................................ 135
HTTP WITH .NET ..................................................................................................................................................... 137
XML .............................................................................................................................................................................. 141
ELEMENTS.................................................................................................................................................................. 142
ELEMENTS, NAMESPACES, AND NAMESPACE DECLARATIONS ..................................................................................... 142
ATTRIBUTES AND NAMESPACES................................................................................................................................. 144
COMMENTS ................................................................................................................................................................ 144
WHITESPACE .............................................................................................................................................................. 145
PROHIBITED CHARACTER LITERALS ........................................................................................................................... 145
CDATA SECTIONS ..................................................................................................................................................... 146
The XML declaration............................................................................................................................................ 146
WELL-FORMED XML................................................................................................................................................. 146
XML WITH VISUAL STUDIO 2005 .............................................................................................................................. 147
XML SCHEMA DEFINITION (XSD) ....................................................................................................................... 150
DATATYPES ............................................................................................................................................................... 150
Numeric types ....................................................................................................................................................... 150
Date and time types .............................................................................................................................................. 151
Name and string types .......................................................................................................................................... 152
Boolean................................................................................................................................................................. 152
Byte....................................................................................................................................................................... 152
Date ...................................................................................................................................................................... 152
dateTime ............................................................................................................................................................... 152
decimal ................................................................................................................................................................. 153
double ................................................................................................................................................................... 153
duration ................................................................................................................................................................ 153
gDay ..................................................................................................................................................................... 153
gMonth ................................................................................................................................................................. 153
gMonthDay........................................................................................................................................................... 154
gYear .................................................................................................................................................................... 154
gYearMonth .......................................................................................................................................................... 154
hexBinary.............................................................................................................................................................. 154
int.......................................................................................................................................................................... 154
integer................................................................................................................................................................... 155
language ............................................................................................................................................................... 155
long....................................................................................................................................................................... 155
Name..................................................................................................................................................................... 155
NCName ............................................................................................................................................................... 155
negativeInteger..................................................................................................................................................... 156
nonNegativeInteger .............................................................................................................................................. 156
nonPositiveInteger................................................................................................................................................ 156
normalizedString .................................................................................................................................................. 156
positiveInteger ...................................................................................................................................................... 156
QName.................................................................................................................................................................. 157
short...................................................................................................................................................................... 157
string..................................................................................................................................................................... 157
time ....................................................................................................................................................................... 157
token ..................................................................................................................................................................... 157
unsignedByte ........................................................................................................................................................ 158
unsignedInt ........................................................................................................................................................... 158
unsignedLong ....................................................................................................................................................... 158
unsignedShort....................................................................................................................................................... 158
FACETS........................................................................................................................................................................ 158
enumeration.......................................................................................................................................................... 159
fractionDigits........................................................................................................................................................ 159
length.................................................................................................................................................................... 159
maxExclusive ........................................................................................................................................................ 159
maxInclusive......................................................................................................................................................... 160
maxLength ............................................................................................................................................................ 160
minExclusive......................................................................................................................................................... 161
minInclusive.......................................................................................................................................................... 161
minLength............................................................................................................................................................. 161
pattern .................................................................................................................................................................. 162
totalDigits............................................................................................................................................................. 162
whiteSpace............................................................................................................................................................ 162
LANGUAGE CONSTRUCTS ........................................................................................................................................... 163
simpleType............................................................................................................................................................ 163
restriction ............................................................................................................................................................. 163
list ......................................................................................................................................................................... 163
Union.................................................................................................................................................................... 164
XML SCHEMA STRUCTURES ................................................................................................................................ 164
XSD WITH VISUAL STUDIO 2005 ............................................................................................................................... 168
SOAP............................................................................................................................................................................. 169
WEB SERVICES DESCRIPTION LANGUAGE (WSDL) ..................................................................................... 186
DEFINITIONS ............................................................................................................................................................... 186
TYPES ......................................................................................................................................................................... 187
MESSAGE .................................................................................................................................................................... 187
PORTTYPE .................................................................................................................................................................. 188
BINDING ..................................................................................................................................................................... 189
SERVICE ..................................................................................................................................................................... 189
.NET WEB SERVICE WSDL....................................................................................................................................... 190
UDDI V3 ....................................................................................................................................................................... 190
SUPPORT FOR DIGITAL SIGNATURE ............................................................................................................................. 191
UDDI SDK ................................................................................................................................................................ 191
WS-* STANDARDS..................................................................................................................................................... 192
SUMMARY .................................................................................................................................................................. 192
CHAPTER 6 DATABASE PROGRAMMING WITH ADO.NET .......................................................................... 194
ADO.NET ..................................................................................................................................................................... 194
WHAT IS NEW IN .NET 2.0......................................................................................................................................... 195
Async Data Access................................................................................................................................................ 195
Metadata Schemas................................................................................................................................................ 195
Query Notification ................................................................................................................................................ 196
Multiple Active Result Sets ................................................................................................................................... 196
User Defined, XML Data Types ........................................................................................................................... 197
THE ADO.NET ARCHITECTURE........................................................................................................................... 197
.NET DATASETS ........................................................................................................................................................ 197
DATA PROVIDERS ...................................................................................................................................................... 198
Connection............................................................................................................................................................ 198
Command ............................................................................................................................................................. 198
DataReader .......................................................................................................................................................... 198
DataAdapter ......................................................................................................................................................... 199
XML...................................................................................................................................................................... 199
Interoperability..................................................................................................................................................... 199
Maintainability ..................................................................................................................................................... 199
Programmability .................................................................................................................................................. 200
Performance ......................................................................................................................................................... 200
Scalability............................................................................................................................................................. 200
In-Memory Representations of Data .................................................................................................................... 200
Minimized Open Connections............................................................................................................................... 200
Sharing Data Between Applications..................................................................................................................... 201
OLE DB DATA PROVIDER IN .NET............................................................................................................................ 201
.NET Data Provider.............................................................................................................................................. 201
THE OLEDBCONNECTION CLASS ............................................................................................................................... 202
THE SQLCONNECTION CLASS .................................................................................................................................... 202
OPENING AND CLOSING CONNECTIONS ...................................................................................................................... 203
The OleDbCommand Class .................................................................................................................................. 204
The ExecuteScalar Method................................................................................................................................... 205
The ExecuteReader Method.................................................................................................................................. 205
The ExecuteNonQuery Method............................................................................................................................. 206
The SqlCommand Class........................................................................................................................................ 207
Using Data Adapters ............................................................................................................................................ 208
The SelectCommand Property .............................................................................................................................. 208
The InsertCommand Property .............................................................................................................................. 208
The UpdateCommand Property............................................................................................................................ 208
The DeleteCommand Property ............................................................................................................................. 209
The DataReader Class.......................................................................................................................................... 210
The SqlDataReader Class..................................................................................................................................... 211
The IsClosed() Method ......................................................................................................................................... 212
The RecordsAffected Property.............................................................................................................................. 212
The OleDbDataReader Class ............................................................................................................................... 212
DATA ACCESS USING VISUAL STUDIO 2005..................................................................................................... 212
WORKING WITH DATASETS................................................................................................................................. 221
CREATING ADO.NET DATASETS ......................................................................................................................... 227
MANIPULATING AN ADO.NET DATASET .......................................................................................................... 229
MERGING THE CONTENTS OF DATASETS ................................................................................................................... 229
CHECK PRIMARY KEYS .............................................................................................................................................. 229
PRESERVE CHANGES .................................................................................................................................................. 229
APPLY CONSTRAINTS ................................................................................................................................................. 230
COPYING DATASET CONTENTS .................................................................................................................................. 231
Creating Data Views ............................................................................................................................................ 231
Handling ADO.NET DataSet Events .................................................................................................................... 232
CREATING A TYPED ADO.NET DATASET ......................................................................................................... 233
MANUALLY CREATING A TYPED DATASET ................................................................................................................ 235
MANUALLY DEFINE TYPED DATASET ........................................................................................................................ 241
RELATIONSHIPS WITH TYPED DATASET ..................................................................................................................... 242
ADO.NET EXCEPTION HANDLING IN .NET ...................................................................................................... 243
WRITING SQLCLR STORED PROCEDURE WITH MS SQL SERVER 2005 .................................................. 245
THE CONTEXT CONNECTION ...................................................................................................................................... 245
.NET STORED PROCEDURE WITH EXECUTEREADER() ............................................................................................... 252
SUMMARY .................................................................................................................................................................. 255
CHAPTER 7 ACCESSING MANIPULATING XML WITH .NET ....................................................................... 257
DOCUMENT OBJECT MODEL ............................................................................................................................... 257
THE XML PARSER ..................................................................................................................................................... 264
XMLREADER AND XMLWRITER ......................................................................................................................... 266
READING XML USING XMLTEXTREADER ................................................................................................................. 267
WRITING XML USING XMLTEXTWRITER ................................................................................................................. 271
XPATHNAVIGATOR................................................................................................................................................. 274
XPATH ....................................................................................................................................................................... 274
XML SCHEMA XSD................................................................................................................................................... 277
XML VALIDATION ................................................................................................................................................... 280
XML AND DATASET................................................................................................................................................. 284
SUMMARY .................................................................................................................................................................. 289
CHAPTER 8 .NET XML SERIALIZATION............................................................................................................ 290
.NET SERIALIZATION ............................................................................................................................................. 290
ENABLE SERIALIZATION USING ATTRIBUTES ............................................................................................................. 290
SERIALIZATION FORMATTER ...................................................................................................................................... 292
XML SERIALIZATION ............................................................................................................................................. 299
CONTROLLING SERIALIZATION .................................................................................................................................. 302
XMLROOT AND XMLELEMENT .................................................................................................................................. 303
IGNORING ELEMENTS ................................................................................................................................................. 313
SERIALIZING ARRAYS ................................................................................................................................................ 314
XMLANYELEMENT AND XMLANYATTRIBUTE .......................................................................................................... 316
XMLINCLUDE - DERIVED DATA TYPES ............................................................................................................ 318
DATATYPE MAPPING ................................................................................................................................................. 319
STRONGLY TYPED XML SERIALIZATION ....................................................................................................... 320
OPEN SCHEMA WITH XMLANYATTRIBUTE AND XMLANYELEMENT ................................................... 332
SUMMARY .................................................................................................................................................................. 336
CHAPTER 9 CREATING AND CONSUMING WEB SERVICE USING VISUAL STUDIO 2005 ................... 337
WEB SERVICE SUMMARY ..................................................................................................................................... 337
CREATING XML WEB SERVICES......................................................................................................................... 338
DEPLOYING WEB SERVICE .................................................................................................................................. 354
WEB SERVICE FILE TYPES ......................................................................................................................................... 357
XML WEB SERVICES DISCOVERY MECHANISM............................................................................................ 357
ADDING CUSTOM DISCOVERY INFORMATION FOR A WEB SERVICE ........................................................................... 358
CONSUMING WEB SERVICE ................................................................................................................................. 359
CLIENT APPLICATION ........................................................................................................................................... 365
SUMMARY .................................................................................................................................................................. 376
CHAPTER 10 TESTING AND DEBUGGING AN XML WEB SERVICE ........................................................... 377
OVERVIEW OF THE TESTING PROCESS ........................................................................................................... 377
ORGANIZING THE TESTING EFFORT................................................................................................................ 378
REQUIREMENTS-BASED TESTING ............................................................................................................................... 378
DEVELOPING A TEST PLAN ........................................................................................................................................ 379
APPROACHES TO DEVELOP TEST PLANS .................................................................................................................... 379
The Waterfall Approach ....................................................................................................................................... 379
The Evolutionary/Agile Approach ........................................................................................................................ 379
THE FOUR PILLARS OF SUCCESSFUL TESTING............................................................................................. 379
PILLAR I: FUNCTIONAL & REGRESSION TESTING ....................................................................................................... 380
PILLAR II: PERFORMANCE .......................................................................................................................................... 380
PILLAR III: INTEROPERABILITY .................................................................................................................................. 380
PILLAR IV: VULNERABILITY ASSESSMENT ................................................................................................................ 381
DEBUGGING............................................................................................................................................................... 381
CORDBG.EXE .............................................................................................................................................................. 381
DEBUGGING USING VISUAL STUDIO 2005 ................................................................................................................. 386
The Watch Window............................................................................................................................................... 387
The Call Stack Window ........................................................................................................................................ 387
The Locals Window .............................................................................................................................................. 388
The Autos Window................................................................................................................................................ 388
The Breakpoint Window ....................................................................................................................................... 388
TESTING WITH VISUAL STUDIO 2005 ................................................................................................................ 390
UNIT TESTING ............................................................................................................................................................ 390
RUNNING TESTS ......................................................................................................................................................... 403
CODE COVERAGE ....................................................................................................................................................... 405
INITIALIZING AND CLEANING UP TESTS ..................................................................................................................... 406
STATIC ANALYSIS ................................................................................................................................................... 407
PROFILING................................................................................................................................................................. 408
SAMPLING .................................................................................................................................................................. 409
INSTRUMENTATION .................................................................................................................................................... 409
IMPLEMENTING SAMPLING ......................................................................................................................................... 409
SUMMARY .................................................................................................................................................................. 415
CHAPTER 11 DEPLOYMENT.................................................................................................................................. 417
.NET DEPLOYMENT................................................................................................................................................. 417
MAINTAINING ASSEMBLY VERSIONS............................................................................................................... 418
PACKAGING AND DISTRIBUTION OPTIONS.................................................................................................... 421
PUBLISHING WEB SERVICE ......................................................................................................................................... 422
PUBLISHING CLIENT APPLICATION USING CLICKONCE DEPLOYMENT ....................................................................... 426
ClickOnce and Windows Installer Comparison Table ......................................................................................... 426
Using ClickOnce Deployment .............................................................................................................................. 427
Publishing to File System ..................................................................................................................................... 427
Publishing To a Web Location ............................................................................................................................. 430
How ClickOnce Deployment Works ..................................................................................................................... 432
USING WEB DEPLOYMENT PROJECTS WITH VISUAL STUDIO 2005 ........................................................ 433
INSTALLING WEB DEPLOYMENT PROJECTS................................................................................................................ 433
BUILD MENU COMMAND ........................................................................................................................................... 434
WEB DEPLOYMENT PROJECT PROPERTY PAGES ........................................................................................................ 435
MANAGING CUSTOM BUILD CONFIGURATIONS ......................................................................................................... 439
WEB SETUP PROJECTS ............................................................................................................................................... 442
CREATING A WEB SETUP PROJECT FOR XML WEB SERVICE ..................................................................................... 443
SUMMARY .................................................................................................................................................................. 447
WEBMETHOD PROPERTIES.................................................................................................................................. 448
BUFFERING RESPONSE FOR A WEB METHOD ............................................................................................................. 448
CACHING THE RESULTS FOR A WEB METHOD ............................................................................................................ 453
SPECIFYING A DESCRIPTION FOR A WEB METHOD ..................................................................................................... 455
ENABLING SESSION STATE IN WEB METHOD ............................................................................................................. 456
IDENTIFYING OVERLOADED WEB METHODS USING AN ALIAS .................................................................................. 459
WEB METHOD TRANSACTION .................................................................................................................................... 460
ASYNCHRONOUS WEB SERVICE......................................................................................................................... 462
ASYNCHRONOUS DELEGATES .................................................................................................................................... 463
CONCURRENT ASYNCHRONOUS CALLS ...................................................................................................................... 470
IMPROVING RESPONSIVENESS IN WINDOWS CLIENT .................................................................................................. 473
SOAP EXTENSIONS .................................................................................................................................................. 477
USING SOAP EXTENSIONS......................................................................................................................................... 478
USING SOAPLOGGER.................................................................................................................................................. 491
SUMMARY .................................................................................................................................................................. 492
CHAPTER 13 .NET REMOTING ............................................................................................................................. 494
.NET REMOTING PROXY ARCHITECTURE ...................................................................................................... 494
REMOTABLE AND NONREMOTABLE OBJECTS ............................................................................................. 495
MARSHAL-BY-VALUE OBJECTS .................................................................................................................................. 495
MARSHAL-BY-REFERENCE OBJECTS .......................................................................................................................... 497
SERVER ACTIVATED AND CLIENT ACTIVATED OBJECTS......................................................................... 497
SERVER ACTIVATED OBJECTS (SAOS)....................................................................................................................... 498
Using Configuration File ..................................................................................................................................... 503
CLIENT ACTIVATED OBJECTS (CAOS) ....................................................................................................................... 507
Using Configuration File ..................................................................................................................................... 512
Using Lifetime Leases........................................................................................................................................... 513
Renewing Lifetime Leases .................................................................................................................................... 517
DIFFERENCES BETWEEN SERVER ACTIVATED OBJECTS AND CLIENT ACTIVATED OBJECTS ....................................... 519
TRANSPORT CHANNELS........................................................................................................................................ 520
TCP CHANNEL ........................................................................................................................................................... 520
HTTP CHANNEL ........................................................................................................................................................ 521
IPC Channel ......................................................................................................................................................... 524
CHANNEL SINKS....................................................................................................................................................... 527
REMOTABLE BANK DEBIT LOG .................................................................................................................................. 528
The Server............................................................................................................................................................. 529
The Client ............................................................................................................................................................. 537
SUMMARY .................................................................................................................................................................. 545
CHAPTER 14 WEB SERVICE SECURITY............................................................................................................. 546
WINDOWS AUTHENTICATION............................................................................................................................. 546
MANAGING USERS BY USING MEMBERSHIP .................................................................................................. 553
CREATING A MEMBERSHIP DATABASE ON SQL SERVER ........................................................................................... 555
CONFIGURING AN APPLICATION TO USE MEMBERSHIP .............................................................................................. 559
Using Web.Config ................................................................................................................................................ 560
Using ASP.NET Configuration Settings ............................................................................................................... 561
Implementing Membership ................................................................................................................................... 563
CUSTOM AUTHENTICATION AND AUTHORIZATION WITH SOAP HEADERS....................................... 567
DEFINING SOAP HEADERS ........................................................................................................................................ 567
DEFINING A SOAP HEADER CLIENT .......................................................................................................................... 570
IMPLEMENTING TOKEN AUTHENTICATION WITH SOAP HEADERS...................................................... 573
IMPLEMENTING SECURITY TOKEN SERVICE ............................................................................................................... 574
IMPLEMENT CLIENT FOR TOKEN SECURITY ............................................................................................................... 586
SUMMARY .................................................................................................................................................................. 590
CHAPTER 15 WEB SERVICES ENHANCEMENTS 3.0 ....................................................................................... 592
WEB SERVICES ENHANCEMENTS OVERVIEW............................................................................................... 592
WS-SECURITY ........................................................................................................................................................... 593
Security Tokens..................................................................................................................................................... 593
INSTALLING WEB SERVICES ENHANCEMENTS ............................................................................................ 594
USING WEB SERVICES ENHANCEMENTS......................................................................................................... 595
WSE COMMUNICATION PROCESS...................................................................................................................... 598
REQUESTING PROCESS ............................................................................................................................................... 598
RESPONSE PROCESS ................................................................................................................................................... 599
IMPLEMENTING WSE SERVICE................................................................................................................................... 600
IMPLEMENTING WSE CLIENT .................................................................................................................................... 608
IMPLEMENTING CUSTOM USERNAME SERVICE .......................................................................................................... 617
X. 509 CERTIFICATE ................................................................................................................................................ 625
THE X.509 CERTIFICATE MANAGEMENT TOOL.......................................................................................................... 625
WSECERTIFICATE3.EXE ............................................................................................................................................ 626
SIGN AND ENCRYPT A SOAP MESSAGE (END-TO-END SECURITY) ........................................................................... 628
Configuring WSE Web service to Sign and Encrypt............................................................................................. 628
Configuring WSE Client Application to Sign and Encrypt................................................................................... 630
BEST SECURITY PRACTICE ......................................................................................................................................... 633
BINARY EXCHANGE WITH MESSAGE TRANSMISSION OPTIMIZATION MECHANISM (MTOM) .... 633
IMPLEMENTING MTOM SERVICE............................................................................................................................... 635
IMPLEMENTING MTOM CLIENT ................................................................................................................................ 639
SUMMARY .................................................................................................................................................................. 641
CHAPTER 16. WINDOWS COMMUNICATION FOUNDATION (WCF) .......................................................... 642
WCF FOUNDAMENTALS ........................................................................................................................................ 643
CONTRACTS ............................................................................................................................................................... 644
Defining Service Contracts................................................................................................................................... 644
Defining Data Contracts ...................................................................................................................................... 645
RPC/Messaging .................................................................................................................................................... 648
BINDING AND ADDRESS (ENDPOINT) ......................................................................................................................... 651
IMPLEMENTING WCF SERVICES........................................................................................................................ 653
IMPLEMENTING WCF SERVICE .................................................................................................................................. 653
IMPLEMENTING A WCF SERVICE CLIENT .................................................................................................................. 661
IMPLEMENTING HOSTING ........................................................................................................................................... 671
IMPLEMENTING SECURE RELIABABLE MESSAGING.................................................................................................... 682
IMPLEMENTING CUSTOM BINDING, RELIABLE MESSAGING AND SECURITY ............................................................... 688
IMPLEMENTING WCF WITH MICROSOFT MESSAGE QUEUE........................................................................................ 698
WCF SESSIONS .......................................................................................................................................................... 713
WCF TRANSACTIONS................................................................................................................................................. 714
DUPLEX COMMUNICATION ........................................................................................................................................ 714
SUMMARY .................................................................................................................................................................. 723
CHAPTER 17. ARCHITECTURE CONCEPTUALIZATION WITH DISTRIBUTED SYSTEM
DESIGNERS ................................................................................................................................................................ 724
APPLICATION DESIGNER...................................................................................................................................... 724
IMPLEMENTING APPLICATION DESIGNER ................................................................................................................... 724
Connecting the Applications................................................................................................................................. 727
Defining Web Service Prototypes ......................................................................................................................... 732
Adding an Endpoint through WSDL ..................................................................................................................... 733
Implement the Application.................................................................................................................................... 736
UPDATING THE DESIGN .............................................................................................................................................. 740
ADDING A WEB APPLICATION .................................................................................................................................... 751
SETTINGS AND CONSTRAINTS .................................................................................................................................... 759
SYSTEM DESIGNER ................................................................................................................................................. 760
SPECIFYING LOGICAL DATACENTER DIAGRAM.......................................................................................... 765
SETTINGS AND CONSTRAINTS .................................................................................................................................... 771
Importing IIS Server Settings ............................................................................................................................... 771
DEPLOYMENT DIAGRAM ...................................................................................................................................... 775
CREATING THE DEPLOYMENT DIAGRAM.................................................................................................................... 775
VALIDATING THE DEPLOYMENT SCENARIO ............................................................................................................... 780
GENERATING DEPLOYMENT REPORT ......................................................................................................................... 783
SUMMARY .................................................................................................................................................................. 784
INDEXES...................................................................................................................................................................... 785
The Complete Reference To Professional SOA with Visual Studio 2005

Introduction
-Applications must retool or perish. Organizations that fail to realize the efficiencies of integration by-design will
lose in the long run to those who pursue them. – Pat Helland
Service Oriented Architecture has the potential to be the next great paradigm that will once and for all change
computing as we know it. The main promise of Service Oriented Architecture is that business systems can be
used by anyone, from anywhere, at any time and on any system.
The popularity in Service Oriented Architecture is largely generated by the ability to allow developers to
seamlessly integrate disparate systems without the requirement to understand the underlying technology specific
details. This abstraction from technology is due to the ability to build Business Services which are application
components that describe the application process instead of describing the technology. The use of Business
Services allows developers to efficiently integrate application processes between disparate systems that are either
internal to the organization or are maintained by another vendor without the requirement to have an intimate
knowledge about the system process.
Today more and more developers, architects and IT managers are turning to Service Oriented Architecture.
This growth in popularity is due to today’s increase in pressure to provide the outmost efficiency and reliability
in solution development. As a result developers and architects are driven to focus their efforts on developing
reusable components to ensure that they can be easily reused in future. With the focus of reusability in mind
developers and architects are able to develop and expand on existing enterprise systems quickly and efficiently.
Through Service Oriented Architecture, system development is unlike before. For the first time in the
history of software development, developers are able to build enterprise systems that can easily keep up with
business agility and changing business requirements whilst developing new functionalities. Service Oriented
Architecture is a revolution that we have all been waiting for.
Following the release of the second generation of the .NET.Framework, application development is on a
new level playing field. The people at Microsoft have spent enormous amounts of time and research into
application development. The fruit is Visual Studio 2005. With Visual Studio 2005 applications can be
developed much more easily and efficiently.
Throughout the book we will use Visual Studio 2005 and .NET 2.0 to illustrate SOA development and
design. This book will not only focus on the technical aspects of SOA, but also place strong emphasis on the
delicate issues of establishing SOA at the enterprise level and the pitfalls associated. The principles described in
this book are the foundations on which enterprise systems are constructed. Through the book we will learn to
develop application systems that are flexible, agile, and secure at lower costs
This book will provide developers, architects and IT managers with a roadmap for success in establishing
SOA at the enterprise level. It is a concrete guide, blueprint and contains best practices for SOA architecture
using the .NET Framework.

20
The Complete Reference To Professional SOA with Visual Studio 2005

Part 1 Core Concepts


Chapter 1: Introduction to
Service Oriented Architecture
For years, large enterprises have struggled with the challenge of integrating disparate and distributed applications
across their organizations and their partners. Despite continuous technological advancements, most IT
departments have chosen to address this problem through custom development. Custom development may work
for smaller organizations that have relatively few endpoints that need to be integrated. However this approach
does not meet the needs of larger organizations whose IT environments are much more complex. Studies have
shown that as the number of endpoints increases the cost and complexity of managing the environment increases
exponentially.
The focus today is on business solutions integration; this focus comes at no surprise when we consider the
amount of time and money spent in buying and building information technology such as Enterprise Resource
Planning (ERP) and Customer Relationship Management (CRM) Applications. It is no wonder companies are
looking for ways to preserve and extend these investments. Unfortunately, most of these applications were
implemented in Silo Architectures without considering the effects and dependencies that the applications would
have on other technologies and the business itself. This lack of vision in integration only leads to poor return on
investment for technology purchases and has always prevented businesses from functioning efficiently and cost
effectively.
In order to remain competitive in today’s fast-moving marketplace, organizations must be able to observe
and understand what is happening in all areas of their business, and must be able to quickly adapt as business
conditions change or as threats and opportunities arise. Due to this exact reason business leaders are constantly
searching for ways to reduce costs, improve efficiency, and grow the bottom line. All of which must be
accomplished with fewer resources.
Achieving superior efficiency and agility of real-time business can be a daunting task for any organization,
along with the technical challenges of integrating applications and automating routine tasks. Achieving
architectural efficiency and agility requires a fundamental change in how IT has traditionally supported business
requirements.
Today, organizations are turning to Service Oriented Architecture (SOA) in order to improve their business
agility. SOA is emerging as the premier design principle for new business applications as it gradually replaces
monolithic architecture. SOA promises to continue to stimulate conversations within the IT industry and
maintain the increase in interest to the businesses that are seeking to lower costs, increase return on investment
(ROI), leverage existing assets, and integrate systems.
SOA’s potential is real, and its importance cannot be understated. When appropriately implemented, it can
help an organization improve ROI by allowing incremental development through reuse of existing business
components. Architecturally it helps to improve the clarity of the application topology.
In this chapter we will be covering SOA core concepts and what it really means for a business to implement
SOA. We will also be examining the reason for the rise in popularity of SOA, as well as looking at real world
case studies.

21
The Complete Reference To Professional SOA with Visual Studio 2005

What is Service Oriented Architecture?


Service Oriented Architecture is a concept for providing agility and flexibility to an architecture. SOA focuses
on building distributed systems through the use of components that have a common Web service interface.
Though SOA does not only refer to software, it is a concept and at its most abstract, service orientation views
everything from the mainframe application to the printer to the shipping dock clerk to the overnight delivery
company as a service provider. These Service providers expose their functions through the means of a public
interface. The interface is more like an advertisement describing what the function is and how to access it. The
service-oriented architecture then maps these capabilities and interfaces so they can be orchestrated into
processes. The service model itself is in segments. The new formed process is a service itself, this service can
then form a higher level service by exposing new and aggregated functionality. This is referred to as entity
aggregation.
Fundamental to the service model is the separation between the interface and the actual implementation. The
consumer of a service need only (and should only) understand the interface which describes the service. The
advantage of the separation is that the implementation is allowed to evolve over time, without breaking the
clients that consume these service interfaces. Through the separation, the same interface can offer many different
implementations. The key benefits of service orientation derive from this abstraction from implementation.
To developers and architects SOA provides a means to construct application quickly and efficiently through
component reuse. By adopting service orientation applications are no longer tightly coupled. This can
dramatically reduce the complexity involved when supporting or updating the application with new
requirements. It also allows applications to be gracefully integrated to other architectures overtime.
To the IT manager, SOA allows different enterprise systems to be integrated quickly and efficiently. As
service orientation provides a model for aggregation from which improved information and business processes
can be derived. Service orientation will also allow existing redundant legacy systems to be recycled to provide
value back into the business again.
To the Chief Information Officer, SOA can protect IT investment from changes. In the past as the business
evolved and new requirement is requested by the business stakeholders. Often to cater to these new requirements
entire systems are tossed out and new system constructed. SOA helps to protect applications from this process.
Through separation between implementation and interface, the actual implementation of the business
applications is protected behind an interface. The separation between implementation and interface allows
systems to continue to evolve and be updated without any impact on the rest of the architecture.
To the business analyst, SOA provides the means to map IT investment with the requirement of the
business. This allows business analysts to better understand the cost and trade offs associated with the business.
By moving to SOA, a constellation of services and devices can be efficiently integrated, to more effectively
meet the needs of the business and its challenges. Enterprise Application development and consolidation through
the use of SOA is truly a revolution for the industry not seen since the days of disconnected systems.

Explaining Service Oriented Architecture Using Metropolis


Pat Helland, Micrsoft Architect, in his 2004 essay, likened service-oriented architecture to a bustling metropolis.
In this analogy Metropolis consisting of many disparate systems whether local or external to the organization. If
we were to think of each of these disparate systems as an individual city and SOA as the railroad network that
connects these cities, we can easily picture these disparate systems working together. Metropolis is an analogy in
an attempt to both explain what is happening in Information Technology today and to show us what we can
expect to happen in the future.
In the past, using the monolithic approach, businesses were developed to target each individual city, their
supply chain to distribution was only developed to target that one specific city. In this environment, expansion
into another city was difficult, because a brand new distribution chain has to be setup and the intricacies of
operating in this city has to be managed. However, using a Service Oriented Architecture, a new distribution

22
The Complete Reference To Professional SOA with Visual Studio 2005

chain is not required. We can use another distribution chain that already exists, is established and operating in
that city to help distribute our own product. Using the SOA approach we can easily branch out our business
whenever required. This level of flexibility is transcendent and will allow the business to expand very rapidly.

Cities as Software Vendors


In the world of Metropolis we symbolize cities as software vendors. Inside the cities are independent buildings
with little or no connection between each other. These software vendors gradually evolved as new applications
were built and extended. Each application stood apart and independent of its neighbors within the same vendor.
Each Software vendor had its own culture, style and process of doing things.
Economic pressures changed our cities. Economic opportunity is what really drove cities to modernize, to
share services, and to devise creative means to achieve efficiencies. Economic pressures are changing our
software vendors too. As new applications are developed and old applications extended. Developers must
consider how to integrate them to the shared infrastructure and to maximize reusability.

Factories and Buildings as Applications


We can think of factories and buildings as applications, and cities as the software vendors that have built them.
Both the appetites of the local market and the sophistication of the manufacturing process limited the goods
manufactured by these factories. Factories were very rigid, and produced its own components to be assembled
into the products that it manufactures. In this rigid style products were created. The process was inefficient and
the product was expensive and often of poor quality.
Most of the applications today are just like the buildings and factories we described earlier. They’re clumsy
and, poorly thought out. As a result they were very rigid and do not accept the work of other applications as
input. However, with the introduction of railroad, the manufacturing processes were quickly and profoundly
altered. Transportation allowed the production of higher quality, more sophisticated goods. It is only by
decoupling of the product that change and efficiency can be achieved. By leveraging the work of other
specialized factories to manufacture components required in production, changes in the production could be
achieved more easily. The use of specialize component manufacturers also helped to improve the quality of the
product. The demand for manufacturing by others provided the economic stimulus that gave reason for many
factories to co-exist today.
Just as in software development today, organizations are realizing the importance of third party software
vendors. This new understanding in component based development, allowed enterprise applications to utilize and
customize existing components instead of reinventing them. These third party components are tested and can be
easily integrated into the organization’s own application. Utilizing the components improved the quality and
features of the application whilst reducing considerable development and testing time.

Transportation as Communication
In Metropolis, transportation refers to the movement of people and goods. This movement stimulated
tremendous change. People were able to travel to different cities and visit places they were unable to previously.
Retail began to expand rapidly as people were able to visit other cities and gather goods from stores in these
cities. Through the movement in goods people arrived at a new expectation that things would work together.
However, prior to the transportation development, one manufacturer’s goods were incompatible with another
manufacturer’s.
In the application world, we can see that in the past applications were structured in a rigid monolithic
architecture. With the arrival of SOA through the use of business services, enterprise architectural applications
are becoming more interoperable and are starting to communicate with each other.

23
The Complete Reference To Professional SOA with Visual Studio 2005

Manufactured Goods as Standardization


Standardization between manufacturer processes was vital. By establishing tight controls over the specification
and production, it allowed companies that produced parts with a high degree of precision to thrive, while those
with less consistent processes failed. As a result standardization had expanded across manufacturers, and de
facto standards had emerged for common parts. These were sizes for nuts and bolts and cylinders. Now, with the
expectation that products produced by one factory would be interchangeable and interoperable with similar and
complementary components produced by another. Manufacturers could pick and chose their preferred
components depending on the price and quality of the component.
Today majority of our data structures are still mostly non-standardized. All application models information
in its own way, and a lot of time is spent adjusting the data structure to integrate different applications. However,
we’re beginning to see the interoperable policy put in place through the use of XML and Web Services
specifications. Through these rudimentary rules, application data structure will be able to support improved
interchangeability of data.

Manufactured Components as Virtual Enterprises


In the Metropolis world manufacturers begin to understand the benefits of manufacturing specialized
components and utilizing components from other manufacturers. With their new understanding manufacturers
begin to strive for higher quality and more sophisticated components. Competition amongst the component
manufacturers drove efficiencies and quality improvements. All of which is only made possible through detailed
specifications for the manufactured components.
Manufacturing became driven by information, reputation, and trust. Companies partnered to change the
process of bringing goods to the market.
Just as manufacturers created components, today software vendors created Assemblies of their business process and
functionality. Rather than building the entire application in house, many organizations today outsource small portions
of work to other software vendors through the use of well-documented specifications. When these software
components are finally completed they’re integrated. The use of specialized software vendors reduced cost as well as
improved quality of the end product. However the engineering, marketing, and ownership of the product may still
remain in house.

Urban Infrastructure as IT Infrastructure Evolution


In Metropolis through gradual urban evolution common services such as water, sewer, gas, electricity and
telephony were gradually built and managed by the government to achieve efficiencies and to make the city a
more livable place. However hooking up these services to every building in the city proved to be extremely
difficult, as no prior thought for these services were ever given when the buildings in Metropolis were first
constructed.
Similarly, each Software Vendor, for a long period of time, had built their own applications with numerous
standards. These applications easily became stagnant as they were extended over and over, standards were lost as
a result, exceptions become harder to route, parse, to take action. Processing data between these dispersed
applications became inhibiting and difficult.
We now understand that application architecture needs to be well-designed and well thought out in order for
application services to function smoothly. Since different visions lead to different infrastructure goals care must
be taken to balance infrastructure investments. If a city actively pursues growth but fails to anticipate the impact
on transportation for example, congestion and inefficiency will result. In the coming section we will be covering
planning and resource allocation as well as balancing the needs of the business against resource and schedule.

24
The Complete Reference To Professional SOA with Visual Studio 2005

Enterprise Architecture
An Enterprise Architecture consists of the various structures and processes. Enterprise Architecture is a
representation of all that exists within an organization. The structures themselves can be either the IT based or
the business process based. A good representation of the enterprise architecture thus will represent the business
model as it is today as well as incorporate the business strategies for the future. The Enterprise Architecture
representation can thus be used as a communication bridge between business stakeholders and the IT system
implementer. For our purposes Enterprise Architecture will mean the design, planning and execution of the
overall IT systems of an enterprise.
To see how Enterprise Architecture affects the role and circumstances of IT in business, we should first
examine the concept of “architecture” itself. Architecture is the process of designing buildings so that they serve
their intended purpose. If an architect designs a house, it is meant to be lived in if he or she designs an office, it
is meant to be used for work. Similarly, Enterprise Architecture is the process of designing IT systems in order to
develop an IT structure that realizes the needs of the business. Enterprise Architecture refers to the ability to
enable the business goals of the organization. We must keep in mind when designing architecture not to over
step the boundary of over indulgence and detract from the need of the organization. To do so is dangerous and
costly for the organization that seeks to optimize its processes.

Architectural Tradeoff Triangle


Enterprise Solutions frequently fail, are completed late, or exceed the planned budget. Ambiguous requirements
can contribute to, or be the cause of, each of these problems. The scope specifies what the solution will and will
not do. To effectively define and manage the scope the needs of an organization have to be identified. These are:

* Identifying project constraints

* Managing tradeoffs
* Establishing change control
* Monitoring project progress

In the process of identifying and managing trade-offs in an Enterprise Architecture, the features of a solution
are not necessarily reduced, but identifying the tradeoffs might result in a reduction of features. Managing trade-
offs provides a structured way to balance all parts of the project while realizing that we cannot attain all of our
goals at the same time.
In Enterprise Solutions, there is a clear relationship between such project variables as resources, schedule,
and features of the project. The relationship between these variables is illustrated in Figure 1-1.

Figure 1-1 illustrates the trade off triangle

25
The Complete Reference To Professional SOA with Visual Studio 2005

As illustrated by the trade-off triangle, any change to any one of the components implies that a
corresponding change might need to be made to the other components. The key to developing a solution that
meets the customer requirements is to determine and maintain the correct balance between resources,
development date, and features.
Often, project teams are reluctant to reduce the number of features in the solution. The trade-off triangle
helps to explain the constraints and present the options for trade-offs.

Architectural Tradeoff Matrix


The Architectural trade-off matrix Figure 1-2 is a tool can be used when making trade-off decisions. These
decisions are made early in the solution. The trade-off matrix helps identify the solution’s features that are
considered essential, the features that are not essential but that would be good to include, and the features that
can be eliminated or added to the next version to accommodate the other two variables.

Figure 1-2 illustrates the trade-off matrix used to make trade off decisions

* In a decision making process:

* If we are given fixed resources and fixed schedules then we must adjust the features that need to be delivered.
* If we are given fixed resources and fixed features to develop then we must adjust the schedule.
* If we are given fixed features and fixed schedules then we must adjust the resources.

Successfully managing and adjusting the trade off variables in a project will ensure the success of your SOA
project.

Understanding Business Benefits of SOA


As businesses continue to expand, demands for IT infrastructure also increases. In today’s business mergers and
acquisitions can form quickly. As a result there is an even greater demand for new applications that can facilitate
the new business model. This results in the formation of many distributed application islands that quickly
become isolated and interoperable. In this complex environment, application silos are formed. These are
applications that are tightly coupled and self contained and difficult to interoperate with other applications.
As companies merge, systems and information are duplicated, these systems are for example payroll and
HR. This has not been a concern in the past, since each business operated independent of each other and each
system managed its own individual business. In recent years, due to new demands, the industry has adopted a
new trend. This trend involves the movement towards automating business processes between similar systems.

26
The Complete Reference To Professional SOA with Visual Studio 2005

This process involves integrating and aggregating entities/information that are present in different systems. As a
result instead of making phone calls to HR and Payroll and Benefits to update an employee’s address details in
each of these different systems. By automating the process through entity aggregation we can update the
information with just one phone call. We can also construct a self-service portal that will update personal
information seamlessly across different systems.
Businesses also benefit by connecting systems and providing integrated solutions to customers. By
implementing SOA, the total cost of ownership (TCO) is dramatically reduced. While the integrated solution
with applications such as enterprise resource planning (ERP) and customer relationship management (CRM)
systems can also provide more value to the end users. The integration of all of these systems can also benefit the
business by reducing the overall total cost of ownership for support individual business functionalities.
Through the use of SOA, organizations are able to make better design, management, and investment
decisions. This level of visibility into application usage allows companies to identify, and, more importantly, to
make changes to existing business processes to take advantage of opportunities for continuous improvement.
This ability to nimbly change and modify business processes as business needs require will give companies a
distinct advantage over their less agile competitors.
Today integrating disparate systems components is about effectively orchestrating the interaction between
enterprise resources: whether it’s machine to machine, person to person, or a combination of both, in a manner
that is conducive to the way business is conducted. Through SOA, IT can easily morph into a valuable asset by
introducing a comprehensive process-centric integration approach that delivers that and more. Thus, allowing IT
systems to make the transition from an inhibitor to an enabler of business.
Organizations can expect to experience the following benefits when deploying enterprise systems built using
SOA.

Better Visibility into Operations and Performance


A Process-centric approach to business integration can unify lines of business using a common infrastructure that
will provide vital information to different types of users at all levels of the enterprise. For instance, a Chief
Financial Officer will be able to access real-time or near-real-time information from financial reporting, order
management, customer relationship management, and business intelligence systems to provide a single view of
the customer relationship as well as profitability. A little further down the corporate hierarchy, a vice president
of logistics can access real-time information about fulfillment and logistics operations, with which he or she can
make decisions to streamline the supply chain.

More Efficient Operations


By gaining visibility across the enterprise, business leaders can take better inventory of their operating strengths
and weaknesses, and consequently identify ways of correcting problems and optimizing efficiency. The adoption
of a process centric integration approach that supports full process lifecycle management will allow IT
organizations to provide the business with the information and tools they require to make these informed
decisions. Business leaders must be able to constantly monitor how business activities (that is to say, processing
orders and serving customers) are executed with respect to their competition and corporate goals.

Better Business Agility


As the marketplace evolves, business leaders need to make changes such as introducing new products, new sales
channels, and new value chains. In order to be able to do so in a consistent, efficient, cost-effective way they rely
on their IT organizations to respond quickly with necessary changes to the underlying system infrastructure. IT
organizations that have built a modular flexible architecture are in a position to adequately support the needs of
change management.

27
The Complete Reference To Professional SOA with Visual Studio 2005

What is a Web Service?


In 2000, the World Wide Web Consortium (W3C) accepted a submission for the Simple Object Access protocol
(SOAP). This XML-based messaging format established a transmission framework for inter-application or inter-
service communication via HTTP. As a vendor neutral technology, SOAP provided an attractive alternative to
traditional proprietary protocols, such as CORBA and DCOM.
In the following year, W3C has accepted and published the WSDL specification. WSDL is implemented
through XML and acts as the interface in the interface/implementation model of Web service. It is essentially a
language that is used to describe the interface of the Web service. The interface is further supplemented by the
Universal Description, Discovery and Integration (UDDI) specification. The UDDI much like a yellow page
directory allows users to perform dynamic searches on the directory for a specific service implementation.
Since then, XML Web services has received industry wide acceptance. The support for XML Web services
has furthered the popularity and importance of a service oriented design principle.

Loose Coupling
In the 1980s and earlier application architecture was developed in a fairly simple format. The architecture
usually consisted of UI Components at the very top, followed by business logic in the middle and data access
components at the very bottom. This was often referred to as the Silo Architecture also known as the Vertical
Architecture Figure 1-3.
From 1980s towards 1990s the software architecture moved towards a more horizontal architecture. This is
where we are starting to see a separation of logic in layers. Layers in software refers to a way of organizing the
code to provide logical abstraction and separation. Typical layers include Presentation, Business and Data layers.
Layers are primarily used to gain the benefits of logical organization and grouping of similar functionalities. This
in turn supports code reuse. This is referred to as the Layer Architecture or Horizontal Architecture
What we’re now seeing through service oriented architecture is a steady move from layers to tiers. Tiers is about
the physical separation between code. In other words tiers is about where layers run. We’re now increasingly
seeing that systems are no longer running off from one Server but from several different servers located in
different countries. A database on Human Resource might be located in the United States whilst another database
on payroll might be located in Australia. This form of architecture is referred to distributed architecture. This is
what SOA is helping us to evolve towards.

Figure 1-3 shows the evolution of software architecture from vertical to horizontal to today’s distributed architecture.

Loose Coupling refers to the act of joining things together. In application development loose coupling refers to
the degree which software components depend upon each other.
Traditionally applications are “tightly coupled”, where each application may or may not connect with others
in a distributed environment through a combination of proprietary interfaces and network protocols. These

28
The Complete Reference To Professional SOA with Visual Studio 2005

applications were often designed within system boundary of an enterprise or even within a specific business unit
of the enterprise. As a result the applications have no concept of interoperating with other units of work outside
of its system boundary.
A solution to the tightly coupled application is an attempt to develop applications in a loosely coupled
manner. Loose coupling is seen as a way to reduce the overall complexity and dependencies of applications on
each other. Loose coupling can be achieved through using XML Web service by using the
interface/implementation approach. Loose coupling leads towards the same goal as service orientation, which is
providing an architecture that is more agile, allowing faster response to change and improvement for overall
system agility. In addition, system maintenance is much easier.
Loose coupling is especially important in the enterprise architecture. As the relationships between business
partners change rapidly. Vendor alliances are constantly made, altered or broken, and business processes
between trading partners are constantly changing to adapt the new market requirements. Due to the severe and
fast paced competition in business today it is essential that the underlying IT infrastructure could reflect the
flexibility and independence of the business efficiently.
Overall scalability is also a lot easier in a loosely coupled architecture. Key software components can be
easily taken and deployed onto multiple servers to improve reliability and availability.
Today, in Service Oriented Architecture, loose coupling is mostly implemented through the use of Web
services. Once a piece of software has been exposed as a web service, it is relatively simple to access through the
use of WSDL and UDDI.

Services
The concept of services has been around for quite a while. Service by definition refers to any component that
provides functionality and is an independent building block that can be integrated together collectively to
represent an application.
Unlike traditional components each service represents a unique discrete unit of work in their environment.
This means that each service is responsible for its specified role in its own domain. In the business sense the
service focuses on a specific business function or possibly a group of functions.
This model allows for the creation of isolated units of business functionality that can be easily reused
throughout development. The loosely bound services help to provide freedom within the architecture.
In the past service orientation was created using services though increasingly today SOA refers to the use of
XML Web services. This is because of the vendor neutral implementation and its interface/implementation
provide as an ideal model for SOA.

XML Web Services


The most widely accepted and successful type of service is the XML Web Service. The popularity generated in
XML Web Service is largely due to its ability to be able to communicate via Internet Protocol (HTTP) and send
and receive data in XML format. Using XML Web services allows a common framework for which different
application environment and platform are able to communicate with each other. Using the common
communication framework HTTP and XML, XML Web Services can communicate with any application that
uses XML over HTTP. Today, with the introduction of Asynchronous JavaScript And XML (AJAX) we can also
call and access XML Web Services from our browsers.

XML and XML Schema


XML provides the ability to represent data that is independent of application, protocol, operating system and
programming language. XML was quickly adopted industry wide as a technology neutral communication
framework. It was exactly what everyone had been waiting for. Due to the competitiveness in IT, each vendor

29
The Complete Reference To Professional SOA with Visual Studio 2005

pushed for its own technology and proprietary standards. The industry was quickly filled with varying
technologies that weren’t able to work together. With the adoption of XML, industry vendors now had a means
to communicate and work together.
The structure of XML documents is based on rules that are also known as grammar. These rules are
specified by a XML Schema document. A schema document contains the definitions of elements, attributes, and
data types. Any XML that is created can be validated against an XML Schema. Though XML can be used
independently of XML Schema, in Web Services the XML that we work with will be governed by an XML
schema called Web Services Description Language (WSDL).

XPath
XPath is used to refer to parts of an XML document. XPath gets its name from its use of a path notation as in
URLs for navigating through the hierarchical structure of an XML document. In addition to its use for
addressing, XPath is also designed so that it has a natural subset that can be used for matching and testing
whether or not a node matches a pattern. XPath models an XML document as a tree of nodes. There are different
types of nodes, including element nodes, attribute nodes and text nodes. XPath defines a way to compute a
string-value for each type of node. Some types of nodes also have names.

SOAP
The SOAP specification provides standards for the format of a SOAP message and how SOAP should be used
over HTTP. SOAP was created to help provide the means to transport XML documents from one computer to
another. SOAP can be used with a number of standard transport protocols. HTTP is one of the most common and
preferred mode of transport protocols used because of its ability to work with firewalls.
SOAP itself is built using XML. SOAP is used to call exposed methods of the Web service. It describes how
the data being passed to those methods is structured, and what the data is. If the client passes the Web service a
correctly formatted SOAP document as a web service request, effectively calling a method, the Web service will
return another SOAP document containing a response. A SOAP message consists of three parts an Envelope,
Header and a Body.

Figure 1-4 shows the SOAP structure.

The SOAP Envelope is used to store the XML message. This envelope is acts as a container to hold XML
information contained as shown in Figure 1-4. The envelope consists of two main parts: the SOAP Header and
the SOAP Body of the message. SOAP header can be used as a container for additional information about the
SOAP message for example security credentials or message authentication information like message hash
values. This information is then used to manage and or to help secure the package.
SOAP body contains the XML message content. The body can contain information about the Web service
method that we’re about to execute in a request. In a request the body would contain information about the
method’s parameters, the datatypes they expect as well as the value that will be passed into those parameters. In

30
The Complete Reference To Professional SOA with Visual Studio 2005

a response the body of the SOAP message would contain the information on the datatype that is being return as
well as the actual returned value.

WSDL
Web Services provide an interface of its functionalities through the use of Web Services Description Language
(WSDL). WSDL is an XML document, designed according to standards specified by the W3C, that describes
exactly how a specific web service works. However, the WSDL document is much more than a mere instruction
manual on how to use the web service that it describes. Web services development software can process the
WSDL document and generate the SOAP messages automatically.
Because of the capabilities of WSDL, web services are known as self describing software elements. This is a
very powerful concept. Not only can web services interoperate universally through SOAP, they can also be
described universally using WSDL. A software developer in Sydney, Australia can easily create software calls to
a Web Service in Canada just by reading and processing WSDL document.

Figure 1-5 Depicts a web service conceptually. A Web service using WSDL can expose its methods so that they can be
accessed from any application whether its windows application, web application or mobile application. Thus Web services
contributes to the power of the interoperable nature of distributed systems.

UDDI
Universal Discovery, Description and Integration (UDDI) directory as the general standard used as a registry of
web services that are available for use in a particular network. Think of the UDDI as a sort of yellow pages for
web services. If we wanted to find a web service for our enterprise application, we can look in the UDDI. The
UDDI would tell us where to find that service, and it would take us to the WSDL document so we could examine
the web service and make sure it was the one we wanted.
A UDDI registry is a central concept as one shifts to a model that assumes a distributed, loosely coupled set
of web services. The services that we want to consume could be anywhere at any given moment, and in fact the
same function may be performed by a different service depending on changing criteria, such as availability or
price. The magic of web services is that they are located at addresses to which any computer can connect. The
web service’s URL is the basis for its universality and network transparency. Universal transparency comes from
the ability to use a logical name in the consuming application that the UDDI can then translate into the
appropriate URL. If we wanted to use a service that provided credit card number validation, we can invoke a
logical name called “VisaAuth” and allow the UDDI to resolve the name into a URL. Thus, if the location of a

31
The Complete Reference To Professional SOA with Visual Studio 2005

service changes, the application can still resolve to the new URL location of the required Web Service. This is
key to achieving the agility that web services technology promises.

Service Oriented Architecture with Web Service


There is a distinct difference between an application that uses XML Web Services and an application based on
Service Oriented Architecture.
In SOA the concept of encapsulating application logic centers within services that interact via a common
generic communications protocol. The services themselves are discrete units of work that can be reused. SOA
today with XML Web service allow services to be developed and through XML and vendor neutral standards
these service can be easily integrated together.
We also need to keep in mind that the requirement for using Web Service for Service Oriented Architecture
is slightly different to Web Service in general. SOA Web Service focuses on independence and on its ability to
operate without relying on the state of other services. This independence is what makes SOA so flexible.
However it is easy to make the mistake of using one Web Service A to call another Web Service B and thus
becoming dependent on the operation of Service B. In essence we have created tightly coupled components
using XML Web service. This should be avoided when implementing SOA, as the creation of spaghetti
architecture often become imminent. In essence one Web Service should encapsulate and is responsible for its
own domain.

Web Service and SOA Technology Soup


Web Service is one of the key enabler for Service Oriented Architecture. Its key benefit is that it is not dependent
on any one particular technology. When SOA is created using Web service (WS) it allows a mixture of
technologies from various vendors. WS consequently allows the creation of enterprise level applications through
the use of a soup of different vendor technologies. Due to its independent and self-describing nature, Web
Service offers what other technologies could not and that is Enterprise Application Integration (EAI) with ease.
Today in Service Oriented Architecture, Web Service is the most widely accepted and successful type of
service technology used. The reason for its popularity is its ability to communicate via HTTP using the universal
XML document as it sends and receives data. Web Service uses a XML based messaging format which was
derived from Simple Object Access Protocol (SOAP). Because SOAP is an open standard adopted by the W3C it
allows anyone and everyone to easily communicate with Web Services. WS using SOAP establishes a
transmission framework for inter-service communication via HTTP as a vendor neutral technology.
Web Service Definition Language (WSDL) specification implemented using XML. This standard provides a
language for describing the interface of Web Services. WSDL is then extended by Universal Description,
Discovery and Integration (UDDI) specification that provides a standard means for the dynamic discovery of
service descriptions.
Together, XML, SOAP, WSDL, UDDI provides Web Services with the means to consolidate technologies
that otherwise would be extremely difficult to interoperate. These standards together provided a method to re-use
existing legacy systems, which only required a simple Web Service layer on top to communicate with its core
API. The Web Service layer can then be easily integrated into other Enterprise Systems with ease.
So Enterprise systems can use and re-use existing technology investments with ease. This is ultimately what
we try to accomplish. In an enterprise system it is difficult and costly to build the system using homogenous
technologies. We must make do with whatever is available to reduce the cost and time of development as much
as possible. This is where Service Oriented Architecture falls into place. Using Service based technology we can
dramatically reduce development and integration. At the same time allowing the different technologies within
the architectural technology soup to simmer and be blended together, to create a flavorsome System.

32
The Complete Reference To Professional SOA with Visual Studio 2005

Service Oriented Enterprise Architecture


If we could make changes to our enterprise architecture at will, to cater for the changing needs in our business
without enormous expenditures of time and money. Suddenly enormous value is created; processes are
continually updated and optimized as our enterprise architecture keeps pace with frequent changes in business
strategies.
The architectural flexibility brought by SOA is a huge driving force behind the shift to service oriented
architecture. Because each element within a SOA is an independent unit, that can be easily moved around,
replaced, and modified without impacting on the rest of the architecture. The reason for this level of flexibility is
due to each service existing in a loosely coupled fashion, the services can be assembled and reassembled in
different forms for different purposes as circumstances warrant. The ability to create processes and composite
applications from these services, combined with re-usability and standards based interoperability, creates what is
the ultimate achievement in enterprise architecture-that is architectural-wide flexibility.

Adopting the Legacy Enterprise Architecture Beast


Lets take some time to examine how service oriented architecture using Web service can enable enterprise
architecture to become more flexible. The image below shows a large organization that has a traditional
architectural plan.

Figure 1-6 shows a simplified system diagram of their current architecture.

The organization is separated regionally; each region is in charge of its own architecture. Figure 1-6 identifies
one particular regional branch. We can see that the architecture contains SAP and SAS running on IBM
mainframes, Analysis Services that use Microsoft Windows, and accounting systems that use Java on Sun. On
top of that there is an external payment gateway component that’s being accessed. The head office also accesses
the regional systems periodically to monitor certain operations.
Figure 1-6 depicts a very simplified version of an organization’s architecture diagram. As we can see there
are disparate systems running on many different technologies. As a result there are independent teams located in
each country to maintain and implement changes to the individual systems and subsystems. Because each branch
operated independently from others branches over time the architecture has evolved through years of patchwork.

33
The Complete Reference To Professional SOA with Visual Studio 2005

Each regional branch office has evolved to an untamed beast that was very rigid, non interoperable and difficult
to maintain. Frequently changes to one aspect of the system alone required redevelopment to many other
components. The regional CIO explained that due to the local nature of their business they were operating in
each region it was difficult to centralize globally.
The head office is not happy because development and maintenance is becoming costly regionally. Since
there are many regional offices around the world, the cost involved was quickly adding up. In an attempt to
reduce costs, and keep all systems changes in check, common functionalities consolidated and centralized. The
head office in Nuremberg Germany, had requested that all non-regional specific systems be moved and
consolidated to the head office. The move will allowed at the very least reduction on maintenance and also
supported system reuse at a global level.
Even though consolidating the architecture is an ambitious and necessary business change, the nightmare
began. The new architecture was nearly impossible to implement because at the regional level system conflicts
were rife. Applications were tightly coupled with one another and quite frankly the IT managers and developers
were not really sure where to start. The patched architecture that had evolved over the years had become the
legacy architecture beast.
In order to switch to the new architecture a lot of the existing system had to be re-written in order for the
systems to be more interoperable. Temporary systems were built, patch tools were created and temporary
solution put in place to attempt to bridge the gap between the existing architecture and the new architecture. A
change for better soon became an exhausting, expensive and time-consuming exercise.
The scenario outlined is not dissimilar to many enterprise architectures that currently exist in the industry
today. Diagrammatically Figure 1-6 is a standard architecture that can easily become overwhelming depending
on the business’s need and change in focus. Today business directions change constantly as new partnerships are
forged and broken. To have IT architectures that inhibit the merge of another partner or the quick separation
between the business and an ex-partner for security reasons can be detrimental to the business.
Often legacy architectures like the one outlined are inherited, and constantly patched. As a result it easily
becomes unmanageable, filled with traps and system conflicts. Changing one dimension of the architecture to
meet the change in business needs will result to change in almost every other dimension of the architecture.
Tight coupling in system architecture always results in a nightmare in maintenance and overall does not support
the change in business needs.

Enterprise Architecture using SOA


The diagram shown in Figure 1-7 shows the same organization with a service-oriented architecture approach.

34
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 1-7 shows the regional office using a Service Oriented Architecture configuration.

Now, each component application in the architecture is exposed as a web service. Since each component is
now a web service it is now loosely coupled. As a result, it can be accessed from anywhere on the network
regardless of the makeup of the requesting computer.
There are several distinct advantages using service-oriented architecture over the traditional architecture. By
moving to web services the entire architecture experiences flexibility that was not there previously. Services can
now be called by different systems regardless of the technologies that they use complexities of deployment of
these services are reduced, and change management is also simplified. If the custom internal financial system
required changes and as long as the interface of the service is unchanged, the consumer of that service would not
be impacted or even know about it in any way.
Now that we have the service-oriented architecture established, we shall examine how it can help with the
head office’s request to centralize non-regional specific systems at a global level. With an architecture that’s now
built using SOA, the systems that are not region specific can be easily aggregated and re-deployed at the head
office. Reintegration from the regional system to head office is fairly simple and straightforward. By moving to
service-oriented architecture the organization has also experienced more flexibility at the global level.

35
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 1-8 shows a separated architecture through the use of SOA the organization’s architecture becomes much more agile
and flexible.

So how will Service Oriented Architecture affect the Enterprise Architecture? Actually, not much. We can
start by building Web service on top of existing system components. Then we can build or integrate these Web
services into applications. The applications that use these Web services will immediately benefit from the agile
properties of SOA. The flexibility is in the ability of Web services to work with each other regardless of the
underlying technology or platform.
If an organization is adopting SOA for the first time, and is converting its existing infrastructure to SOA.
The initial shift to SOA will be difficult and time consuming. However, in the long run, the amount of time and
money required making those changes would be a fraction of what would be required under the traditional
model. Not only will the entire architecture become more flexible, there will be considerably less maintenance,
and the cost savings on Enterprise Application Integration for new developed component will be enormous.
The main benefit of the SOA is its ability to deliver agility to the enterprise. The entire enterprise will
become simple, fast, and inexpensive to implement changes at the enterprise level. Service Oriented Architecture
really gives the system the ability to keep up with business changes, and not the other way around. Business
decisions are made based on business requirements instead of IT limitations.
The adoption of service-orientation is both liberating for the business manager and the IT manager. The
business manager can act according to strategic directive without the classic constraints of IT. While the IT
manager can deliver results in an efficient and cost-effective manner.

So is Service Oriented Architecture a Breakthrough?


The concept of SOA is not new. Distributed computing was first available as early as 1980s. However, it was
mainly confined to the academic world until around mid 1990s. As the need for distributed application
development became more recognized within the industry.
In the world of the distributed computing the separation between client and server was first noted when
Sybase introduced the concept of functions that were executed within the database and that did not need to be
shipped with the client application. The concept later became known as stored procedures. Followed by Novell’s
NetWare Loadable Modules (NLM), which were programs that ran on the server. A few years of combining
concepts from distributed computing platforms such as Distributed Computing Environment (DCE) with the
newly emerging paradigm of object-oriented development, CORBA (common object request broker
Architecture) was created. Instead of providing servers, which expose large numbers of remotely accessible
functions, the functionality was now broken down into uniquely identifiable, remotely accessible objects that
were able to manage their own state. Different objects could communicate with each other by means of an
Object Request Broker (ORB). CORBA’s vision of distributed business objects never fully materialized because
of its fine-grained model often proved to be too complex to be suitable for the purposes of enterprise-level
software reuse. Driven by the high demand for more sophisticated platforms for Internet applications Sun
Microsystems introduced Enterprise java Beans (EJB) in 1997. Similar to CORBA, EJB also relies on a
distributed object model. However, the EJB model is based on a controlled and therefore usually limited number
of servers that host the actual objects.
In addition to core-application remoting technologies, such as RPC, CORBA, DCOM, and EJB, the 1990s
saw the emergence of a large number of additional distributed computing middleware solutions, addressing
distributed transaction management these are X/Open-based CORBA Object Transaction Service, the Java
Transaction Service, and the Microsoft Transaction Server.
Now there are many types of infrastructures for the development of individual systems. However the sheer
number of different development distributed computing concepts, standards, and products also caused an issue.

36
The Complete Reference To Professional SOA with Visual Studio 2005

Interoperability was difficult between these infrastructures. As a result it proved almost impossible to impose
enterprise-wide standards in large enterprise systems.
Its no wonder Service Oriented Architecture had almost disappeared briefly. However it was quickly
revived as soon as Web Service became widely adopted within the industry. Through the use of XML essentially
is the lowest common denominator that the industry could agree on. Unlike previous technologies XML is not
bound to a particular vendor or technology standard and thus provided a common communication framework.
Because of its flexibility it is frequently used as a way of transferring data across largely different platforms. As
we move through the book we will see that XML Web Services is a great provider for Service Oriented
Architecture. However, it is important to keep in mind that Web Services are not the only valid technology
platform for an SOA. As SOA concept is not dependent on any one single technology platform.

Case Studies
Service-oriented architecture is catching on. According to a recent Industry Development Center (IDC) report,
SOA spending has reached $8.6 billion in 2006 a 138% increase from 2005 at $3.6 billion. By 2010, IDC
estimates companies will spend upwards of $33 billion on SOA services.

Which Industry Is Best For SOA


SOA can be used in any industry. As all businesses need to have the flexibility to change or create business
processes dynamically. The need to quickly and seamlessly take elements of processes that weren't built to work
together and make them work together is ever more important in today’s fast paced industry.
Achieving this level of flexibility used to be time-consuming, labor-intensive and expensive. It involved
building your own custom integration systems. However, with SOA and the recent developments in Internet
standards now we can easily make software applications talk to each other even if they're written in different
languages or for different types of hardware.

The Drive for SOA


The fact is SOA can be used in any industry. The underlying benefits of SOA are not just IT systems but in fact
improvement on agility of business processes itself.
It is a simple matter of taking stock of what we have in an architecture, take it apart, and put it back together
in new ways. Or alternatively we can view it from a different light as breaking up a business process into
reusable components, even if those components span across applications. We can then draw upon new and old
components from the business or business partners and mix the old and new to create a new business process.
Within a service-oriented architecture, applications, information and other IT assets are viewed as services
or “building blocks.” Each of these services can be mixed and matched to create new, flexible business
processes.
Let us examine some of the common scenarios that are plaguing different industries today.

1. Problem: Healthcare industry must address accelerating costs, slow response times and inconsistent quality of
patient records.
Solution: Use SOA approach to integrate payer systems, provider systems with hospitals record system.

2. Problem: The electronics industry is converging from traditional manufacturing to configure to order market.

Solution: Build SOA that facilitates mass production with easy to configure last-minute customization ability.

37
The Complete Reference To Professional SOA with Visual Studio 2005

3. Problem: The banking industry must deal with information silos, redundancy and underutilization of data,
while constantly under pressure to grow.

Solution: To address this we can utilize a SOA to add flexibility to existing infrastructures. Once systems are service-
oriented we can reduce information silos, redundancy and improve on the growth of the architecture to provide new
products and services.

4. Problem: Retailers are confronted with exponentially increasing data such as radio frequency identification
(RFID) that's not leveraged effectively.

Solution: To resolve this we can use SOA to deliver near real-time information to optimize the supply chain.

5. Problem: Telecom companies cope with island like infrastructures. As the industry spurs ahead many legacy
systems and heterogeneous environments are left costly to interoperate. These systems provide services such as
billing, account activation and other specialized customer care services.

Solution: Use SOA to aggregate and consolidate all services to deliver Enterprise Resource Planning (ERP)
application.

The case studies below demonstrates some of the use for SOA to resolve current issues. However the key to
SOA is not only in what it offers to resolve architectural issues but also its ability to support application reuse.
This aspect of SOA is not a result that can be seen immediately but over time service-oriented architectures has a
significant reduction on development costs through component reuse.

Case Study: Starwood Hotels Uses SOA to Improve Guest Services and
Cut Costs
Starwood Hotels, realized five years ago that service-oriented architecture was in its future, says Israel Del Rio,
Starwood's senior vice president of technology solutions. The international hotel chain, which includes such
brands such as the St. Regis Hotels, Sheraton, Westin's and the W Hotels, saw that its costly, clunky old
mainframe system was limiting its ability to accommodate rapidly growing distribution channels like the
Internet. "It was too difficult to add capabilities to our CRM system, do proper searching to find properties
basically many of the things a modern IT environment needs," says Del Rio.
Starwood's current systems were also having difficult handling the rapidly increasing traffic on its Web
sites, what hospitality professionals refer to as the "look-to-book" ratio. "In the old days of the Internet, the look-
to-book ratio was 50 to 1. Now it's 300 to 1. So we needed an IT environment that could handle all those
requests." To keep the legacy mainframe system would have required a multi-million-dollar investment in
upgrades and technical support. "It was very costly, and we didn't want to be held down," he says.
So Starwood began the long process of moving its systems to an open SOA framework. "It was the best way
to let us map our technology with our various brands," says Del Rio. Instead of having each of Starwood's hotel
chains build their own applications, SOA allows the brands to share the same programs and features—but they
can be customized specifically for each hotel's look and feel. Sheraton's search function, for example, may
deliver information differently than, say, the W Hotels', even though it's the same program. "That way we benefit
from using all the same tools that can be called up by different applications and interfaces," says Del Rio.
Because SOA is built on an open framework (meaning it can be called up by different operating systems), it
also creates greater flexibility for the company to create new tools. Starwood has put in place an application that
tracks guest requests and complaints, for example. "We created a workflow around that to ensure that our guests'
needs are satisfied," says Del Rio. The company also created a program that stores and tracks frequent guests'
preferences. "These are functions that didn't exist in the mainframe at all," he says. Software from Burlington,

38
The Complete Reference To Professional SOA with Visual Studio 2005

Mass.-based SOA vendor Systinet helps Starwood track all the SOA tools it has created. "That way everyone
across our brands knows which applications are available," he says.
But it didn't happen overnight. After five years, the company is finally ready to officially dismantle its
mainframe—an endeavor Del Rio expects will save the company as much as $20 million per year in
maintenance costs. He expects Starwood to be entirely up and running on SOA by 2007. "It's a very complex
initiative with a lot of moving parts," says Del Rio, "but if applied to the right business problem, it produces
good results."

Case Study: Harley-Davidson


Here's how loose coupling had a direct impact on Harley-Davidson's business: When the weather warms up,
people begin to wander into Harley's showrooms with visions of the wind whipping through their hair on an
open roadway. "We have specific marketing programs geared towards that customer base," Haney explained.
"Those programs are targeted to get those people that are dreaming about motorcycles to actually purchase one.
We want to put together a good financial package to entice and incite people to get into the sport."
Enter Harley's credit and loan origination process. Until recently, however, the financial services
applications were tightly coupled, and thus weren't very flexible, Haney explained. Making a change in one
program meant having to go in and change countless other applications as well. "The way our systems are very
tightly coupled, being very rigid from how they are architected, if we made one change to one of those systems
that supports one of those processes, we basically have to touch all of the systems."
The answer? Break it all up. "We actually busted apart all of those systems, and put the SOA with
WebSphere in the middle of all that," Haney said. "We loosely coupled these things. Our goal is to be able to
change any one of those systems. If we see key indicators in the industry, we want to very quickly put different
marketing programs in place, and not have to go and touch and test every single system."
If ever there was a case of IT agility supporting new business opportunities, this is it. "We can bring
applications to the forefront as services, and arrange them differently," Haney said. "But more importantly, we
can change an application, and do it quickly. We can be a lot more responsive to the business, which helps us
sell motorcycles — the business we're in."

Case Study: IBM towards SOA


Recently, IBM has been quite eager to deliver SOA to the enterprise world, with countless product and service
announcements. Howie Miller, IBM’s vice president for enterprise architecture told us that Big Blue currently
has 77 shareable and reusable services in production ranging from authentication to order fulfillment as part of
its service-oriented architecture. The most notable outcome of IBM’s internal SOA efforts is the fact that Big
Blue was able to reduce its inventory of 16,000 applications in 1998 to 4,000 applications today.
The secret sauce to streamlining down to a quarter of its applications was governance, Miller explained.
“The governance model helped us achieve that nice statistic. It’s how we plan to go from more big integrated
spaghetti code applications to more component-based Web services. That same governance model will be part of
what gets us moving forward to the SOA-based approach.” Decisions about new technology investments are
vetted through an Enterprise Architecture Council and Investment Review Board run by the CIO (Miller's boss).
IBM’s CIO's office is leading the SOA charge internally at IBM, but doesn’t have a central bucket of money
or huge staff to plan and build SOA. Instead, Miller, said, the office — which has 10 architects — plays a role in
influencing Big Blue’s annual internal $4 billion annual technology spend. "About 28 percent of our investment
of our total IT spend is what we call 'transformational investment,' or new development.” That's where SOA
comes in.
“What we do, through roadmaps, standards, and target architecture is try to influence the behavior of the
way that our development teams are doing transformation initiatives to spend their money.”

39
The Complete Reference To Professional SOA with Visual Studio 2005

Web identity service: This is an authentication and authorization service for end-users accessing IBM
applications. "When an employee or partner signs into a Web site, they have a single user ID and password for
sign-on," Miller explained. "It used to be, every time I used a different application in IBM, I had a different user
ID and password. Now, all these applications call the Web service to validate the user ID and password. This
common Web service is callable from any application.”
Factory in a box: IBM's semiconductor group built a set of services called "semiconductor factory in a box.,"
Miller said. "It has enabled us to do is invest, acquire, or divest, or outsource manufacturing plant very quickly.
If we divest a manufacturing plant, we had to rip out all the connections to various systems. Or, to acquire a new
company that comes with a manufacturing plant, we had to integrate them into our systems. The process used to
take several weeks — now it's two hours.”
Customer order and tracking system: IBM's customer order analysis and tracking system (COATS) "was a big
spaghetti-code application, all integrated into one big app," said Miller. The huge application was being
overwhelmed by order volumes, which "were causing problems with performance with the application." MIller's
staff decomposed the entire application into 13 separate components. "We found that the logjam in the
application was only in a couple of the pieces of the app. We pulled out that application code for those two
pieces and wrapped them as Web services. It was a way to rewrite a legacy application in pieces, without having
to go do the full 13 big chunks of functional capability."
Miller says SOA enablement didn't happen overnight, even for IBM. "A lot of time, when we talk to folks about
this stuff, they say, ‘oh my gosh, I could never do an enterprise architecture of that size, with the complexity of
my company. It must have taken you years.’ The answer is yes, it did take years," he related. "But you can start
in a corner of the business, business unit or functional area, and work it out from there."

Case Study: Microsoft SOA (Milton Keynes General Hospital)


ROI: 61%
Payback: 1.65 years
Located in Buckinghamshire, England, Milton Keynes General Hospital is a 460-bed District General Hospital
serving the needs of the people of Milton Keynes and surrounding areas for the past 20 years. Milton Keynes is
part of England’s National Health Service (NHS), which provides healthcare for all citizens in England,
Scotland, Wales, and Northern Ireland.

All NHS hospitals are subject to the recently-initiated NHS National Program for IT. This is a broad integration
initiative across the entire NHS hospital system that will be phased in over a number of stages. Its objective is for
each hospital to replace the functionalities of its various local disparate IT systems into a single, cost effective
service that can deliver far greater patient data transmission. Integration requirements under this mandate include
the following:

* Paperless or near-paperless transmission of patient files such as documents, care records, and X-rays.
* Viewability of any document from any location.

* Capacity for data entry from any point.

* Elimination of redundant data entry.

NHS is pursuing this degree of integration because it believes that for any given patient, the hospital’s ability to
provide rapid and effective prognosis and treatment is directly impacted by the ability of the organization to

40
The Complete Reference To Professional SOA with Visual Studio 2005

transmit critical patient data among the various departments and hospitals within the NHS system. In the face of
the NHS integration mandate, Milton Keynes determined its existing patient admission system was no longer
capable of delivering the requirements of a modern day healthcare system. The patient admission system, which
is 22 years old, annually processes 60,000 in-patient admissions and 100,000 out-patient admissions, resulting in
approximately 1.5 million transactions per year. Upon receipt of the integration mandate, this enterprise was
comprised of 28 systems spread across more than 80 servers. There were numerous heterogeneous systems in
this configuration. Additionally, there were numerous disparate connections of both a point-to-point and many-
to-many nature within the system. As a result, the system was far from rationalized, and required much work in
order to comply with the NHS integration mandate.
Early in 2005, the hospital began looking for an integration solution that could be used to rationalize its
complex patient admission system. They chose to use Web service and along with Microsoft BizTalk Server
2004 for integration.
Subsequent to selecting Microsoft BizTalk Server 2004 as the integration platform for Milton Keynes, the
hospital formed a deployment team. Milton Keynes staff members, including a project manager, a systems
architect, and an integration and systems developer were joined by four consultants from WCI, a British
Microsoft partner. Over a 4-month period, the team completed the necessary development testing and
deployment for the Microsoft BizTalk solution. The process concluded with a 3-week long installation of
Microsoft BizTalk Server 2004 for interfacing with the existing 28 local departmental systems that are currently
tied together with point-to-point interfaces.
During the deployment, Milton Keynes made extensive use of Web service and along with Biztalk’s pre-
built messaging tools designed for healthcare institutions, which helped to accommodate local compliance
requirements such as those requested by the Health Insurance Portability and Accountability Act (HIPPA).
By converting to a service oriented architecture and integrating the existing patient admission system with
Microsoft BizTalk Server 2004, Milton Keynes is now able to accelerate its IT integration, reduce costs, and
improve patient service. Some of the key benefits are:

* Rapid system rationalization. The hospital can now transform the current state of the patient admission system
from one characterized by numerous point-to-point and many-to-many connections to one resembling a hub-
and-spoke structure.

* Reduced programming costs. Because Milton Keynes will make vigorous use of its service oriented
architecture, the hospital can complete its integration tasks with far less programming costs than had been
budgeted.
* SOA adoption. Service oriented architecture adaptation is viewed as an enabler of new practices, including
solution reuse, business-to-business integration, and business activity monitoring. These are viewed as critical
going forward, as other systems within Milton Keynes are rationalized and integrated as required under NHS
National Program for IT.
* Improved patient service. By improving data flows, the hospital will be able to provide better scheduling,
diagnostic services, and treatments to its patients.

Case Study: GfK Market Research


GfK is one of the largest market research organizations in the world. Like many large organization it is facing
the global challenge to improve organization revenue and reduce operational costs. In order to be a truly global
market research organization GfK must have offices locally in every country to collect local regional sales
information from retailers on weekly basis. For the last twenty years GfK has left local operations to its own. As
a result through the years each regional operation center has evolved with its own suite of systems to process and
collate data. In a bid to reduce operation costs the head quarter in Germany has requested that all operations to be

41
The Complete Reference To Professional SOA with Visual Studio 2005

consolidated to a single point. This will essentially remove local processing at a regional level and all work will
be now done at head quarters.
The regional operations center has several departments, each department focused on a particular industry
within the local retail market. Because of the difference in the type of data that is submitted from the retailers
and difference in requirement for each department. The department themselves also has their own IT operation
teams which also developed different sub systems. Some of these systems relied on SAS others relied on Access
and MS SQL Server with different Business Intelligence (BI) tools such as Cognos, Microsoft Data Analyzer,
Analysis Services and even MS Excel tied onto the front of each of the systems. It was a difficult task sorting out
what can really be consolidated at the regional level which in turn can be consolidated to the central system in
Germany.
Each regional operation center differed from each other. Industry information and categories within each
region also differed greatly from each other. This posed an issue when trying to consolidate data and applications
at a regional level. On top of these problems with changes the operation teams were having a hard time
maintaining operation of the current systems. For quite awhile it seemed that the entire consolidation process to
Germany was on the verge of failure.
To ensure stability and operation at the regional office the head office has requested all regional offices
construct Web services on top of each application. With this request regional offices quickly established scalable
Web services on top each of its proprietary systems. The head quarter operation team was then able to duplicate
all applications to the head quarter level and using a hub and spoke approach with Enterprise Service Bus (ESB)
integrated the local proprietary systems into its centralized process.

Case Study: PureProfile


PureProfile an online market research organization offers virtual credits for all those who participate in their
online market research service. PureProfile wishes to rapidly expand their business internationally. To achieve
this PureProfile needs to establish a base from which services can be rapidly launched to meet the requirements
of its clients. With limited resources this was almost impossible to achieve.
PureProfile CIO, Basil Karam, decided to expose their Intellectual Property through the use of XML Web
service. This was quickly achieved as Web services was already being implemented internally to help ease
integration within the organization. PureProfile quickly gained supported from a number of other market
research organizations wishing to support broaden their own capabilities by implement PureProfile’s IP into their
own market research system. As such PureProfile without requiring to expand additional resources into their
operations team has increased their Market base exponentially.

Case Study: Amazing People


Amazing People is one of the leading training organizations in Australia. Amazing people was rated by Business
Review Weekly (BRW) as one of the fastest growing organizations in Australia. Trainers facilitated training
within Amazing People on premises and outside on client sites.
However growth in this manner is always limited. Amazing People wanted to be able to access the global
market without the need to fly facilitators from country to country. To achieve this Amazing People opened their
business processes and course materials to partners through the use of XML Web service.
By incorporating the course contents of Amazing People other training organizations are able to provide
Amazing People courses for them. Whilst by incorporating Amazing People XML Web services into their own
architecture, they have constant access to updated course work and lectures. The partners then pay a royalty for
the materials that they use.
Using XML Web service Amazing People was able to quickly expand their business globally without the
need to increase in business costs.

42
The Complete Reference To Professional SOA with Visual Studio 2005

Case Study: Sunshine Sugar


Sunshine Sugar in NSW has been struggling with their legacy systems. These systems had provided reliable
services to the organizations for many years. However, Sunshine sugar is bringing in a new suite of software
system which will help the business to cater for today’s business requirement. The CIO does not wish to lose the
old systems as they can still provide valuable service to the organization.
The integration process between the legacy and the new system proved to be difficult. Proprietary interfaces
were required to be implemented to interface with the new system this proved to be costly and not an optimal
solution.
The CIO decided to implement generic interfaces using XML interoperate requests and response operations
between applications. XML Web service was used as a method for exposing legacy capabilities whilst the newer
application then consumed these capabilities. This was a great success at a fraction of the original costs.

Case Study: Intellifield


One of the difficulties today for component manufacturer is trying to provide information in an industry neutral
standard. This is especially the case in the oil rigging industry. Intellifield an independent supplier of products
and systems to oil rigs needed to provide an out of the box plug and play component that can be used on the field
with any application available today.
To do this Intellifield used XML and XML Web services. Intellifield sensors are used in the oil drilling industry
to transfer drilling sensor data from offshore oil rig back onshore. In order to facilitate a plug and play scenario
XML Web services were used to provide the service. Data is gathered in different proprietary formats before
converting the information to a XML based document for transfer, which client applications can then readily
access to acquire the information.

Summary
Web services uses SOAP messages a specific type of XML message format determined by the W3C standards to
communicate over a number of protocols such as HTTP.
Due to the open nature of web services, it is possible for many web service consumers to access the same
service regardless of operating system or programming language. As long as a consumer invokes the web service
using a SOAP request in standardized format. It does not care for the language the service is written in nor does
it care for the platform the Web Service is currently on.
Each web service can contain a Web Service Description Language (WSDL) document that provides the
potential consumer of the service with an explanation of how the service works and how to access it. The WSDL
describes how to create a SOAP request that will invoke that specific web service. If a developer wanted to
create a Web Service consumer application, they simply need to retrieve this XML document, which will
provide all the information the developer require to develop the new application to invoke the relevant functions
within that Web Service. Due to the self-describing nature of the web service it allowed developers to quickly
develop distributed applications without requiring understanding of the underlying technology or functionality of
the service.
Web Service also uses Universal Discovery, Description, and Integration (UDDI), which is a listing of web
services available within a particular network. The UDDI functions like a “yellow pages” of web services.
Potential web service consumers can search for the web services that are available for use through the UDDI
directory.
Web Services play a key role in the promotion of Service Oriented Architecture. As it is technology neutral
and uses an open-communication framework such as XML. This quality allows distributed applications to be

43
The Complete Reference To Professional SOA with Visual Studio 2005

developed, integrated and maintained with ease and most importantly it supports the reuse of existing technology
investments.

44
The Complete Reference To Professional SOA with Visual Studio 2005

Chapter 2 Implementing
Service Oriented Architecture
In order to successfully adopt SOA into enterprise architecture we must first determine its goals or destinations.
To do this we need a clear idea of where we are and a vague idea of where we want to be. In this chapter we will
continue to discuss SOA theories and concepts and most importantly we will focus on the implementation side of
SOA.

SOA Architectural Roadmap


Any great journey starts with a goal or destination, and the decision to implement SOA is no different. We may
start with only a vague idea of where we want to be, or how we could get to our destination. To be successful,
we must assess our strengths and weaknesses, establish clear a direction, to choose a route, and then consistently
reevaluate our progress as we follow it. To put it simply, we must create our own unique roadmap for the
journey.
On the journey to create service oriented enterprise architecture, we are likely to encounter many obstacles
and will need to cope with the frequently changing requirements of the organization. It is therefore important for
our architecture and roadmap to be designed to cope with the complexity and dynamics of the enterprise
environment. In this section we will learn to develop our own architectural roadmap to help us reach our goals

What is a SOA Roadmap and Why Do You Need One?


Service-Oriented Architecture refers to an IT strategy. This strategy incorporates an organization’s plan for its
architecture. To achieve this, organization need to breakdown its applications into discrete reusable components
and build standards based services such as XML Web services as the interface for these components. This will
allow the architecture to quickly reflect changes and be combined with reusable components to meet the
business’s needs.
Creating a SOA roadmap will require a delicate balance between the long-term goals and the shorter-term
needs of the business. This balance can be maintained by instituting a set of organizational, financial,
operational, design, and delivery practices from the outset of your SOA initiative. But rather than making
enterprise wide changes, it is important to deploy culture-changing disciplines in an incremental and iterative
fashion to allow for an organizational learning curve. In essence, an SOA roadmap provides an iterative and
incremental way to capture your organization’s unique plan as you progress.
The SOA roadmap should clearly outline the boundaries of your SOA initiative and establish a transparent
and flexible timeline for achieving SOA goals. These goals should be broken down into manageable phases,
which can then be realized in an iterative and incremental manner.

How to build a SOA Roadmap


In any organization one key area for any form of budget or financial allocation is through the justification of
return on investment. As such we must provide an adequate roadmap to rationalize the reasoning behind a switch
or to build in a SOA manner.

45
The Complete Reference To Professional SOA with Visual Studio 2005

There are four phases to developing your SOA roadmap: SOA Planning, SOA Maturity Assessment, SOA
Future Vision, and SOA Roadmap Definition. Once the roadmap had been defined and development begins, at
the end of each iterative development phase there must be an Iterative Quality Assurance stage to ensure that the
overall development is in sync and on track with the SOA roadmap defined.

Figure 2-1. Six-domain model for a SOA roadmap (Copyright BEA Systems - Used with permission)

In order to plan for a successful SOA implementation. Our SOA roadmap should encompass six domains Figure
2-1. These domains, while distinct, are interrelated and interdependent. Implementation on each domain is
fundamental to the success of an enterprise-wide SOA. Our SOA roadmap should clearly outline the boundaries
of our SOA initiative and establish a transparent timeline for achieving our SOA goals. Each domain’s area of
responsibility is illustrated in the table below.

Table 2-1. Responsibilities of domains.

Domain Focus
Business Strategy and Process SOA-enabled Business strategies
Business process architecture is derived
Architecture Reference Architectures
Manageability/Availability
Scalability
Security
Building Blocks Public Services, Logic Centric Services, Data Centric Services,
Transitional Services, and Basic Services
Projects and Applications Existing Applications
Key “in-flight” Projects
Infrastructure Construction Plans
Organization & Governance Organization Design
Funding
Skill sets
Roles and Responsibilities

46
The Complete Reference To Professional SOA with Visual Studio 2005

Standards
Operational Processes and Tools
Change Management
Cost & Benefits Constructions costs
Business & IT Benefits
Key Measures

SOA planning

Defining a plan for the implementation of SOA is vital to the success of the overall architecture. In any
organization alteration or new development needs to be justified. After all there is no point in moving to SOA
without a strategy. The return on investment in the exercise must also be justified in the long run. Planning also
allows constant monitoring of the progress as well as successful evaluation of the architecture.
During this phase, your SOA initiatives are organized and defined. Stakeholders are brought into the process
through communications and briefings and mutually agreed upon priorities and parameters are set. Because this
phase involves employees across your organization, clear and ample communication is critical. During this phase
you will:

* Define the scope of SOA.

* Establish boundaries and alignments with other IT initiatives.


* Appropriately showcase the business justification for SOA.
* Show alignment of existing and future business initiatives.

It is important to define your SOA strategy in terms of long-term business goals, but its equally important to
meet short-term business goals. A business cannot possibly cease to function simply because of the change to
service orientation.

SOA maturity assessment


To develop a successful roadmap you must treat your SOA roadmap as a “living document” that continually
captures experiences and lessons learned. As your SOA roadmap matures, your SOA initiative reaches higher
levels of sophistication in a controlled manner. The creation of an SOA roadmap begins with an assessment of
your organization’s current capabilities and disciplines applicable to SOA.
During the SOA maturity assessment phase, you will establish a metric for where you are today. Here you
will define what services and capabilities you currently have that can serve as a starting point for SOA, as well as
identify projects that may serve as foundation projects. Through a series of interviews and questionnaires, your
teams should examine the various domain analyzing, base lining, and validating the “as-is” current situation for
each.
Use Domain Model to structure your examination of the following:

* Business Strategy and Process: Top-down view of business strategies and processes.

* Architecture: Review of current architectures, policies, and standards.


* Cost and Benefits: Overview of existing cost structures and benefits cases.
* Building Blocks: Analysis of existing services, processes, tools, and technologies.

47
The Complete Reference To Professional SOA with Visual Studio 2005

* Projects and Applications: Review of existing systems, and in-flight and planned projects.
* Organization and Governance: Analysis of existing governance structures and policies.

SOA future vision


In this phase, teams use workshops to determine and define the desired “should-be” state and ensure cross-
organizational buy-in.

* Business Strategy and Process: Correlation of SOA future vision with business strategies and processes.
* Architecture: Guiding principles, requirements, policies, standards, and reference architecture.
* Cost and Benefits: Metrics and measurement requirements.

* Building Blocks: Shared services infrastructure requirements and standardized tools.


* Projects and Applications: SOA mapping to projects and applications.

* Organization and Governance: Governance and compliance structures and policies.

SOA roadmap definition


This phase is where the SOA roadmap is initially defined. A complete gap analysis should be performed for your
corporation’s SOA goals and appropriate timelines, based on the information gathered in the previous three
phases. Near-term events will be more detailed, while later events will be more fluid—so that they may
incorporate lessons learned as you move forward.

* Business Strategy and Process: Opportunity alignment by business value.


* Architecture: Near-, medium-, and long-term reference architecture roadmap.

* Cost and Benefits: Roadmap of future metrics, cost structures, and benefits cases.

* Building Blocks: Prioritization of shared services strategy and standardized processes.


* Projects and Applications: Project and application impact.

* Organization and Governance: Proposed governance structures and policies.

Iterative Quality Assurance


By learning and adapting process at each milestone, and by being both iterative and incremental, your roadmap
will remain relevant throughout the SOA initiative. To ensure your SOA roadmap’s quality, communicate and
validate it with all stakeholders, soliciting feedback from all quarters at each iterative level.

SOA Governance
Governance in SOA is particularly vital in its ability to assess and ensure flexibility of the enterprise
architecture. The definition of the word governance implies the action or manner of governing. Further, IT
governance is a decision and accountability framework to encourage desirable behavior in IT. Participants of the
governance body lay down policies around different categories of decisions that need to be made. That body also
decides upon the people in the enterprise who are empowered to make those decisions; that is, it carries out role
identification. The members of the governance council also identify subject matter experts who are expected to
provide input to firm up the decisions and also identify the group of people who may be held accountable for

48
The Complete Reference To Professional SOA with Visual Studio 2005

exercising their responsibilities (based on their roles). An effective IT governance council must address three
questions:

1. What decisions must be made to ensure effective management and use of IT?

2. Who should make these decisions?

3. How will these decisions be made and monitored?

Establishing successful governance will align software governance and business governance. SOA
governance is really an extension of IT governance that focuses on managing service and the related service
level abstractions.
The SOA governance policies and processes should establish a governing body within the enterprise that has
representation from each service domain and the different business units and from subject matter experts who
can understand key technological components of the solution. This governing body should define the policies
and processes for identifying, implementing, deploying and versioning services.
SOA governance policies and processes should identify mandatory and optional training that members of
the SOA team and the larger project teams should complete to effectively implement the SOA roadmap.

Enterprise Service Enabling Architectures


Service Types
An important aspect of any software architecture is to be able to break down the overall structure of a software
system into smaller components. These components can then be used as flexible building blocks.
Being able to classify service types is a precondition for effective designs to SOA. Here we will learn to
describe and differentiate the different types of services.

Basic services
These are silo like services, which access data and contain certain amount of data operations and also some basic
business logic. These services are predominantly simple services that could easily be used and reused. Basic
services that provide both data and business logic can be referred to as agile and reusable as services. For
example, a social security number validation service will access the database to find the name that the social
security number belongs to. At the same time there is some simple logic to validate the social security number
before a call is placed to the database. In this regard this service both contains basic data access and some basic
business logic.

Data-Centric Services
A data-centric service handles the storage and retrieval of data, these services also handles transaction
management. These data-centric services often retrieve data from a database; as such it acts similar to that of the
data layer. These are important part of any enterprise application development and often provide as a solution to
data ownership. It allows access to data from different data vendors. The user of the service does not care for the
vendor of the service or what kind of query language the service uses to query the database. All that the
consumer of the service need is the interface. This improves the flexibility, transparency and allows more
efficient reuse of the service.

49
The Complete Reference To Professional SOA with Visual Studio 2005

Logic-Centric Services
These are services, which contain complex business rules or business logics. In the past these functionalities in
application development are deeply nested within the application. It was difficult to reuse these encapsulated
logics as it was too tightly coupled with the application. Through the use of Logic-Centric Services complex
logic can be exposed and easily reused by any application that requires it. The Logic-Centric Service may be
sitting on a proprietary system, which does not usually interoperate with applications requesting the service.
However through the use of Web service we can expose the service and allow other users to request for its
service.
A good example of Logic-Centric Service is a bank that’s providing home loan. The home loan formula is
extremely sensitive and should not be known by its competitors, however the bank wishes to provide the home
loan service to its partners. With every request personal account details and income information are sent to the
service. The service then takes these values and calculates against the imbedded business rules to work out an
estimated loan. This amount is then returned to the requesting client. There is minimal data processing and the
service is purely business logic.
With the Logic-Centric Service exposed, the bank can easily provide the loan estimate service to its partners
whilst keeping its business logic secure and central within the bank. Because of the nature of Web service’s
interoperability, it allows this particular functionality to be integrated with internal applications as well as
utilized by external applications from its partners.

Transitional Services
These are services that are generally placed on top of an existing legacy system to allow access from external
applications. Traditionally components are not always interoperable with each other as a result it was difficult to
work with one another. These could be components that provided any level of services. They can be data centric,
logic centric components or components that provided network access. Transitional services provide access to
these components by placing a transitional layer between these legacy components and that of the outside world.
This allowed for reuse.
Transitional services provide a huge amount of flexibility, to applications and components that had already
been developed. They allow existing systems to be more robust and agile.

Public Services
These are services that were exposed to the public in the sense that they’re outside the domain of business logic.
In SOA these services are used to provide cross-enterprise integration. These can be services that are offered by
a company to its partners and customers. An example of Public Services in use would be Amazon. Amazon
provides public services to allow its partners to build applications that utilize these services to retrieve
information about books that are currently available on Amazon.
Public Services are versatile they provide a gateway for the outside world to access functionalities within a
business domain. This allows the business to sell and promote its product in this case Amazon is allowing its
partners to build applications that access Amazon’s database. Allowing them to integrate Amazon into part of
their applications. Public Services really is the face of SOA and one of the most popular and used service types.

SOA Web Service Transforming Logical Layers to Physical Tiers


In this chapter, we have already discussed different service types. Now we will look at the overall structure of
service types in the enterprise landscape.
Firstly, let’s clarify the difference between Layers and Tiers in application. Layers, refers to a way of
organizing the code to provide logical abstraction and separation. Typical layers include Presentation, Business

50
The Complete Reference To Professional SOA with Visual Studio 2005

and Data. Layers, refers to the logical organization of code. Layers are primarily used to gain the benefits of
logical organization and grouping of similar functionalities. In application development logical layers offer
reuse, easier maintenance and shorter development cycles. Proper layering of software reduces the cost to
develop and maintain an application.
Tiers however, are only about where the code runs. Specifically, tiers are places where layers are deployed
and where layers run. In other words, tiers are the physical deployment of layers. Tiers refer to boundaries these
are either process or network based. A one-tier model has all of its layers running from a single memory or
processor space on the same machine. A two-tier model has two separately working memory spaces with tiers in
each of the working space. The number of boundaries for an n-tier model with can be calculated as having n-1
boundaries.
Traditionally, software that were developed were isolated and thus and layering provided all the abstraction
required for code reuse in this silo architecture. However as application development had evolved to become
more distributed, layering is no longer an adequate way to provide abstraction at the enterprise level. This is
especially the case when parts of the application are located in other regions of the world.
SOA layers should not be confused with the traditional software layers, and tiers. In SOA layers are
effectively traditional tiers. SOA layers provide a conceptual structure at the enterprise level.
Let’s have a look at SOA layers. Figure 2-2 shows different service types possible within a SOA, though
SOA is flexible enough to not to conform to this one particular model. Each service type essentially has the
ability to become a public service. Although for security reasons public services should always be documented
and noted.

Figure 2-2. Web service layers

Starting Your Enterprise SOA with Entity Aggregation


As businesses continued to expand over the years, mergers and acquisitions became more frequent. As a result,
today’s enterprises place increasing demand on IT systems to reflect the change in organizational restructuring
quickly. Whether it’s a new partnership that has just been forged where certain core business functionalities or
services needs to be provided. Or, when a partnership had ceased and access to information needs to be
restricted. The requirement to provide flexibility at this level gave rise to the emergence of a new trend in
software development and architecture.

51
The Complete Reference To Professional SOA with Visual Studio 2005

This trend, in its movement towards automating business processes between systems, promotes the value of
Service Oriented Architecture (SOA). Integrating and aggregating information (entities) that is present in
different systems and is essential in building solutions that will support this trend. For example, in many
businesses employees must make separate phone calls to HR, Payroll, and Benefits to have their addresses
updated in the different systems. Through SOA, however, multiple systems can become integrated and the
entities in the different systems aggregated. By automating these simple processes, employees can now make one
phone call or use a self-service portal and update their personal information seamlessly across numerous
systems.
Businesses can also reduce total cost of ownership (TCO) by connecting systems with Service Oriented
Architecture. Over time, the Enterprise IT group may plan to deliver services directly to end-users by integrating
multiple systems. This means that services, offered by applications such as enterprise resource planning (ERP)
and customer relationship management (CRM) systems, will be available to end-users, which results in an
overall reduction in the TCO for supporting the business functionalities. This is where Entity Aggregation plays
a large role.
An Entity Aggregation solution can be designed to not only act as a single point in accessing information
that exists in multiple systems, but it also provides a holistic view of an entity and the entity model. Additionally,
Entity Aggregation solutions address several design issues to ensure the success of Service Oriented
Architecture.
The underlying goal of Entity Aggregation service is to design an Entity Aggregation layer that acts as a
single point to access information that may exist in multiple systems.
There’re three main reasons why entity aggregation is important.

Single View of Entity


Information in today’s Enterprise IT is essentially disparate and spanned across a number of systems and maybe
supported by different vendors. A typical example of these disparate systems would be a Human Resource
Management System (HRMS) application, Payroll application, and Benefits application. Typically these systems
define their own individual Employee entities, which result in incoherency between systems. As a result, the
trend should be toward enforcing consistency between systems by maintaining a holistic view that is concerned
with the whole instead of just the parts. In the case of building an Employee Self-Service portal, a holistic view,
not the bits and pieces, of what constitutes an employee is necessary.

52
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 2-3 shows the aggregation of the employee table between the payroll system and the benefit system. Previously update
of information required users to log into both systems to update their personal information. However with entity aggregation
update to the aggregated view of the employee table will result in update of both Payroll System and the Benefit System.

Horizontal Partitions
There are cases where geographical constraints require a partitioning of entries across services. At certain times,
however, a solution may require a complete set of information to obtain a detailed picture across services. One
example of this of a distributed of stock trades as an entity that is partitioned across various geographical
locations.

Figure 2-4 shows the horizontal partitioning across services provided by a UK stock trader and a US stock trader. If a
company wished to request information on the performance logging into individual stock trader is troublesome especially if
you need to check regularly. By aggregating the available information to a higher level. We can perform queries and check
performance at the click of a button.

Cross Entities Query


Some cases require special handling of entities. In these cases, different services encapsulate related entities, and
the solution requires a complicated join between them.

53
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 2-5 depicts cross system join between an ordering system and an inventory system. In Service-Oriented Architecture it
is often necessary to query independent systems to bring a more simplified, holistic view to the consumer of the service.

Enterprise Application Integration (EAI)


As we enter an era of enterprise computing where components and systems providing different services are
easily distributed through out the world. A crucial focus is placed on technologies that will enable the integration
between these different systems.
Until recently, integration between disparate systems and unrelated technology were extremely frustrating
and painful. This is mostly caused by the competitiveness of the industry, as each vendor promoted and pushed
for its own technology creating a mayhem of similar technologies in the architectural landscape. However thanks
to the growth of XML an industry wide accepted communication framework and the use of XML web services, a
vendor neutral technology, enterprise wide integration can now be achieved relatively easily through the use of
SOA. SOA is slowly changing the way we think about applications and how they relate to each other and, in
doing so, is fundamentally changing the nature of enterprise application integration (EAI).
The first stage in application integration is to ensure that the components are interoperable. This means the
mapping of each application’s functionality and internal data model to some normalized format. Historically the
normalized format used was implicit to the integration broker that an organization purchased, meaning that any
interactions with the application would be limited to the capabilities of the broker, greatly restricting the
reusability of the interface. With SOAs, it’s now possible to express application functionality and data in a more
generalized, standards based way, through the use of Web services. Instead of plugging directly into a
proprietary integration broker, the application is ready to be invoked by any software that understands its service
interface. The SOA approach provides significantly greater reuse and flexibility.
Currently the industry supports two emerging standards Web Service Choreography Interface (WSCI) and
Business Process Execution Language for Web Services (BPEL4WS). They are both designed to reduce the
inherent complexity of connecting Web services together. Without them, an organization is left to build
proprietary business protocols that shortchange true Web services collaboration.
Recently, the terms orchestration and choreography have been employed to describe this collaboration:

* Orchestration: Refers to an executable business process that may interact with both internal and external Web
services. Orchestration describes how Web services can interact at the message level, including the business
logic and execution order of the interactions. These interactions may span applications and/or organizations,
and result in a long-lived, transactional process. With orchestration, the process is always controlled from the
perspective of one of the business parties. See Figure 2-6.

* Choreography: More collaborative in nature, where each party involved in the process describes the part they
play in the interaction. Choreography tracks the sequence of messages that may involve multiple parties and
multiple sources. It is associated with the public message exchanges that occur between multiple Web services.
See Figure 2-6.

54
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 2-6. Outlines the difference between Orchestration and Choreography

The difference between orchestration and choreography is that orchestration is a more detailed, execution-driven
mechanism, viewed from the perspective of routing a particular set of messages through a process, and
choreography is more abstract and descriptive, viewed from the perspective of the parties that exchange
messages to accomplish a particular process.

Web Service Choreography Interface (WSCI)


WSCI defines an extension to WSDL for Web services collaboration. WSCI is a choreography language that
describes the messages exchanged between Web services that participate in a collaborative exchange. A key
aspect of WSCI is that it describes only the observable behavior between Web services. It does not address the
definition of an executable business process. A single WSCI interface describes only one partner’s participation
in a message exchange. A WSCI choreography would include a set of WSCI interfaces, one for each partner in
the interaction. In WSCI, there is no single controlling process managing the interaction. WSCI can be viewed as
a layer on top of the existing Web services stack. Each action in WSCI represents a unit of work, which typically
would map to a specific WSDL operation. WSCI can be thought of as an extension to WSDL, describing how
the operations can be choreographed. In other words, WSDL describes the entry points for each service, while
WSCI would describe the interactions among these WSDL operations.
As Figure 2-7 illustrates, a WSCI choreography would include a set of WSCI interfaces, one for each
partner in the interaction. In WSCI, there is no single controlling process managing the interaction.

Figure 2-7. WSCI choreography.

55
The Complete Reference To Professional SOA with Visual Studio 2005

Business Process Execution Language for Web Services (BPEL4WS)


When coordinating the message exchange pattern involved in the execution of a business task, it is often
necessary to encapsulate the interaction between web services into a dedicated business process. This provides a
central source of business logic that determines the rules, conditions, and exceptions relating to the workflow
scenarios that can occur within a solution.
BPEL4WS specification has received the broadest industry support. It is complemented by WS-
Coordination and WS-Transaction standards to provide a framework for building sophisticated and fully
managed business workflows. BPEL4WS uses XML to describes its control logic required to coordinate Web
service in the workflow process. BPEL4WS operate much like an ESB in that it supports internal workflow
management and also supports transaction in its workflow.
BPEL4WS has its own WSDL which defines interfaces for all the services involved in its execution process.
Though the interfaces themselves do not specify specific binding information this is intentional so that it remains
implementation neutral.
The BPEL4WS specification supports basic activities for communicating with Web services. When a
message is received by a BPEL4WS process, the process will then invoke a series of other predefined external
Web services when the workflow is complete the process responds back to the requesting application see figure
2-8.

Figure 2-8. BPEL4WS work flow

In Figure 2-8, the messages all represent basic activities for connecting the services together. In BPEL4WS
we can predefine a number of models we can define sequential processing for workflow where services are
executed one after the other. Alternatively we can specify a parallel processing model for workflow where
messages are sent to several service at the same time for processing. A third model where conditional looping is
supported.

Coordination Services
WS-Coordination is closely associated with the WS-Transaction specification, which defines two distinct
coordinated types, both of which are relevant to enterprise integration environments. The first, atomic
transactions, enables the management of ACID like transactions. The service model for atomic transaction

56
The Complete Reference To Professional SOA with Visual Studio 2005

coordinators is the most common type of coordination service used in legacy integration architectures. The
second coordination type provides a model for long running transactions, and is represented as part of the
coordination service model.
Business service coordination is a typical characteristic of EAI solutions, which is why coordination
services for business activities are utilized exclusively for the management of business activities. Coordination
services are generally used in conjunction with logic-centric services as a means of handling success and failure
conditions related to the execution of the overall process activities.
The WS-Coordination specification provides an assembly of services with predefined interfaces that support
the management of a coordination context. Specifically, this collection of services provides separate operations
for the creation of a context, the registration for a context, and the selection of a protocol.

Distributed Event Driven Architecture and SOA


Service Oriented Architecture is slowly changing the IT world, as we know it today. A new emergence in
technology is the requirement to quickly respond to real-time changes and events in a timely manner. It is also
one of the most important requirements for an enterprise framework.
This requirement has given rise to Event Driven Architecture (EDA). EDA is an architecture that allows a
service-oriented framework to effectively respond to real-time stimuli and, therefore, send and receive
synchronous and asynchronous events across layers of an architectural stack without knowing the details of the
underlying event system.
Internet transactions, business-to-business systems, peer-to-peer processes, and real-time workflows are too
dynamic and too complex to be modeled by traditional sequential-processing methods. Therefore, the need for
more sophisticated asynchronous processing techniques is quickly becoming apparent. To address these
unpredictable environments, the current trend in systems architecture is service-oriented design and event-driven
programming.
A service-oriented architecture (SOA) presents a dynamic runtime environment, where loose couplings
between service providers and/or service consumers enable powerful and flexible component interactions.
Building a communication model to exploit this power and flexibility is a high priority for competitive software
development. An event-driven communication model is able to respond better to real-time changes and stimuli
than conventional request/reply mechanisms.
Service-oriented and event-driven architectures are natural fits for distributed systems since they share many
of the same characteristics, such as modularity, loose-couplings, and adaptability.
Unlike a request/reply system, where callers must explicitly request information, an event-driven
architecture (EDA) provides a mechanism for systems to respond dynamically as events occur. In an EDA,
events are published by event producers, and event consumers receive events as they happen.
Business systems benefit from the features of both an SOA and an EDA, since an EDA can trigger event
consumers as events happen and loosely coupled services can be quickly accessed and queried from those same
consumers.
For systems to be most responsive, they must be able to quickly determine the necessary actions when
events are triggered. To this end, events should be published and consumed across all boundaries of the SOA,
including the layers of the architectural stack and across physical tiers.
Distributed event driven architecture is supported through the use of Enterprise Service Bus (ESB). We will
examine ESB in more details in the coming section.

Enterprise Service Bus & Services


Successfully implementing an SOA requires applications and infrastructure that can support the SOA principles.
Each application will have a service interfaces to existing or new functions. The abstraction from
implementation allows its consumers to remain functional regardless of the changes to the underlying

57
The Complete Reference To Professional SOA with Visual Studio 2005

implementation. The service interfaces should be accessed using an infrastructure that can route and transport
service requests to the correct service provider. As organizations expose more and more functions as services, it
is vitally important that this infrastructure should support the management of SOA on an enterprise scale.
One of the key enablers in a SOA enabling architecture is the Enterprise Service Bus (ESB). Enterprise
Service Bus is used by large organizations to enforce standardization on Service Oriented Architecture. The role
of the service bus is to enable the basic interactions between different service components across a range of
varied platforms. It also provides a new way to build and deploy enterprise SOA. ESB is a concept that is
increasingly gaining the attention of architects and developers, as it provides an effective approach to solving
common problems such as service orchestration, application data synchronization, and business activity
monitoring.
Enterprise Service Bus helps to support the concepts of SOA implementation through decoupling of the
consumer’s view of a service from the actual implementation of the service, decoupling the technical aspects of
service interactions, and the Integrating and managing services within the enterprise.
Decoupling the consumer’s view of a service from the actual implementation greatly increases the flexibility
of the architecture. It allows the substitution of one service provider for another (for example, because another
provider offers the same services for lower cost or with higher standards) without the consumer being aware of
the change or without the need to alter the architecture to support the substitution.
In SOA, services are described as being loosely coupled. However, at implementation time, there is no way
to loosely couple a service or any other interaction between systems. The systems must have some common
understanding to conduct an interaction. Instead, to achieve the benefits of loose coupling, consideration should
be given to how to couple or decouple various aspects of service interactions, such as the platform and language
in which services are implemented, the communication protocols used to invoke services, the data formats used
to exchange input and output data between service consumers and providers.
Traditionally, Web service interactions between consumers and providers are relatively straight forward. It
generally involves a Web service consumer requesting an operation directly by sending a message to the Web
service provider. The provider then responds with a SOAP message to the consumer with the operation results.
This sort of interaction pattern is easily maintained in small to medium architecture. However as the number of
Web services increase so does the complexity involved and a pattern using simple point-to-point link is not
sufficient. In applications that require large amount of Web service calls with spaghetti type interactions
requiring multiple security and transactional supports is where ESB’s value can be realized.
The ESB helps to provide an abstraction between the service providers and service consumers Figure 2-9.
This abstraction aids the decoupling nature between service consumers and the service providers. Requirements
as routing control, logging and monitoring and over all interaction management can be implemented easily
through the use of ESB, in an environment that would otherwise require considerable modification to
applications to implement.

58
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 2-9. Architecture without Web service

The diagram above Figure 2-9 shows the implementation of an architecture without the use of Web service.
This results in complex bindings at each component endpoint. As the number of components increases, the
complexity of the application increases exponentially.

Figure 2-10. Architecture implementing Web service but not ESB

The diagram in Figure 2-10 shows the implementation of an architecture using Web service. This results in
simplified and interoperable bindings at each component endpoint. However, as the number of components
increases, the complexity of the application also increases due to the complexity of message interactions between
components.

Figure 2-11. Architecture using Web service and Enterprise Service Bus

The diagram in Figure 2-11 shows the implementation of an architecture using Web service as well as
enterprise service bus. This results in simplified and interoperable bindings at each component endpoint. The

59
The Complete Reference To Professional SOA with Visual Studio 2005

complexities of message interactions between components are governed by the enterprise service bus. As such if
the number of components increases the application does not necessarily increase in complexity.

Mediation support
The ESB provides mediation support to enable service interactions for example, the ESB can help a consumer
service find services that provide the requested capabilities and or to help take care of a interface mismatch
between the consumers and the providers. In many ways the ESB is much more than just a transport layer. It
must support a variety of ways to get on and off the bus, such as adapter support for existing applications or
business connections, that enable external partners in business-to-business interaction scenarios. To support
these different ways to get on and off the bus, it must support service interaction with a wide variety of service
endpoints. It is likely that each endpoint will have its own integration techniques, protocols, security models and
so on. This level of complexity should be hidden from service consumers. They need to be offered a simpler
model. In order to hide the complexity from the consumers, the ESB is required to mediate between the multiple
interaction models that are understood by service providers and the simplified view that is provided to
consumers.

Protocol independence
Services can be offered by a variety of sources. Without an ESB infrastructure, any service consumer that needs
to invoke a service needs to connect directly to a service provider using the protocol, transport, and interaction
pattern that is used by the provider. With an ESB, the infrastructure shields the consumer from the details of how
to connect to the provider.
By using an ESB there is no longer a direct association between the service consumer and the service
provider. The ESB acting as a tier shields the service consumer to the location of the service provider. The
consuming service in turn accesses the ESB to invoke the required service. The ESB can then convert the request
to the appropriate protocol or format before passing the information on.
The ESB generally supports several protocols and standards. Even if it in some cases the location
information is stored in a Customer Information Control System (CICS®) transaction and using a Java 2
Enterprise Edition platform resource adapter as protocol integrated with the CICS Transaction Gateway. By
using the ESB, the consumers are unaware of how the service is invoked on the provider. ESB thus allows
applications that do not implement service interfaces to become interoperable and aid in the migration of
architectures towards SOA.

Web Service Management Orchestration


In an ESB, each application’s service interface and logical address are referenced in a global directory. ESBs
support message movements between services and provide location transparency to the consuming service. The
interactions between consumer and provider can be configured internally within the ESB. Generally there are
several common models that can be configured between applications:

* Logical point-to-point connectivity can be defined,


* Broadcasting messages across the bus or to multiple predefined receivers
* Intelligent routing based upon message rules and message content.

Additional, process management engines can be integrated into an ESB allowing the process management
engine to manage and monitor the interactions of services within the ESB. Unlike traditional integration brokers
these service oriented process engines can control an entire network of loosely coupled service components. This

60
The Complete Reference To Professional SOA with Visual Studio 2005

can dramatically increases the scalability of applications whilst improving business process management
throughout the architecture.
Within the ESB events are triggered whenever messages are received. With both service consumers and
service providers none the wiser about the interactions that happen between requests. An architect can easily
configure interactions between two points as point-to-point then later alter the configuration to broadcasting. All
of these changes can be made without altering the underlying application implementation or its interfaces.

Figure 2-12 shows the inner working of orchestration happening within an enterprise service bus.

Orchestration-managed messaging tends to be more sophisticated than the standard SOAP messages you
may be using in simpler integration scenarios. For instance, messages processed by EAI components can contain
routing and transaction information in addition to standard data structure. Also, messages undergo various states.
The use of orchestration will often classify an integration solution as a virtual application. Abstracting
process and business logic into orchestration workflows also results in elaborate service assemblies that
encapsulate aggregated process logic.

Security in Service Oriented Architecture


The IT community is slowly embracing service oriented architecture because of its promise of efficiency and
improved IT management. However the openness that it brings raises another issue and that is security. This has
caused many organizations to proceed slowly or in some cases avoid implementing SOA all together. Security
has always been a concern for IT managers in large enterprise systems. Major systems have typically been
designed to protect against unauthorized use, intrusion, and viruses. Today however, the issue has taken on even
more seriousness in the wake of terrorist attacks and global viruses.
SOA security concerns are real and IT managers are realizing that they must soon identify and implement
various security solutions for SOA as more and more applications are exposed by developers as web services. A
pressing need exists to produce better security architecture as well as measures to ensure secure usage.

61
The Complete Reference To Professional SOA with Visual Studio 2005

The SOA’s inherent security problems stems from the way in which the SOA replaces traditional security
parameters with new, open standards. The security problem exists in that not only are the new standards
completely open but also the onus of which its security ownership belongs to is uncertain in a distributed world.
Web Services were developed over a period of years by industry consensus as a way to enable the creation
of reusable distributed code, simplify development, and streamline system integration. However these did not
address security. Specifically, XML, SOAP, WSDL, and UDDI are open standards that enable the transmission
and description of data and procedure calls between systems. However, none of these open standards contain any
inherent security aspects of their own. If left alone, they are completely non-secure. In fact, web services were
designed to be able to move more efficiently through firewalls. This very loose coupling and flexibility increased
its usability but decreased its security in this regard.
The main issues of any basic security infrastructure are authentication, authorization, and confidentiality.
The focus broadens where the infrastructure is exposed as in the case of SOA. In this case, concerns such as non-
repudiation, message integrity, and legally binding identity assertion become vital.
In this section, we will discuss these principles. The goal is to use security as a tool to foster and encourage
the use of Service-Oriented enterprise architecture.

Security Basics

Authentication
Authentication is used to establish that the requesting consumer is genuine and that the account is valid. The
caller must provide identity credentials such as username and password or in some cases a digital certificate. In
SOA there can be three levels of authentication:

* First level refers to application level authentication

* The second refers to SOA framework authentication


* The third refers to service level authentication.

Authentication at the application level is generally straight forward and mandatory for the business in order
protect from unauthorized access. Authentication at the infrastructure level is preferred instead of requesting
access to each Web Service. This allows security policies to be maintained more easily at a central place instead
of for each web service.
A single sign-on framework can provide credential mapping, providing the correct logon credentials for
each invoked service or even backend applications. Single Sign-on is usually straight forward and transparent to
implement.

Authorization
In security authorization refers to the process of validating that a client has the necessary security privileges to
perform certain functions, or in our instance invoke a particular method on the Web service.
Most Web services coming in over the public network to an enterprise require authentication. A payment
gateway can not provide the service to debit money from an account until it knows who is using it. So
fundamentally, authorization requires authentication.
One method for authorization to be implemented is through a set of credentials that a subject identity carries
and presents. These credentials are then mapped to allow access to certain contents.

62
The Complete Reference To Professional SOA with Visual Studio 2005

Integrity
In security integrity refers to examining a message to see if it has been tampered with since it was initially
created. In SOA generally communication is facilitated through open publicly available networks. There is every
chance that as a message is produced and put on the wire that the message is intercepted and its content altered.
The altered content is then put back on the wire and sent as the original message to the receiver. This is a form of
deception and it is a possible form of attack that is possible in an open network unless security procedures are
implemented. We can ensure the validity of message integrities through process such as encryption and hashing
we will be talking about Web service security later in Chapter 13 (Web Service Security) and Chapter 16
(Windows Communication Foundation). Message integrity check thus refers to validating the message was
received precisely as it was sent with no content altered.

Confidentiality
In security confidentiality refers to keeping a message confidential. Implementing confidentiality is important in
SOA context. This is because of the open architecture of SOA. With the necessary access to network it is
possible to intercept messages. Thus keeping information secure and confidential is especially important when
financial applications are concerned. By using encryption we can scramble the messages so that only the
authorized recipients can decrypt and view the message. Even if messages are intercepted without the decryption
key the message itself remain scrambled and useless. In XML Web service we can use a number of encryption
techniques to keep the message confidential. The most popular method is to use a Public Key Infrastructure
(PKI) where a message is encrypted using a public key and decrypted with a private key issued through a trusted
third-party authority.

Non-repudiation
Non-repudiation proves that one identity sent the data to another identity. This proves that the recipient entered
into this specific transaction, and neither party can refute or deny that it occurred later. Non-repudiation is
achieved through the use of public key cryptography. One identity prove that it had sent the data only to another
identity because the sender used the recipient’s public key, and it is only the recipient with his secret private key
who can decrypt the data. To achieve non-repudiation, separate timestamp notary is required to prove when the
transaction occurred as well as independent verification of the participant’s identities.

Web Service Security

Point-to-Point vs End-to-End Security


Point to point refers to the lower layers of security. This is usually achieved through the use of SSL short for
Secure Sockets Layer, SSL is a protocol developed by Netscape. SSL uses Asymmetric Encryption where
messages are encrypted using public key that is shared with the public and decrypted with a private key that is
only known by the recipient of the message. SSL support was integrated into browsers so that security can be
implemented for messages traveling from the server to the browser. Today most browsers support SSL. Web
sites that require SSL must have a valid security certificate. Web sites that implement SSL security are identified
by HTTPS instead of the usual HTTP.

63
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 2-13. Shows point to point security only

In the above diagram Figure 2-13 transmission of data between Partner X and that of its Web service only
implements Point to Point security. This means that whilst data traveled in the first segment of the network from
Partner X it is protected by SSL encryption. However due to various reasons, most commonly network
ownership issues. We can not enforce network security upon rest of the segments of the network. It is at these
other networks segments that our data become vulnerable.

Figure 2-14 is point-to-point and end-to-end.

Figure 2-14. is point-to-point and end-to-end

In the above diagram Figure 2-14 we’re implementing point-to-point security added with end-to-end security. Even
though data travel through networks that does not implement the necessary SSL data security (point-to-point). The data
itself is encrypted (end-to-end). Thus data protection is ensured at all stages of travel.
Another protocol for transmitting data securely over the World Wide Web is Secure HTTP (S-HTTP).
Whereas SSL creates a secure connection between a client and a server, over which any amount of data can be
sent securely, S-HTTP is designed to transmit individual messages securely. SSL and S-HTTP, therefore, can be
seen as complementary rather than competing technologies. Both protocols have been approved by the Internet
Engineering Task Force (IETF) as a standard.
However point-to-point based security has its limitations. Firstly, SSL is designed to provide point-to-point
security, which falls short for Web services because we need end-to-end security, where multiple intermediary
nodes could exist between the two endpoints. In a typical Web services environment where XML-based business
documents route through multiple intermediary nodes, it proves difficult for those intermediary nodes to
participate in security operations in an integrated fashion.
Secondly, SSL secures communication at transport level rather than at message level. As a result, messages
are protected only while in transit on the wire. For example, sensitive data on your hard disk drive is not
generally protected unless you apply a proprietary encryption technology.

64
The Complete Reference To Professional SOA with Visual Studio 2005

Thirdly, point-to-point in its current form does not support non-repudiation well. Non-repudiation is critical
for business Web services and, for that matter, any business transaction. What is non-repudiation? Non-
repudiation means that a communicating partner can prove that the other party has performed a particular
transaction. For example, if E-Trade received a stock transaction order from one of its clients and performed the
transaction on behalf of that client, E-Trade wants to ensure it can prove it completed that transaction to an
arbitration committee, for example, if a dispute arises. We need some level of non-repudiation for Web services-
based transactions.
Finally, point-to-point does not provide element-wise signing and encryption. For example, if you have a
large purchase order XML document, yet you want to only sign or encrypt a credit card element, signing or
encrypting only that element with SSL proves rather difficult. Again, that is due to the fact that SSL is a
transport-level security scheme as opposed to a message-level scheme.
Even though point-to-point provides some aspects of security such as confidentiality and authentication,
however, web services require data validation, accountability, and distributed authentication and authorization.
None of these are provided by point-to-point security. However, these security requirements can be
supplemented with the use of XML security technologies, including XML Signature and SAML, which apply
security at the message layer. Please note that point to point does not compete with end to end in fact the two
complement each other however point to point alone is not adequate enough for the purpose of providing SOA
level security.
For the purpose of this book we will focus on achieving end-to-end security.

Web Service Authentication


As computer systems have increased in complexity so has the challenge of authenticating users. As a result
there’re a variety of models for authentication in Web service. For example, clients accessing a web application
may directly provide credentials, such as a user name and password for authentication. However, a third-party
security broker, such as a Kerberos domain controller, may be used to provide a security token for
authentication.

Figure 2-15 illustrates the Web service authentication models.

The mechanism that we choose to use for authentication will have an affect on other security
implementations such as encryption and signatures.

65
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 2-16 depicts a direct authentication when a client and service share a trust relationship.

In Web service a consumer of a Web service can directly submit authentication information to the web service
when a client and service share a trust relationship Figure 2-16. This is regarded as Direct Authentication. This is
simplest form of authentication in terms of implementation.
In a more complex model where a client and service do not share a direct trust relationship, a mutually
trusted broker can be used to perform authentication. The client will send a request to the authentication broker
who then validates the client and sends a security token. The client then using the security token can send
requests to the Web service. Upon receiving the request the Web service then sends the token to the
authentication broker for validation. If the broker returns a valid response then the Web service will process the
request. Though, typically the Web service does not always send the token to the broker for authentication. As
receiving the token is often enough proof of the client’s relationship with the broker.

Figure 2-17 using a broker to perform authentication when client and service do not share a trust relationship.

WS-Security
WS-Security is the name given to the set of security standards that have been ratified by the Organization for the
Advancement of Structured Information Standards (OASIS). WS-Security is a conceptual model that abstracts

66
The Complete Reference To Professional SOA with Visual Studio 2005

different security technologies into “tokens”. It formalizes a way to package security tokens into SOAP
messages. WS-Security provides a set of additional roadmap specifications built on these concepts and integrated
into XML specifications. These roadmaps describe how to apply for a security token, how tokens are linked to
identity and how they’re linked to a web service and more.

XML Encryption
XML Encryption utilizes cryptography technology using shared key encryption. Shared key encryption was
selected because it allowed for the encryption of varying sized XML messages efficiently. Encryption provides
for message confidentiality (the message remains a secret from all but its recipient). The reason XML encryption
is needed over and above point-to-point encryption mechanisms like SSL is because confidentiality of messages
needs to be maintained while the message is taking multiple server hops on its way to its destination. This will
be common when shared services are utilized. We also need confidentiality when the XML message is stored
even after it reaches its final destination. This requirement is called persistent confidentiality.
There are two types of encryption typically used in Web service security these are symmetric key encryption
and asymmetric (public) key encryption otherwise known as Public Key Infrastructure (PKI), both encryptions
can be used in conjunction with one another.

Symmetric Key Encryption, refers to encrypting and decrypting a message using the same
key. The key is always kept private and only known to each of the parties that is one who
encrypt and send the message and one who receive and then decrypt the message. Symmetric
Key Encryption is simpler to implement than Asymmetric Key Encryptions and performance
wise it is faster because it requires less computation.
Asymmetric (Public) Key Encryption, also known as Public Key Infrastructure (PKI) refers
to encrypting and decrypting using two different keys a public key which is used to encrypt a
message and a private key is used to decrypt the message. When the owner of the private key
wishes to send a message to other parties the private key can be used to encrypt the message
and the public key used to decrypt the message. Today Asymmetric Key Encryption can be
implemented through X.509 certificates. A client uses the public key (of an X.509 certificate)
to encrypt his message and only the owner of the private key (of that X.509 certificate) can
decrypt the message.

Due to the open nature of Web service security is very important, since SOAP messages are essentially just
plain texts that are transported across the wire. Anyone can intercept the message and read its content. The Web
Service Extension (WSE ) specification supports both symmetric and asymmetric encryption. Using WSE, in
symmetric encryption the Web Service and the client share a secret key outside the SOAP message
communication, the client encrypts the message using this key and the Web Service decrypts the message using
the same shared key.

XML Signature
XML Signature is the foundational technology for the Web service security standard called WS-Security. XML
signature is built on top of mature digital signature technology. The purpose of digital signatures is to provide a
mechanism for message integrity (to ensure no alteration on the message) and non-repudiation (can not contest
that the transaction had occurred). XML Signature enables you to encode digital signatures into XML.

SOAP Message Monitoring


SOAP message monitoring based on SOAP interception is one way to build the foundation of an effective SOA
security solution. SOAP interception involves placing a special piece of software called a “SOAP interceptor” in

67
The Complete Reference To Professional SOA with Visual Studio 2005

the path of the SOAP messages that travel back and forth between a web services consumer and a web service.
Because of their ability to process, monitor, copy, and forward the data-rich SOAP messages. SOAP interceptors
are a very prominent element in SOA security. An SOA security solution examines the SOAP invocation
messages approaching the web service as well as the response to those service calls. It analysis the message, the
SOA security solution checks to ensure that the requesting entity is authenticated and authorized to use the web
service. The SOA security solution accomplishes this by checking the user data contained in the SOAP message
header.
Your SOA security solution should be complementing an existing security solution that you deployed to
secure your entire enterprise before beginning transitioning to an SOA. This may mean that your SOA security
solution will need to plug into existing security infrastructures to authenticate and authorize access requests.

Figure 2-18 Shows a SOAP Message interceptor, interception and authorizing messages.A vendor requires access to a
particular service from the supplier, the request is interrogated against an existing security infrastructure before it is
forwarded onto the service within the network.

The authentication and authorization of the users on the SOA occurs when their credentials are checked with
the security infrastructure of authorized users Figure 2-18. This is achieved by intercepting the SOAP messages
and comparing the users listed in the message header with those users stored in existing security infrastructure.

Security with Federation and SOAP Interceptor


One of the key security problems associated with SOA is its openness. It is this openness that introduced new
problems with authentication. We can no longer authenticate a client requesting service just from our own user
database alone because with SOA, business partners when given permission can also access the same required
services. So then how do we authenticate and check authorization with clients that don’t originate from the same
enterprise architecture? To deal with this we can use the Web service standard for federation (WS-Federation)
for security access. Federated authentication refers to creating a federated identity management system, it can
access security information from a number of sources. This identity management system can gather user security
information through established trusts with each of the enterprises. So now when a request is received it is
validated against the federated identity management system first. If required the federated identity management
system will query the relevant security database on either of the systems before returning a response.

68
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 2-19. shows a federated authentication user database created from a Partner X with a LDAP system and a Partner Y
with an internal custom security solution system.

In Figure 2-19 a request is sent by one of the partners requesting for service from our server. The message
passes through the firewall and is received by our security infrastructure which then validates for authentication
and authorization. If the request is from a valid client then the message is forwarded on to the service. Otherwise
the message will simply be dropped

Security with Federation and SAML


Alternatively to SOAP message interceptor we can also use Security Assertion Markup Language (SAML). In
the model of using federated security infrastructure it is also common to use SAML. SAML is an XML standard
for exchanging authentication and authorization. SAML assertion much like SOAP message interceptor in that it
watches the messages as it arrives. The SOAP message is then authenticated and authorized before a SAML tag
is inserted into the SOAP message. The tag can contain security information and attach additional information
about the requesting client such as security group it belongs to.

69
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 2-20. SAML

Figure 2-20 shows the use of WS-Federation to authenticate an income SOAP message once the message
has been authenticated a secure assertion markup language (SAML) is appended to the SOAP message. A
vendor in this case sends a request to the supplier. The request is checked against a security infrastructure if
found valid a SAML message is appended to the request which is then forwarded onto the supplier. The supplier
then checks the SAML before it responds to the request.

Application Proxy
One highly effective way to protect the security of core systems is to avoid letting an unauthorized requests to
reach the server that is hosting the web service. Through the deployment of a firewall to secure the server and
then applying proxy for the web services within the SOA. A secured application proxy can receive and respond
to all web service requests on behalf of the actual web service, and is protected from unauthorized requests. The
proxy can also manage and cache requests to authenticate and authorize web service requests. The proxy can
also append SAML to SOAP messages there by eliminating the need for actual requests to security systems at
the web service level.

Message Reliability in Service Oriented Architecture


One of the biggest challenging in developing for Service-Oriented Architecture is maintaining reliability for
mission-critical applications. This is because of the nature of unreliable network transports, such as HTTP, and
the lack of reliable message delivery. However by adopting a reliable messaging specification for Web services
and adding reliability headers into SOAP messages, Web services can be used for a broader range of
applications, and application development can be dramatically simplified.
Reliability for Web services is defined independently of the transport as a series of SOAP messages
exchanged within a group or sequence and some processing rules governing the use of acknowledgements and
message numbers to ensure that all the messages are received, duplicates are eliminated, and that message

70
The Complete Reference To Professional SOA with Visual Studio 2005

ordering is preserved. Of course, Web service reliability does only refer to messaging. Security, transactions and
execution environments such as clustering and redundant storage all have an impact on reliability.
Reliable messaging technology requires a piece of software infrastructure deployed on both ends of
connections. The reliability-messaging agent handles errors in the transmission of messages from one computer
to another over a potentially unreliable network. Typically the agents are symmetrical implementations so that
mutual handshakes can be implemented.
The reliability-messaging agent assigns a sequence ID to a group of related messages and message IDS to
the individual messages within the group. The requester’s agent marks the last message in the group, and the
provider’s agent returns an acknowledgement to indicate whether all messages in the group were received. If one
or more message IDs are missing from the acknowledgement, the missing message is resent until the provider’s
agent returns an acknowledgement containing all the message numbers in the group.
The sequence IDs and message IDs can also be used to prevent duplicate message processing and to require
that messages be processed in the order they were sent. Reliable messaging mechanisms can be used with SOAP
Message Exchange Protocol (MEP). A MEP is a template specified for exchanging SOAP messages between
nodes to ensure reliability. Typically the message exchange between nodes is predefined synchronous data
exchange.

Figure 2-21 depicts a reliable messaging architecture.

A reliability layer is introduced between the transport and the application that interprets and executes a
series of message acknowledgements Figure 2-21. Acknowledgement from the provider allows the consumer to
know if a message has been successfully received by the Web service. This is very important in a mission critical
system. The reliability allows both parties to temporarily store their message within a file or a database incase of
unsuccessful or missing messages. The sequence of messages is then removed from the database when
acknowledgement is received from receiving party. However if a message acknowledged as missing then it will
be retrieved from the database and resent to the receiving party.
In Web service specification both WS-ReliableMessaging and WS-Reliability establishes standard processes
for the acknowledgement of successful message deliveries and the notification of transmission failures. It can be
used in conjunction with other specifications, such as WS-Security, WS-Policy, WS-Coordination, and WS-
Transaction.

Summary
Developing for any architecture requires a great deal of requirements gathering and planning, and with it comes
a great deal of responsibility. The initial step is to plan out the roadmap that you will need to take through out the
development of your SOA. This will help you realize your long-term goals whilst keeping your short term goals
in check.

71
The Complete Reference To Professional SOA with Visual Studio 2005

Your SOA needs to be agile and flexible and structured according to business domains and business
requirements. This can be achieved through the use of several service types. These are Basic Services, Data-
Centric Services, Logic-Centric Services, Transitional Services and Public Services. These services are used to
provide SOA layer, which abstracts the constraints such as location, operating system, and language. Together
the different service types help to create a balanced SOA architecture.
If you’re developing on top of legacy systems or large enterprise systems that already has web services quite
often you will need to aggregate these entities to a higher level. This is important in maintaining abstraction at a
higher level and ensures that the overall SOA remains flexible and agile so that they do not need to consider
physical location constraints.
In SOA, Enterprise Application Integration (EAI) is aided by an integration middleware. Its role is to
connect a broad range of applications and let the organization decide how they should be logically coupled to
automate key business functionalities. The middleware provides organizations with flexibility to allow services
to publish and subscribe asynchronously. This resulted in the rise of Event-Driven Architecture (EDA) which
uses SOA based concepts to provide a more flexible and robust system of collaboration.
However due to the flexibility and openness of SOA it opens up security vulnerabilities. We have examined
various security concepts within the chapter to lock down and secure a real enterprise SOA. These techniques
include: point-to-point and end-to-end security, web service authentication, xml encryption, xml signaturing,
SOAP message monitoring, Security Assertion Markup Language and Application Proxying. Understanding of
these techniques are essential in providing your enterprise with a secure and yet flexible architecture that will
save you in the long run.
We have also discussed the importance of ensuring message reliability in a largely unreliable delivery
system. This is essential in any form of mission-critical systems where successful transmissions of message to
destinations are vital.
Overall we have examined various aspects of SOA and by now you should have a firm grasp and
understanding of SOA and the tasks involved in approaching planning, development and deployment.

72
The Complete Reference To Professional SOA with Visual Studio 2005

Chapter 3 Business Adaptation


of SOA
Previous chapters focused on what SOA really is and provided technical concepts to the implementation of SOA.
In this chapter we will be focusing on the challenge of introducing SOA to the business as well as discuss the
benefits to the business and pitfalls that may arise.
Up until now we have discussed a lot of positive aspects of SOA. However as much as we love SOA to be
everything and some what of a silver bullet but it is not. Far from it, SOA is often described as a journey not a
destination. The journey of SOA realistically is quite difficult and time consuming, however weighing in the
positive outcomes the journey is well justified. In a service-oriented enabled architecture, the total cost of
ownership is reduced, development time of new systems through the use of existing components is reduced, total
system maintenance is reduced and system scalability improved.
Even though the journey of becoming service oriented is very difficult and costly at first. Organizations that
have gone through this journey will dramatically benefit from it. While those organizations that have architecture
that are rigid and difficult to change and improve will comparatively eventually perish.
It is a journey that organizations should and must undertake sooner or later.

Service Orientation and Its Role in Our Connected


System Strategy
The primary reason for most organizations to adopt a service-oriented architecture is to increase agility of the
enterprise IT systems. On top of this SOA also allows the reduction of technology dependency to a
simplification of the development process. This allows for flexibility and reusability of the business
infrastructure.
The focus of additional flexibility is to allow processes and services to be rapidly developed and configured.
The reason for efficiency and speed is the ability to reuse existing technology investments. This allows
organizations to save tremendous amounts of resources on redevelopment and testing. Let’s face it no matter
how great the new component will be there is always an integration phase and there may always be that few bugs
that will cause headaches to the users. Existing investments that have worked for many years will continue to
work and continue to do what it is suppose to do. Isn’t it much safer to just place a service on top of that piece of
business logic to promote inter-operability instead of redeveloping the component again?
With the vision of agile enterprise, it allows a much superior time to market for new business initiatives.
This allows the reconciliation of the growing demands of a rapidly changing business environment with the
limitations of current technological and organizational infrastructures. Consequently, the Agile Enterprise is not
characterized by a fixed state of the enterprise but by an ongoing change process within the enterprise.
The value of the agile enterprise architecture can not be understated. In today’s business world new mergers
are forged continuously. It is therefore vital for the IT infrastructure to support Enterprise Application
Integration (EAI) so that new components can be registered onto the infrastructure quickly. It’s important for IT
infrastructures to keep up with the business requirements in order to improve the competitiveness of a business.
Not only will an agile structure support this, but also take the pressure of the enterprises with on going
maintenance and changes. Due to the competitiveness within the business world businesses are continually
forced to reinvent themselves by offering their customers new or better products to stay ahead or keep up with

73
The Complete Reference To Professional SOA with Visual Studio 2005

their competitions. In order to remain efficient, partners and suppliers must regularly evaluate to find better
quality, prices and conditioned products.

Figure 3-1 illustrates the benefit of a service-oriented agile architecture.

Why do we need flexibility?


In the past changes required to an organization resulted in technological obstacles. For example replacing a
partner or supplier might be straightforward in theory, but it could require major efforts in reality. These efforts
could involve a complete redevelopment of technical components and a major redesign of business processes.
Similarly, integrating a newly merged or acquired company’s IT infrastructure and processes might call for a
large-scale integration project. In addition, although offering new or better services might be desirable from the
business perspective it often proves to be technologically infeasible. Primarily due to lack of time and lack of
resource. These are the primary limiting factors to a business. Quite often developing the desired practical
solution would take too long to be of use. For most products, there often is a window of opportunity (time-to-
market) that must not be missed. Or developing the requirement functionality is simply not possible because of
the cost involved. For example replacing a supplier is only profitable if the cost does not exceed the saving
obtained through the replacement.
Recent research on 365 organizations found that 82% of the IT projects are late, over budget, or have
reduced features. On average IT projects are 189% over budget and 1/3 of late projects are late by 100-200%
with 70% of IT work being reworked. With a record like this we can easily see that there are serious problems
with the way IT currently works. From the statistics we can see 70% of IT work being rework. If we were to
reduce that 70% rework surely it will decrease some of the other percentiles. This will in turn reduce the time
taken for delivery as well as the total cost involved in development.
SOA provides the means for achieving flexibility by leveraging an appropriate architecture and reducing the
amount of rework within an architecture.

Agility
We’ve constantly mentioned agile architecture. In case we’re still confused or wondering what it is, agile
architecture simply means an architecture that is responsive to the need of that of the business its serving.
However to reach agility is no simple matter. In order to fully understand the benefit of agility we must identify

74
The Complete Reference To Professional SOA with Visual Studio 2005

the different levels at which enterprise projects may be threatened by complexity. These inevitably, diminish the
effect of an agile architecture.

Technology
Technology and the ability to understand the complexity of different technologies as well as its functionalities is
always going to be an issue. Often complexity comes as a result of yearlong efforts to add patches to existing
systems which provide more functionality. Whilst other complexities come as a result of using cutting edge /
bleeding edge technologies that have not yet matured. This results in complex configuration as well as
proprietary systems that is not backward compatible in its future releases. Finding the right people to manage
these technologies will always be a key limiting issue.

Communication & Location Issue


In the past one of the key issues with developing enterprise applications when different components are
developed by different teams from different countries is communication. A very high level of communication is
required and as well as comprehensive understanding of requirements is vital. However reality is vastly different
and chances are people from these teams speak different native languages and communication is and always will
be an issue. Even when the language is the same see Table 3-1. As we can see even when we speak the same
language sometimes different meanings are implied and could result in different outcomes. This is an issue when
developing cross country.

Table 3-1. Outlines the difference in meaning even when they’re common words in English.

Expression Meaning in countries listed Meaning in countries listed

pavement (noun) paved area at side of road set paved surface of road (US)
aside for pedestrians (CA, GB, HK)

biscuit (noun) A crisp, generally sweet, confection Soft, flakey savoury pastry eaten
(AU, GB, HK, ZA) with gravy (US)

corn (noun) Grain, or a cereal crop, as in Maize (AU, CA, US)


“cornfield” (GB)

table (verb) To put forward a proposal (AU, CA, To abandon a proposal (US)
GB, HK)

Business Process
Business process complexity is not always obvious. However it is as important as the technological complexity.
Typically a complex business process will result in a complex implementation. It is often during implementation
that the real complexity comes through. Another issue with Business process complexity is that there is quite
often a lack of documentation. In any business, processes should be documented. However, realistically this is
not always the case. Quite often documentations were made at the start of a process and as the business
processes evolve the documentation is left behind. This is an inherent issue in IT as outdated business process
documentation often finds their way to an unsuspecting developer. Sometimes the issue does not become
immediately visible until solution becomes complete.

75
The Complete Reference To Professional SOA with Visual Studio 2005

Business Functionality
Business functions themselves can be complex. They can contain complex contradicting logic between different
functions. The complexity associated with any one function could exponentially explode at its component level.
A very good example of this is insurance, the complexity involved in calculating something as simple as
premium could easily become exponential based existing data. At a global level each service providing logical
functions has the potential to have its complexity increased exponentially. In this case careful planning and
detailed documentation is required at every level. This will save tremendous amount of time on future support
and maintenance.

Integration
Integration is key to any enterprise application. Typically, enterprise projects combine functionality from
existing applications. Even if the individual application is stable and has been well tested, using it in a new
context and integrating with them and other application generally can become complex and unpredictable.

Support
Supportability is vital to the on going maintenance of an application after it has been deployed and is running in
a production environment. However maintenance of a complex application can be quite difficult. It is important
to plan out trace and logging functionalities and exception handling within the application early during
development. This will save considerable time in support. Typically customers are not interested about how
complex the application is. All they’re interested is whether it takes 30mins to fix something or 3 days. Often
applications are frequently updated such as when additional functionality has been introduced or when a new
version of software has been released. Such updates can cause the complex issues similar to those encountered
during the initial integration of the application.
Without an appropriate architecture planning, all of the outlined complexity could easily get in the way of
our agile architecture. Thus preventing all the real benefits of a service-oriented architecture. SOA can help to
significantly reduce complexity at all levels. This is a key aspect of SOA which allows existing infrastructures to
react as quickly as possible to the changing business environments and offer new services to its customers.
In order to achieve SOA the following must be carefully considered.

* Decomposition. SOA decomposes large, complex systems into application frontends and services.
* Appropriate granularity. The granularity of services is well suited to gain a high-level understanding of the
entire system. Unlike other approaches SOAs do not confuse practitioners by presenting too much detail.
* Decoupling from technology. SOAs can be well understood without in-depth knowledge of technology
* Reuse. SOAs result in the high-level reuse of existing components. This streamlines the code base and reduces
complex redundancies.

* Documentation. Due to the service contracts every service is well documented, which adds to the
comprehensibility of the SOA.

Reduction in Cost of Development


One of the main reason that we strive towards agility and efficiency is because of the benefits of reuse that SOA
brings. By having a greater support for reuse commercial organizations can benefit with increased return on
investment (ROI) and faster and more efficient development. Generally, we differentiate between direct IT cost
saving and direct business cost saving.

76
The Complete Reference To Professional SOA with Visual Studio 2005

IT Cost Savings
SOA in an enterprise project will be able to considerably reduce project costs because it allows for more efficient
implementation and deployment. However in order to achieve reduced project costs initial SOA infrastructure
must already in place. To convert to a SOA infrastructure from a rigid infrastructure could initially be costly. For
those organizations that undergo this process the benefit will be evident in future development compared to those
that have not.
By adopting SOA early, the long-term maintenance of SOA is also reduced. This is due to the simplification
of application. Future changes can be made more easily. Maintenance efforts can be targeted to business
functionality. Side effects can also be reduced and comprehensibility can be increased due to a clear
decomposition of the application landscape within components.
Finally, correct adaptation of SOA guarantees future proof solutions. This is due to the ability for web
services to provide abstraction from the underlying technology. Thus the service itself is not tied to any
shortcomings of technology. SOA also allows the preservation of IT investments because it enables us to
integrate functionality from existing systems in an enterprise instead of replacing them. This support for
reusability is central to so much of better future IT development.

Business Cost Saving from SOA


SOAs can help to reduce costs in the enterprise’s core business. These cost savings come from SOA’s agility.
Because of the flexibility of SOA it allows organizations to pick and chose the cheapest service supplier. In the
past organizations were held ransom by these services suppliers as in order to change to another service supplier
often meant considerable cost to infrastructure redevelopment. SOA solves the issue that are related to changing
suppliers. By providing the means to have more flexibility within the architecture, so that re-integration with
another cheaper supplier can be achieved in a timely manner.
SOA helps to streamline business processes. Allowing a business to make use of internal resources in the
most efficient way. In traditional environments, adaptation of existing applications are costly and typically
prohibit IT system changes and thus prohibit rapid changes of business process.
With improved agility businesses can monitor every section of the business process. Allowing more detailed
financial analysis and tracking which was costly and difficult to implement in the past. Due to its ability to make
different parts of the architecture share live data, SOA financial reporting on the spot is possible. This gives live
statistics and reason to allow management to make more appropriate business decisions on daily basis.
We can see the value of SOA and its benefits to an organization. Most of these benefits are related to SOA’s
flexibility and agility, solving the age long issue of rigid architecture.

Opening Our Intellectual Property


The Web is evolving from a collection of linked pages to a network of interactive applications that communicate
and collaborate. Today we see the websites starting to work together to introduce a new compelling concept of
no longer just one lonely website but a new series of connected web services creating a limitless platform.
With this change the question the organizations are asking is how can they benefit from this advance and
adaptation in technology? As internets old and new considers the best ways to profit from the evolving Web.
Originally the HTML-based Web began as a better interface between humans and information stored on
servers. Largely due to the popularity and the mutual adaptation of XML and Web Service organizations are able
to open up specific APIs to their partners and clients. This openness, allowed developers to come up with more
innovative ways to share and access data. This in reality worked well for both parties.

77
The Complete Reference To Professional SOA with Visual Studio 2005

Suppliers
Organizations had always longed for more development resource after all swiftness to act is the key to any
success in business. However to act quickly has always been extremely expensive and the solution produced are
often bug ridden and not always guaranteed to have rewards that were expected. As a result, businesses have
learned to be patient with technology. This meant that they’re no longer competing at the level that they like.
With SOA an entire architecture can be opened up. Organizations have the control on what component and
functionality to make available to its partners and clients. This changed the world of supply/customer
relationship in business. Previously the supplier developed applications for its customer and then in turn sold the
solution to the customer. This was rigid and the intellectual property often belonged to the supplier and therefore
the business restrained from making subtle changes to streamline business processes. This often made both
parties feel unhappy and tied down. The supplier of the system who uses its functionalities is reluctant to make
client-by-client changes. From a business perspective it was just not possible to develop and maintain for each
and every customer. While the customer was not happy with the rigidness of the application and the lack of
flexibility and support is constantly an issue for the business.
Suppliers are beginning to see the benefits of SOA as they’re able to open up their functionalities and leave
the rest to the consumers. This reduced the responsibility and maintenance costs of maintaining client side
applications. Suppliers could simply charge a service fee for each usage or its service. An example is a payment
transaction service, each time a client used the service a fee is charged to the registered client account holder.
This essentially allows consumers to build a provider’s business for them.
In fact the supplier is able to gain additional market and users through its client’s users. Which in turn
requires the supplier’s web services to function. This is an alternative strategy to expand one’s business through
the aid of others.
Opening up functionalities seems simple, and is simple. So what is the catch ? There really is none. It is
exactly the same as before but now there’s just a web service in between the client and the provider.

Consumers
The consumers of the business services are mostly the victims of rigid supplier-consumer relationships.
Consumers are nearly always given what they don’t want and functionalities that they don’t really need for a
costly price. Even after paying such high prices, support is poor.
When the suppliers opened their functionalities as web services. Their clients could programmatically
consume required functions. This gave the consumers unlimited flexibility on how they can use the
functionalities and how they can integrate their existing systems with the these services. Consumers could
quickly streamline their internal systems. This provided them with more value and control to their business.
They no longer have to purchase the pre-packaged bundle that was designed for everyone and catered for every
scenario. All they needed was to integrate the web services that their internal systems required to begin
operation. The integration process is usually straight forward and overall it’s a reduction on cost and thus better
return on investment.
Web services are the key to the platform evolution, because they provide a standard, controlled way for
outside machines to interact with corporate systems. A company can “expose” only what it wants in the form of
Web services: access to a database or product attributes, for example, or to an application such as search. Clients
“consume” these Web services by embedding them in their own applications or Web sites.
For example, instead of having to license and host a geospatial database, a site that publishes restaurant
reviews could embed a tag that calls on a third-party database when a user wants directions to a particular
restaurant. This is just like how suppliers build applications for consumers in the past. Except now the clients are
building the applications they want themselves, and thus expanding the supplier’s business by integrating
supplier functionalities within client applications.

78
The Complete Reference To Professional SOA with Visual Studio 2005

Take eBay. The online auction giant has offered APIs since 1999, as well as Simple Object Access Protocol
and Java integration capabilities to its software development kit. eBay has around 100 public Web services calls
available, while about a quarter of the money exchanged in the online marketplace is via PayPal, which is
effectively a Web service on eBay. This is a good example of an organization using third-party developers to
provide the growth that the organization need.
Organizations will often find that when outsiders build onto the platform, they often do it in surprising ways
that the mother company wouldn’t have considered. For example, when Amazon.com exposed data from its
Alexa Web Information Service (AWIS) program, it kicked off a wave of creativity as it provided aggregated,
close-to-real-time information about Web traffic, including the top sites visited and where visitors to one site go
next.
By offering web services to the public and generating a public following is like employing an army of
developers dedicated to a common course except without the cost. Third-party developers are often able to see
an aspect not seen from the business perspective. This promotes innovations but the focus is still on the
organization as it is still the public service that the third-party application is using. With this strategy in mind an
organization can quickly grow where growth was not possible previously.

Promoting Inter-Platform Connection


Independence from technology thus allowing inter-platform connection
Software increase – complexity has also increased therefore impossible and frequently difficult to develop
inter-platform solutions. Many large organizations generally have applications that reside on a range of
platforms. This is often because development technologies at the time were appropriate for certain aspects of the
overall system. However over time the result is a library of technologies sitting on different platforms that is
difficult to interoperate.
Today the focus on technology can be a huge issue in IT projects. We’re reaching a new generation of
interconnectivity where everything must be connected with everything else. To achieve interconnectivity
between various software solutions a large number of “helper” software applications were created they were
used to simplify certain integration tasks between systems. However as industry grew so did the different types
of software and also the number of “helper” solutions. Now we’re faced with a dilemma. This is because in order
to develop one particular solution as an architect we would need to know the ins and outs of a dozen “helper”
solutions. As a result valuable solution development time is often spent on debates about the right technology to
use often threaten to tie up resources that could be better spent designing and optimizing business processes.
These “helper” solutions often determined a project’s functionality and features due to its limitations.

79
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 3-2 illustrates that as the number of “helper” software increased the agility of development becomes inhibited.

SOA helps to shift the attention from technological issues to questions of service functionality and service
design. Allowing a more productive development cycle through the use of a range of technologies that was
frustrating and tedious to work together in the past.SOA provides an abstraction from the underlying technology
of different systems. This independence offers several benefits to an organization. Most important is the agility
that is brought to the business, subsequently allowing it to make important business decisions instead of waiting
on IT. This is all achieved through SOA’s ability to support inter-platform connections between some very
different systems.
Independence from technology also increases independence from software vendors. Applying SOA allows a
software system to choose the best of products and to combine them to formulate a well rounded solution that’s
not restricted by one software vendor.
The two most common contemporary application landscapes are characterized by two incompatible
development frameworks J2EE and .NET. This make it particularly difficult to create and maintain cross-
departmental business processes. Due to the tight coupling of business functionality to specific technology, it is
arbitrarily difficult to force different parts of the architecture to work together. SOA avoids these obstacles by
decoupling the technologies of the provider and consumer of specific business functionality. SOAs do not
interfere with the development framework itself. But rather it allows more efficiency and agility within the
application. It also promotes future reuse which allows for a reduction in development resource in future
projects.
Independence from underlying technology supports decoupling of technology lifecycles from the lifecycles
of business services. Therefore, the introduction of a new technology within an enterprise does not require a
makeover of the business processes and services. Similarly, new business service can be introduced without the
need to wait for new, innovative technology to become mature, stable and affordable.

Measuring a SOA
Determining ROI for service-oriented architecture can provide valuable information. It also justifies the
reasoning behind the push for SOA. However, putting together a realistic ROI is not a simple task and often
takes many revisions as new ROI information becomes available. Determining a ROI ahead of a project will
often shape an enterprise’s migration strategy. Whilst by examining the migration strategy also contributes to the
outcome of a ROI. Nevertheless realistically there is no real way of knowing the ROI until a project is actually
deployed. Even then measuring the real ROI will take months if not years.
Often determining ROI takes considerable research that tends to be performed for migration strategies and is
more focused on technology and implementation, rather than high-level organizational benefits. An intelligent
strategy for integrating a service-oriented architecture can lead to much greater cost benefits than an ROI can
originally predict. Even though if an ROI is used to justify the migration path of a project. The ROI can be
refined further on as new information is obtained.
The initial SOA migration phase is the most expensive phase of an enterprise-wide initiative however, the
scope of our ROI will likely always go beyond the migration phase. Further revisions to an ROI will improve the
accuracy of its predictions as they relate to subsequent phases in a long-term program. The benefits for SOA tend
to be tangible, because the interoperability enabled by the service integration layer results in immediately
recognizable savings.
To be able to measure a SOA a measurement plan must be drawn up from the start. The best method of
measuring of a SOA is to start with a small project and to expand and iterate as new information becomes
available. Make sure that the service is something that is simple and measurable such as a service which provides
access to a database. Because even small things have ROI value attached to them. The service should be
monitored and the results measured.

80
The Complete Reference To Professional SOA with Visual Studio 2005

To measure the success of a SOA it is important to draw up a projected ROI ahead of development. The real
ROI should then be tracked and monitored. By comparing the two values we can assess whether SOA
implemented is successful. Of course depending on the industry that the system is designed for the ROI will
vary, as not all industries have the same benefit from SOA. Typically Banking, Insurance, Telecommunication,
Retail and Government have the greatest ROI partly because they service such a large range of users. If we’re
not in these industry types we will still benefit from savings in asset re-use and business labor savings.

Figure 3-3 shows the four areas of ROI benefits.

In measuring SOA we look into four areas where ROI can be examined.

1. The simplest and most straightforward is short-term, tactical ROI, which is gained from the immediate
reduction in the cost of integration. This should be able to save us money the day after we implement SOA
from an immediate savings on integration. We will be able to get rid of middleware, reduce the time in
transformational mapping and get other similar benefits. It’s easily quantifiable, because we can identify the
business processes and systems that were replaced.
2. The second ROI can be obtained through application reuse. This is a little more difficult to get than integration
costs. To achieve it, a company has to identify areas of commonality between applications, and build services
for them. That way, the total amount of design, programming and development time can be reduced, because
the service can be designed only once, instead of multiple times.

3. The third area is in business agility, and this ROI benefit can be gained in the medium to long term. This allows
an organization to make rapid changes to its IT infrastructure when required. These are necessary in today’s
environment where alliances with other organizations are quickly forged and then broken. Traditionally IT
systems have always been a limiting factor in slowing down business process. So this ROI is particularly
valuable and allows for a faster time to market.

4. The fourth area of ROI is provided in a way of reputation. By having a faster time to market value to changes
in business process an organization can slowly build up reputation in the form of reliability. Although a
company will not gain anything from the ROI however it is possible for this ROI to generate potential income.

All these areas should be iteratively analyzed through our ROI evaluation.

81
The Complete Reference To Professional SOA with Visual Studio 2005

Organizational Roadmap
Identifying Stakeholders and Conflicts
Before implementing SOA at the enterprise level, we need to examine the different stakeholders within the
organization and avoid potential conflicts of interest to ensure a successful implementation of the new
implementation.
Even though it is true that every organization is different, and as such has different stake holders. Generally
an organization contains two types of stakeholders the decision makers who make financial and high-level
strategic decisions and the end users who are often operating the systems on day to day basis. It is essential to
have open and transparent meetings where all aspects of implementation and business process can be examined.
This will provide everyone within the organization with an opportunity to address any concern they might have.
An area of impact is the CEO and the board of directors that are responsible for high-level strategic
decisions, which often will have a direct impact on IT systems and system implementations. While another area
to be mindful is the business functional requirements, they often present the IT department with conflicting
requirements because their interests sometimes may conflict.
It is therefore important to identify the stakeholders and potential conflicts early on.
Figure 3-4 represents the equal stake holders within an SOA.

Figure 3-4. Stakeholders representation

IT is typically a cross-sectional service as such it is easy to become constrained by other business decisions.
These obstacles involve;

* It is more difficult to provide ROI for the push towards SOA. CEO and Business executives generally only
have a understanding towards investing in business applications that has a measurable return on investment.

* Difficulty with managing changing functionalities and changes in business strategy.

* Division in internal departmental conflicting interests,

82
The Complete Reference To Professional SOA with Visual Studio 2005

Business and IT
After executives have completed their decision making process, it is up to the business units and the related IT
projects and departments to implement systems that meet business requirements. The daily interaction between
business and IT people has traditionally been difficult. Business people often have a difficult time
comprehending why technical issues are so complicated, while IT people often struggle with the complexity of
having to understand detailed business procedures. Typically, business requirements require a large number of
specialists who have slightly different understandings of the environment and often differing agendas and
perspectives. While external vendors with their own consultants and products add to this complexity, all of this
increased complexity of matching business requirement to their corresponding technology.

Internal Politics
Internal Politics play a large role in the decision making process. Though, typically IT people coming from a
development background are not always aware of the intricacies involved. The CIO and technology architecture
boards often have different interests in the path of individual projects. These conflicts can have various reasons
sometimes disagreement may occur from difference in position of a particular employee. But it is an area which
one should be aware of. An architect for example will introduce standards that allow for technology reuse. While
a Project manager, on the other hand, often have a bigger interest in getting their projects out the door and costs
low, instead of investing the time to examine reusability. In these situations, it is often not a matter of reasonable
decision making but a question of who has the power to enforce a particular course of action.
Similarly, project managers and operations managers can have conflicting interests. How fast the project
delivers certain business functionality often measures the success of a project. Consequently, speed is the major
concern of a project manager. In order to ensure the successful delivery of the project the project manager must
ensure all aspects of the application had been thoroughly tested. These may include System Management
Integration, exception handling, CPU and Memory consumption, Scalability and over all application
performance testing. However these tests do not have any bearings to the operations manager and take up
development time and money.
It is necessary to consult stakeholders and identify potential conflicts of interest before a project begins. It is
important to hold meetings where all key stakeholders can attend and discuss issues that concern them. In this
manner solutions or alternative resolutions can be drawn up in an open manner.

Organization Vision
Once all the stakeholders have been consulted and potential conflicts identified and resolved, the next step is to
gather the key stakeholders once again to agree on the vision of the new enterprise SOA and the role the SOA
will play within the organization. The meeting can begin by formalizing a vision statement which states the
ultimate goal and how it can be achieved. People from both the business and technology side should be involved
in formulating this vision. It is in reality that the actual technology that drives business goals and the new vision.
However it is vital for the people from business section to validate the concepts of the vision from the business
point of view.
Once the vision statement is agreed upon, the next step is to define a plan that outlines how the goals
defined in the vision can be achieved. This does not require a detailed project plan but it is more about
motivating the organization towards a common goal. The development of the vision will have future impact and
bearing on all future development and business decision making process, which will eventually lead to budget
allocations, which is so important to the maintenance and the growth of the existing infrastructure.
It is important to keep in mind that once the vision statement had been defined we should consistently check
the process of existing development and ensure that the SOA is steered towards the new vision milestones. The

83
The Complete Reference To Professional SOA with Visual Studio 2005

introduction of an SOA is not a one-off project but it is a journey and requires constant efforts to ensure that
future development projects will stand by the principles of the SOA.

Budget Consideration
With the initial introduction of SOA the starting projects must be chosen with great care. As these initial projects
is what the business often judges the success of SOA on. Even though fundamentally the success of SOA should
be judged later on as it promotes reuse and thus reduces costs with later projects. Thus it is important to select
simple initial projects that can be developed as pilots. This will slowly ease the fear of everyone else who is
afraid of change. It is important that these initial projects are equipped with sufficient time and budget to meet
any unexpected issues that may arise.
Over all the initial beginning of SOA is always more expensive and has more overhead. This is because the
reuse and agility of the infrastructure still does not exist; as a result reuse simply does not occur. Thus instead of
merely focusing on the immediate challenges, potential future applications must be taken into account to ensure
maximum reusability and cost reduction in future.
After implementing SOA, Verizon Communications claims it averages about 2.5 million to three million
Web services transactions a day. The company claims that it was through implementing its internal application
IT Workbench, which was constructed on SOA principles and is built on XML and SOAP messaging. The
system became operational in 2004 and Verizon says it was able to slash its IT budget by 50% by eliminating
redundant systems inherited from the merger of Bell Atlantic and GTE. By adopting SOA, the company claims
that it also helped integrate the operations of some 7,000 developers. Verizon’s SOA covers about 250 services,
and the company says it plans to eventually support 33 million Web services transactions per year.

Gathering Internal Support


No matter what we do everything amounts to nothing if we do not have support. The focus on SOA is no
different. Support comes in various forms, whether it is a mind set support for SOA or financial support in
budget allocation. It is vital that we consistently gather and maintain these supports around us to ensure current
and future success of SOA.
To gather support we will need to please key areas within our organization that means providing better
services to key departments. While having the right people on the team is also vital. Our SOA team should be
consisting of SOA evangelists whose task is to explain the benefits of SOA to different departments. The
importance of the implementation of SOA is a mind set so it takes a lot of encouragement. But with consistent
iteration on the benefits of SOA and with increased service and support to key departments they will soon be
thinking the way we do.
We should keep in mind that these supporters of SOA always have their own interests and agendas and that
they have to sell the SOA to others. In order to successfully introduce SOA it is important to prepare specific
reasoning for various groups. The easier it is for our supporters to sell SOA the more likely it is for them to
support it.

SOA Driven Project Development using MSF


This section provides some overview to SOA project management using Microsoft Solution Framework (MSF).
Microsoft Solutions Framework provides an adaptable framework for successfully developing solutions
faster, with fewer resources and provides the medium to manage risk while also ensuring higher quality output.
MSF helps teams directly address the most common causes of technology project failure in order to improve
success rates, solution quality and reduce business impact.

84
The Complete Reference To Professional SOA with Visual Studio 2005

MSF provides a flexible and scalable framework that can be adapted to meet the needs of any organizations
with projects that varied in size and complexity. It also focuses on the planning, building and deploying of
business driven technology solutions. MSF can be applied to improve success rates for the following types of
projects:

* Software development projects, including mobile, Web and e-commerce applications, Web services,
mainframe, and n-tier.

* Infrastructure deployment projects, including desktop deployments, operating system upgrades, enterprise
messaging deployments, and configuration and operations management systems deployment
* Packaged application integration projects, including personal productivity suites, enterprise resource planning
(ERP), and enterprise project management solutions.
* Any complex combination of the above.

Challenges and Opportunities


In software development projects rarely go smoothly and majority of projects will never meet their deadlines.
This is often due to a number of factors mostly to do with people, other resources and technology involved.
Sometimes complexity involved in technology alone is enough to cause a project to fail. Success in project
planning thus requires a detailed understanding of the project requirements and the capabilities required to meet
goals. But most importantly an understanding of the development process is required.
When projects fail the following causes are often observed:

* Stakeholders were disconnected from the development process.

* Lack of communication and understanding of business needs by the development teams.


* Failure to address the real problem or omission of important features, and including unsubstantiated features.
* Unclear project requirements that are not understood by the participants which results in confusion, overwork
and missing elements.

* Lack of training or documentation after a complex system has been deployed resulting in misunderstanding
over system functions.

Generally organizations that have development processes in place avoid the need to overcome these issues
and thus derive better results for their business through higher product and service quality. This also improves
customer satisfaction and business reputation, which always leads to wining more projects through word of
mouth. These factors translate into a positive influence on bottom line and improvements in the organization’s
strategic effectiveness. MSF was designed and built to provide organizations with a clear roadmap towards
successful project planning and development.

MSF Tracks
The MSF Tracks describe a generalized sequence of activities for building and deploying enterprise solutions.
This process is flexible and can accommodate the design and development of a broad range of enterprise
projects. The MSF Tracks is a track-based, milestone-driven, and iterative model that can be applied to
developing and deploying enterprise solutions for SOA. There are two sets of tracks following MSF 4.0 for
Agile Software Development (MSF Agile), and MSF 4.0 for CMMI Process Improvement (MSF CMMI).

85
The Complete Reference To Professional SOA with Visual Studio 2005

MSF CMMI

Figure 3-5. MSF CMMI Tracks

The MSF CMMI represented in Figure 3-5 consists of seven distinct tracks:

* Governance
* Envision

* Planning

* Building
* Stabilizing

* Deploying

* Operational Management

MSF Agile

Figure 3-6. MSF Agile Tracks

The MSF CMMI represented in Figure 3-6 consists of six distinct tracks:

86
The Complete Reference To Professional SOA with Visual Studio 2005

* Envision
* Planning
* Building

* Stabilizing
* Deploying
* Continuous

Envisioning Track
The MSF process begins with the envisioning track. It is in this track where a broad description of the goals and
constraints of the project is defined. Here we identify the team and what the team must accomplish for the
organization. The purpose of the envisioning track is to build a shared vision of the project among all the key
stakeholders of the project.

* Setting up the team. Creation of a project team that represents all roles within the SOA. When setting up a
team, it is important to consider the skills, experience, and performance level of the team members. In addition,
there are practical considerations such as availability of resources and project budget.

* Defining the project structure. Identifying the administrative structure for the project team and the standards for
managing the project.

* Defining the business goals. Analysis of the business problem and opportunities in order to identify the
objectives for the solution.

Planning Track
Following Envision is the planning track, during this track the team determines what to develop and plans how to
create the solution. The team prepares the functional specification, creates a design of the solution, and prepares
work plans, cost estimates, and schedules for the various deliverables.
It is during this track analysis of requirements is performed. These requirements can be: Business
requirements
* User requirements
* Operational requirements

* System requirements.

Obtaining requirements are important because they in turn are used to design the solution and its features and to
validate the correctness of the design.
During the planning track, the team performs multiple tasks. The milestones of the planning track are:

* Technology validation. During technology validation, the team evaluates the products and technologies that
will be used to create or deploy the solution. The team also audits the customer’s current production
environment.
* Functional Specification. The functional specification is completed and submitted for review to the customers
and stakeholders. Remember that the design document is different from the functional specification. The design
document is written for the project team and describes the internal workings of the solution.

87
The Complete Reference To Professional SOA with Visual Studio 2005

* Mast Plan & Schedule. The mast plan is a combination of plans of various roles on the team. The master
project schedule includes all detailed milestone project schedules and the solution release date.

Developing Track
During the developing track, the project team creates the solution. This process includes creating the code that
implements the solution and documenting the code. In addition to developing code, the team also develops the
infrastructure for the SOA solution.
The team performs the following tasks during the developing track:

* Starting the development cycle. Verification that all tasks identified during the envisioning and planning track
have been completed so that the team can begin developing the solution.
* Creating a prototype application. Verification of the concepts of the solution design in an environment that
resembles the environment to which the solution will be eventually deployed.
* Building the solution. Developing the core functionalities, within the requirement for the project.

Stabilizing Track
During this track, the solution progresses from the state of all features being complete as defined in the
functional specification for this version to the state of meeting the defined quality level. On the completion of
this track the solution must be ready for deployment to the business. During this track the team will need to
perform integration, load testing on the solution. The teams also need to address any issues that may arise to
prepare for the project release.
During the stabilizing track the following milestones are reached:

* Bug Convergence. A milestone of the stabilizing track that marks the point at which the team makes
measurable progress against the active issue and bug count.
* Release. A series of milestones of the stabilizing track that reflects the incremental improvements in the
reduction of the issue and bugs.

* Zero-bug release. A goal of stabilizing track that marks the point at which the issue and bug count has met the
zero-defect metric for this particular point in time in the project.

Deploying Track
The team deploys the solution to the organization. The team transfers the skills and support to the relevant
department members, and obtains final customer approval of the project. After deployment, the team conducts a
project review and a customer satisfaction survey.
During the Deployment Track the following milestones are reached:

* Major components are deployed. Successful deployment of sites depends on these components.

* Site deployment complete. At the completion of this milestone, all intended users must be able to access the
solution. Leading developers for each component within the SOA must confirm that their sites are operating.

* Deployment stable. At this milestone, the customer and team agree that the sites are operating as required.
Issues may arise and will be tracked and resolved by relevant parties.

88
The Complete Reference To Professional SOA with Visual Studio 2005

Governance
Is a continuous track through out the lifecycle of MSF CMMI usually performed by people in the role of
Auditor. System governance and supports covers subprojects focusing on the transition of system wide structures
to govern and support the delivery of direct services. There are governance structures being developed to
facilitate inter-Authority communication and coordination.
Governance requires the continuous process of:

* Identify Inconsistencies

* Analyze Review Minutes


* Review Design and Code Guidelines
* Track Corrective Actions to Closure

Operational Management
Is another continuous track through out the lifecycle of MSF CMMI. Operational Management allows us to
better anticipate disruptions in day-to-day business operations and quickly take a direct and proactive approach
to improve results. Operational Management can be performed by people of the roles of: Project Manager and
Business Analyst.
Operation Management requires the continuous process of:

* Start with business activity monitoring to anticipate and eliminate disruptions

* Apply business integration to optimize processes by identifying performance improvement opportunities.


* Improve the ability to anticipate and act

Continuous Track
The continuous track is used by the MSF Agile track model. It is performed by people of the roles of Business
Analyst and Project Manager through out the life cycle of the project.

* Define Personas
* Refine Personas

* Review Objective
* Assess Progress
* Triage Bugs

* Identify Risk

Project Teams
MSF provides the MSF Team Model for organizing project teams. The MSF Team Model emphasizes the
importance of clear roles, responsibilities, and goals of individual members to the success of the project. This
model also increases the accountability of each team member. The flexibility of the MSF Team Model helps us
to adapt it to the scope of the project, the size of the team, and the skills of the team members. This forms the
basis of creating effective, resilient, and successful project teams.

89
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 3-7. MSF Team Model.

Program Management
The project manager advocates for the program management constituency in the MSF Team Model. The project
manager is responsible for the flow of knowledge creation and ultimately the realization of value, which comes
from delivery of the product outlined in the vision statement. The project manager owns the life cycle of the
project from end-to-end. The main goal is to deliver business value within the agreed upon schedule and budget.
The project manager is charged with planning and scheduling duties including developing project and iteration
plans, monitoring and reporting status, and identifying and mitigating risk. The project manager is also expected
to consult with business analysts to plan backlog for the project and its iterations, consult with architects,
developers, testers, user education specialists, and user experience architects to estimate work and facilitate
communication within the team.
The program management’s responsibilities are as follows:

* Capture Product Vision


* Create Product Requirements

* Develop Documentation
* Establish Project Process
* Manage Issues

* Plan an Iteration
* Plan Project
* Manage Risk

* Test a Customer Requirement


* Verify a Product Requirement

90
The Complete Reference To Professional SOA with Visual Studio 2005

Architecture
The architect role is to advocate for the architecture constituency in the MSF Team Model. The architect is
responsible for maintaining the architectural integrity of the product and ensuring the success of the project by
designing the foundations upon which all the value can be realized. This includes defining both the
organizational structure of the application and the physical structure of its deployment. In these endeavors, the
architect’s goal is to reduce complexity, decrease coupling and regression effects, and increase the cohesiveness
of components by partitioning the system into parts which can be built and tested independently. The resulting
architecture is extremely important because it not only dictates how the system will be built going forward but
also establishes whether the application will exhibit the many traits that are essential for a successful project.
These include its usability, whether it is reliable and maintainable, whether it meets performance and security
standards, and whether it can be evolved easily in the face of changing requirements.
The architect’s responsibilities are as follows:

Analysis

* Create a Quality of Service Requirement

* Create Product Requirements


* Create Solution Architecture

* Establish Environments

* Establish Project Process


* Test a Customer Requirement
* Verify a Product Requirement

Development
The developer advocates for the development constituency in the MSF Team Model. The developer is
responsible for the bulk of the work of building the product. Other development roles such as the lead developer
and development manager have additional communication and project management responsibilities. The
developer should suffer a minimum of communication overhead allowing for a maximum effort on construction
of code. In addition, during the early stages of a project, developers may be expected to help specify product
requirements not included in the customer requirements and to work on analysis and architecture activities as
part of a multi-disciplinary team. A lead developer's role is to lead and to communicate on behalf of other
developers. A lead developer advocates for the development constituency in the MSF Team Model. A lead
developer lends experience and skill and shows leadership by coaching fellow developers. Lead developers carry
responsibility for code reviews, design, and unit testing coverage. Lead developers act as a conduit to the rest of
the project for the developers. As an aid to productivity, lead developers funnel communications between the
wider project team and external organizations, and shield developers from noise and random interference in their
daily schedules. Because of this, lead developers can seldom dedicate themselves to development tasks.
Typically, they spend about 50% of their time on communication and split the remainder between leading and
coaching the developers on their team, and actually writing code for development tasks.
The developer’s responsibilities are as follows:

* Analysis
* Create Solution Architecture

91
The Complete Reference To Professional SOA with Visual Studio 2005

* Develop Documentation
* Establish Environments
* Establish Project Process

* Fix a Bug
* Implement a Development Task
* Release a Product

* Test a Customer Requirement


* Verify a Product Requirement

Test
The tester advocates for the test constituency in the MSF Team Model. The tester's main goal is to discover and
communicate problems with the product that could adversely impact its value. The tester must understand the
context for the project and help others to make informed decisions based on this context. A key goal for the
tester is to find and report the significant bugs in the product by testing the product. Once a bug is found, it is
also the tester’s job to accurately communicate its impact and describe any workaround solutions that could
lessen its impact. The tester makes bug descriptions and steps for recreating the bugs easy to understand and
follow. The tester participates with the entire team in setting the quality standards for the product. The purpose
of testing is to prove that known functions work correctly and to discover new product issues.
The tester’s responsibilities are as follows:

* Analysis
* Close a Bug

* Develop Documentation
* Establish Environments
* Establish Project Process

* Release a Product
* Test a Customer Requirement
* Verify a Product Requirement

Release/Operations
The release manager advocates for the smooth delivery and deployment of the solution into the appropriate
infrastructure. This role's goal is to manage the rollout of the product. The release manager coordinates the
release with operations or media control. They create a rollout plan and certify release candidates for shipment or
deployment.
The release manager’s responsibilities are as follows:

* Baseline Configuration Management


* Create Product Requirements

* Establish Project Process

92
The Complete Reference To Professional SOA with Visual Studio 2005

* Manage Change Requests


* Release a Product

User Experience
The user education specialist is typically a technical writer who advocates for the user experience constituency in
the MSF Team Model. The user education specialist focuses on consumer-focused technical writing which
reinforces or enhances product value and helps to realize the product vision. A user education specialist may
work on product manuals, on-line Help, operations manuals, maintenance manuals, training manuals, and any
other documentation which can be used to enhance the usage and value delivered with the product. User
experience architects typically work closely with user education specialists. A good user experience and product
design typically leads to a lower workload for the technical writing team. Excessive documentation may be an
indicator that the user experience is poor and the writing is compensating for poor overall product design.
The user education specialist’s responsibilities are as follows:

* Analysis
* Develop Documentation

* Establish Project Process


* Release a Product

Product Management
The product manager is the main advocate for the customer in the MSF Team Model. The product manager is
the proxy for the end consumer of the product. The product manager has overall product mix responsibility for
the requirements. The product manager must ensure that the product vision is met through the requirements and
the acceptance tests developed to validate the product. The product manager must show that the product aligns
with the organizations strategic planning and fits the market segment(s) intended in the original vision statement.
The product manager will ensure that the project stays within budget and that the business case is realized. The
product manager's work is used as the primary source for the track checkpoints in the MSF Governance Model.
The project manager’s responsibilities are as follows:

* Capture Product Vision


* Release a Product

MSF Risk Management


MSF risk management process promotes proactive risk management, continuous risk assessment, and decision
making throughout the project life cycle. The team continuously assesses, monitors, and actively manages risks
until they’re either resolved or turn into problems that can be broken down and allocated to relevant parties to be
resolved.
MSF risk management defines six steps through which teams can manage and avoid potential risks.

1. Risk identification, individuals are encouraged to identify risks so that other team members are aware of any
potential problems.

2. Risk analysis, in this step risks identified during risk identification are investigated these risks are assigned a
priority by the team.

93
The Complete Reference To Professional SOA with Visual Studio 2005

3. Risk planning, uses the information obtained from risk analysis to formulate strategies, plans, and actions.

4. Risk tracking, monitors the status of specific risks and document the progress of risk in their respective
development plans.

5. Risk control occurs when we are required to execute relevant risk management action plans, detailed status
report of the risk and its progress is then required.

6. The last step in the MSF risk management is, risk learning, the learning process will give teams an opportunity
to reflect upon the risk so that the knowledge can be formalized into documentation as a reusable form for
future use within the team and by the enterprise.

Simplifying SOA development using .NET and Visual


Studio 2005
Developing service-oriented applications has never been simpler with .NET Framework. The .NET Framework
provides facilities for creating, deploying and managing service-oriented applications. Using Visual Studio 2005
developers are able to develop web services that they can call from any other applications with ease. The
environment abstracts many of the specifics away from the developer, allowing us to focus more on the business
logic for our service rather than actual implementation.
With Visual Studio 2005, developers can support .NET objects natively that remove coding responsibility
from the developer (such as marshalling infrastructure, data structure management, and service discovery).
Additionally, we can support multiple versions of components for the same application, allowing for rapid
update and system modification.
The .NET platform provides built-in support for building and consuming standards-based XML Web
services. Unlike other development platforms, developers do not require additional tools or plug-ins to build
XML Web services with .NET. XML Web services are natively supported within .NET. Developers could
develop Web Services to improve interoperability (possibly across multiple platforms such as .NET and J2EE).
Visual Studio also has the advantage of having greater support for a set of commonly used pseudo-standards
such as Simple Object Access Protocol (SOAP), Web Services Description Language (WSDL), and Universal
Description, Discovery, and Integration (UDDI). While the process of developing service consumer applications
is also simplified through Visual Studio.
The Microsoft .NET Framework 2.0 also allows developers to use Web Services Enhancements or WSE
(pronounced “wizzy”). WSE 3.0 simplifies the development and deployment of secure Web services. It enables
developers and administrators to apply security policies to Web services running on the .NET Framework 2.0.
Using WSE 3.0, Web services communication can be signed and encrypted using Kerberos tickets, X.509
certificates and other custom binary and XML-based security tokens. In addition username/password credentials
can be used for authentication purposes. An enhanced security model provides a policy-driven foundation for
securing Web services. WSE also supports the ability to establish a trust-issuing service for retrieval and
validation of security tokens, as well as the ability to establish more efficient long-running secure
communication via secure conversations.
Microsoft has also included Microsoft Solutions Framework (MSF) a highly customizable, scalable, fully
integrated set of software development processes with its Visual Studio Foundation Server. Visual Studio Team
Foundation Server is a set of client/server tools for team projects. It provides a seamless experience with Visual
Studio 2005 Team System for process automation and guidance within the software development life cycle
(SDLC). It also allows for Version control, work item tracking and reporting.
It is easy to see why .NET is one of the predominant development frameworks used today. Not only does it
support simplified development but it streamlines the entire life cycle of the enterprise SOA solution.

94
The Complete Reference To Professional SOA with Visual Studio 2005

Using Visual Studio 2005 to create a Web service


For now, we will look at building a very simple Web service.
Having launched Visual Studio 2005, select File menu ~TRA New ~TRA Web Site. We will be presented
with the New Web Site dialog box, as shown in Figure 3-8.

Figure 3-8. New Project Template.

Select Language as Visual C# or Visual Basic, Location as HTTP and select the ASP.NET Web Service
template as shown in the figure. We could select Visual J# and also be able to create an ASP.NET Web service.
For the purpose of this book we will only be concentrating on Visual C# and VB .NET.
In the Location text box (Figure 3-8) change the address for the Web service to
http://localhost/SOAWebService/CSSimpleWebService. When we click OK, the Web service will be created for us.
In Visual Studio 2005 we’re not forced to install Internet Information Service (IIS) as had been the case with
Visual Studio 2003. This allows us to even launch web projects in the file system through Visual Studio 2005’s
integrated web server called ASP.NET Development Server.
In this case we have selected Visual C# the following code would have been generated for us by Visual
Studio 2005.

Listing 3-1. Visual C#

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
public Service () {

//Uncomment the following line if using designed components

95
The Complete Reference To Professional SOA with Visual Studio 2005

//InitializeComponent();
}

[WebMethod]
public string HelloWorld() {
return "Hello World";
}
}
If we had selected Visual Basic then the following code would be generated.

Listing 3-2. Visual Basic

Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols

<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class Service
Inherits System.Web.Services.WebService

<WebMethod()> _
Public Function HelloWorld() As String
Return "Hello World"
End Function
End Class
Within the generated code we can see that Visual Studio has generated a public method decorated with the
WebMethod attribute. A WebMethod is the function that the Web service exposes to our consumers. In this case,
it’s a pretty dull method that takes no parameters and returns the string “Hello World” to the caller. The
[WebMethod] or <WebMethod()> label is called an attribute and it is used by the compiler to help generate the
details for the WSDL document. That’s the job of an attribute to give special instructions to the compiler about
how to handle the code.
Many developers prefer to start with a WSDL description of the service and move into the code from there,
instead of the other way around as this example shows. Either way is good, but Visual Studio leads us in the
direction of building code first and foremost, and auto-generating WSDL from our Web services code.
Let’s try something a little more interesting. We will pass in a parameter string.

Listing 3-3. Visual C#

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
public Service () {

//Uncomment the following line if using designed components


//InitializeComponent();

96
The Complete Reference To Professional SOA with Visual Studio 2005

[WebMethod]
public string HelloWorld(string param1) {
return "Hello " + param1;
}
}

Listing 3-4. Visual Basic

Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols

<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class Service
Inherits System.Web.Services.WebService

<WebMethod()> _
Public Function HelloWorld(ByVal param1 As String) As String
Return "Hello " & param1
End Function
End Class
The method will now accept a parameter of type String, which it uses to build the output.
If we run this Web service, Visual Studio will construct a test harness for us. A test harness is an IDE-
supplied set of pages or applications that are used to test our applications. So we don’t need to build these pages
ourselves. We can see the test harness in action in figure 3-11.
We can run the Web service by selecting Debug ~TRA Start Debugging
Visual Studio will detect that we have not enabled debugging and will prompt us if we wish to enable
debugging.
In this case we will select the Modify Web.config file to enable debugging selection and click Ok. As show
in Figure 3-9.

Figure 3-9. Visual studio auto-prompting debugging options

97
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 3-10. Auto-generated ASMX page.

Clicking the HelloWorld hyperlink will take us to a form generated by the test harness based on the method
signatures. In this case, the method takes a single string, so the form will have one text box. This can be seen in
Figure 3-11.

Figure 3-11. Auto-generated WebMethod test harness.

98
The Complete Reference To Professional SOA with Visual Studio 2005

If we enter our name in the text box and click the Invoke button, the Web service will be called, passing
whatever we typed as the parameter to the HelloWorld method. The results may be seen in Figure 3-12 if we
enter the name Kim.

Figure 3-12. SOAP from the WebMethod result

Another thing that Visual Studio 2005 does for us is that it generates the WSDL document that describes our
Web services. If we look back to Figure 3-10, we will see a hyperlink to the Service Description at the top of the
page. Clicking this will navigate us to the page containing the WSDL, which of course will also indicate to us
the URL that we can use to consume the WSDL. We can see an example of this WSDL in Figure 3-13.

Figure 3-13. Shows the WSDL document generated by Visual Studio for the Hello World web method

We can see that the URL for the WSDL is the URL for the Web service with the ?WSDL appended to it. For
example, Service.asmx?wsdl.

99
The Complete Reference To Professional SOA with Visual Studio 2005

Using Visual Studio 2005 to Consume a Web Service


Now that we have built our Web service, the next thing to do is consume it in an application. It doesn’t have to
be an application. A Web service can be consumed by anything that talks SOAP, even another Web service. For
simplicity we will create a windows application using Visual Studio’s Windows Forms application.
First, we need to create the application. We do this by selecting the File Menu ~TRA New ~TRA Project
dialog. This time, select Windows Application as the Template within the C# or Visual Basic (see Figure 3-14).
We are doing this because we are creating a Windows application that runs on our PC as an executable that will
access the web service for information.

Figure 3-14. New project template for windows application. (please note that Visual Studio 2005 comes with a range of
editions catering to different roles in development. The screen shot that you see may differ slightly depending on the edition
that you use.)

Once the project has generated the windows form for us. We can drag and drop a button and label onto the
form (see Figure 3-15).

100
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 3-15. Windows form designer allows drag and drop to add controls.

Now we can establish contact with the web service by adding a reference to the web service we created earlier.

Figure 3-16. Solution explorer


Simply right mouse click on the Project within the Solution Explorer then select “Add Web Reference”.

101
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 3-17. Add a web service reference to the project.

Enter the location of the web service from the HelloWorld Web service application that we had created
earlier and click the go button. Click the Add Reference name. Note that the web service is added under the web
reference name of localhost.
On the winform Double clicking on the button will bring us to the code behind the form.

Listing 3-5. Visual C#

private void button1_Click(object sender, EventArgs e)


{
localhost.Service helloworld = new WinAppService.localhost.Service();
label1.Text = helloworld.HelloWorld("Kim");
}

Listing 3-6. Visual Basic

Private Sub Button1_Click(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles Button1.Click
Dim helloworld As New localhost.Service
Label1.Text = helloworld.HelloWorld("Kim")
End Sub

Now when that we had entered the above code into the code behind we can compile and run the code. We will see the result of the
execution in Figure 3-17.

102
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 3-18. Windows application result from invoking the Web service.

From the example above we can easily see why developing with .NET is so simple. Visual Studio helps us
take care of all the subtleties so that we don’t need to touch them. The job of a developer is simplified. .NET
Framework takes care of the web service requests as well as response by marshalling of SOAP information to
and from the wire. Visual Studio also generates a Proxy class from the information obtained from the WSDL of
the web service. This allows the developer to access development information from the Web service. Developers
can use the proxy class created by Visual Studio to map to the Web service that they’re currently accessing. To
aid the developer’s development effort all functions accessible via the Web service can be accessed through
Visual Studio’s intellisense.

Summary
Through this chapter we have focused on various areas in the domain of business adaptations of SOA. These are:
Role of SOA within the organization
Opening our private infrastructure

* Roadmaps for SOA


* Measuring a SOA
* SOA driven project development using MSF

Lastly we looked at the ease of creating Web service using .NET and Visual Studio 2005.

103
The Complete Reference To Professional SOA with Visual Studio 2005

Part 2 Using .NET Web Service


2.0 with Visual Studio 2005
In Part 1 of this book we learned about the core concept of SOA which was its ability to
provide agility and better ROI to the enterprise architecture. We will now cover the
implementation of a SOA through the use of .NET 2.0 Web Service and Visual Studio 2005.

Chapter 4 Introducing .NET 2.0


The reality is that developing software today is inherently difficult. Enterprise developers can no longer generate
a script and deploy it with a proprietary db on a floppy disk. Today’s enterprise scale applications can have many
layers of services and quite often data is distributed throughout the enterprise. These projects require a lot more
development effort and demand a high level of standards compared to the past.
Today enterprise-scale software has significantly more moving pieces than it did 10 to 15 years ago. Web-
based applications such as XML Web services make systems more interoperable and extensible but this is only
from an architect, stakeholder and user point of view. However as a developer plugging the various elements
together and ensuring that they’re working efficiently together can be extremely challenging and daunting.
Microsoft took a great deal of effort to study the way that software shops and teams successfully, and
sometimes unsuccessfully, developed software. This knowledge and experience is then poured into the earlier
version of ASP.NET, which contains the culmination of web technologies. ASP.NET 2.0 is a major upgrade to
the platform, even though no new programming paradigm has been introduced. ASP.NET 2.0 is a fundamental
milestone in the Microsoft Web development roadmap.
ASP.NET 2.0 is currently the most advanced, feature-rich and powerful platform for building distributed
applications. ASP.NET 2.0 simplifies development tasks and presents itself as a paradise for developers.
ASP.NET 2.0 is complemented through Microsoft’s Visual Studio 2005. Unlike its earlier version Visual Studio
.NET 2003 it is no longer just a slick IDE for development. Visual Studio 2005 contains a powerful suite of
rapid application development (RAD) tools that integrates the enterprise team with the entire solution across the
life cycle of the project. The Visual Studio 2005 IDE has been considerably enhanced in the areas of exception
assistant, code snippets, and visualizers. The emphasis is on providing useful information that improved the
quality of development of developers and their productivity.
Visual Studio 2005 provides an edge to development. It aims to increase team’s productivity by reducing the
complexity of service-oriented solutions and increase the team’s collaboration by integrating all required tools
within the IDE. Its aim is to increase the predictability of a successful project.

.NET Framework
The .NET Framework was developed to work with the Windows operating system. It is an integral part of
Windows components and will play a further role with the release of the Vista operating system. The framework
supports building and running various types of Windows applications such as console applications, Winform
applications as well as support for Web based applications such as Webforms and also support for the

104
The Complete Reference To Professional SOA with Visual Studio 2005

development and running of the next generation of XML Web service developed for .NET. The .NET
Framework aims to:
* To ensure a consistent object-oriented programming environment.

* To remove software deployment and version conflicts


* To ensure a secure execution environment by promoting safe and secure code execution
* To improve the performance of code execution

* To ensure a consistent development experience across different type of applications, such as Windows-based
applications and Web-based applications.

* To provide a consistent framework where developer are free to choose their favorite programming language.

The heart of .NET Framework consists of two main components: the Common Language Runtime and the
.NET Framework class libraries. The Common Language Runtime is fundamental principle of runtime. It works
as the agent that manages the execution of code while also governs the type safety and other code securities.
Code that is managed by the .NET Framework runtime is known as managed code while code running outside of
the runtime management is known as unmanaged code. The other main component of the .NET Framework is
the class library. The class library is an object oriented collection of reusable types that we can use to develop
different types of .NET applications. These .NET applications range from traditional command-line applications
to graphical user interface (GUI) applications to Web based applications such as ASP.NET Web form and XML
Web service.
The .NET Runtime was designed with performance in mind. Managed code is never interpreted. A feature
called just-in-time(JIT) compiling enables all managed code to run in native machine language of the system on
which it is executing. The memory manager also helps to remove possible memory fragments to increase
memory locality-of-reference to further improve performance.
The .NET Framework provides several runtime hosts which allow hosting of managed and unmanaged
components. These hosts can be Microsoft SQL Server and Internet Information Services (IIS). The host loads
the common language runtime into their process and handle the managed code execution. By doing so the
runtime can access both managed and unmanaged features of the components. This infrastructure allows
developers to develop applications with managed code whilst still enjoying the superior performance of the
.NET Runtime.

105
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 4-1 illustrates .NET Framework in context

Figure 4-1 Demonstrates the separation of managed applications and unmanaged applications. Managed applications
are managed by the .NET Framework’s runtime. Whilst IIS is an unmanaged application which provides a hosting
environment for the ASP.NET Runtime. The ASP.NET Runtime time manages the execution of applications such as
ASP.NET web applications as well as XML Web services.

Features of the Common Language Runtime


In the .NET Framework the Common Language Runtime (CLR) looks after the managed code it manages
features such as compilation, code execution, manages memory, thread execution, code safety verification, and
other system services.
In managed components we can specify a number of varying degrees of trusts. This trust for example
depends on the origin of the component for example if they’re from Internet, from a network or a local machine.
This mean that managed components have more control in terms of registry access operations, file access
operations, and other functions that are deemed as sensitive even if code is launched from the same application
different security levels can be configured.
The .NET runtime also implements a verification infrastructure for type and code. This is called the
Common Type System (CTS). CTS is what allows other third-party language compilers to work with .NET
Framework. This is because CTS ensures that all managed code are self describing this means managed code can
be consumed by other managed types and instances whilst the CLR maintains security and type safety.
The .NET managed environment addresses many of the common issues today in software development. For
example the runtime automatically takes care of object management. The garbage collection automatically
cycles through memory and remove objects that are no longer used. This resolves two common issues that is
memory leak and invalid memory reference.
The runtime also fast tracks development through CTS by allowing third party compilers to compile into
.NET managed code. This means that developers can develop in their favorite language and yet still take

106
The Complete Reference To Professional SOA with Visual Studio 2005

advantage of the full features of the .NET Framework. This greatly eases the migration process for developing
new and existing applications.
The runtime also maintains interoperability with legacy applications through the support for the use of
unmanaged code components such as COM and DLLs. The runtime is also optimized for enhanced performance.
Unlike script based languages the managed code is never interpreted by using features like Just-In-Time (JIT) all
managed code are compiled into native machine language for that particular system on which it is execution.
This greatly improves the performance and execution of applications. While memory management reduces
fragmentation to increase the locality of reference to further increase performance.
Lastly the .NET runtime is now integrated to other high performance applications such as Microsoft® SQL
Server™ and Internet Information Services (IIS). We can now develop and embed SQL stored procedures, SQL
data types, SQL Triggers in .NET code. This is very exciting.

Managed Development
In .NET managed applications are implemented through the .NET runtime hosts. In development such as
applications for ASP.NET the unmanaged host in our case the Internet Information Services (IIS) hosts the
common language runtime, which allows us to manage code. This is a proven model which give us all the
capabilities of the common language runtime and class library. This also allows us to gain the performance and
scalability benefit of utilizing the host server.
Figure 4-2 shows a basic network schema with managed code running in different server environments.
Servers such as IIS and SQL Server can perform standard operations while our application logic executes
through the managed code.

Figure 4-2 Managed code running on different environments

Web Forms together with XML Web services both use ASP.NET and IIS to host its deployed applications.
ASP.NET is more than just a managed runtime host. ASP.NET is a complete architecture from which developers
can build web based applications and Internet based distributed applications such as XML Web services.
XML Web services is a type of distributed server side application. In some ways it is similar to a web sites
in terms of requiring to be hosted on IIS and developing using the same managed environment. However it
differs in that XML web service do not require user interfaces they are essentially much like COM components
or simply a DLL providing functionalities to all that required its services. Despite the requirement to be hosted
on IIS XML Web services do not target browsers such as Internet Explorer and Netscape. Instead it offers its
service to the public through a description document called Web Server Description Language (WSDL) which
details all the functionalities provided by the web service. XML Web service technology is rapidly evolving
because of its distributed nature and its separation between interface and implementation it is fast becoming the
choice of many who implement SOA.

107
The Complete Reference To Professional SOA with Visual Studio 2005

The .NET Framework supports the development of XML Web services with a collection of classes and
tools. The .NET Framework has internal support for Simple Object Access Protocol (SOAP) a remote procedure
protocol and Extensible Markup Language (XML) the framework also helps to generate the WSDL document
which describes the Web service. All of this greatly reduces the workload of a developer. The .NET Framework
with internal support using these standards to help promote interoperability with applications with even non-
Microsoft solutions.
The .NET Framework has built-in WSDL tool so it can parse the WSDL document of another Web service
and produce C# or Visual Basic source code. This is called a Web service proxy. The proxy can then be used to
invoke the functions on the Web service.
If we develop and publish our own XML Web service, the .NET Framework provides a set of classes that
conform to all the underlying communication standards, such as SOAP, WSDL, and XML. Using those classes
enables us to focus on the logic of our service, without concerning ourselves with the communications
infrastructure required by distributed software development.
The best thing is unlike other script languages the XML Web service will be able to utilize the managed
environment the code will be compiled to native machine language for performance.

.NET Framework 2.0


The .NET Framework 2.0 is the infrastructure for building applications using .NET. The .NET Framework
provides a consistent object-oriented programming model that we can use to build all types of applications. The
approach for creating various applications such as Windows-based applications and XML Web services is the
same. To create a .NET application, we create a class and define the functionality of the application in terms of
properties, events, and methods of the class. Even for Web applications, the code that controls the behavior of
the Web page is encapsulated within a class. In addition, classes support object-oriented features such as
inheritance, encapsulation, and polymorphism. Therefore, classes are fundamental to programming in the .NET
environment. We can create classes in any language supported by the .NET Framework. A class written in one
language is reusable by classes written in other languages. We can also inherit classes across language
boundaries because the .NET Framework allows language interoperability and supports cross-language
inheritance.
The .NET Framework 2.0 provides four CLS-compliant languages: Microsoft Visual Basic Microsoft Visual
C#, Microsoft Visual C++ .NET, and Microsoft Visual J# .NET. Visual C# was ratified by ECMA as an
international standard on December 13, 2001. The compilers of these languages generate an intermediate code,
called Microsoft Intermediate Language (MSIL), which makes programs written in the .NET languages
interoperable. Therefore, in the .NET Framework, we can use any language to create applications, and these
applications can interoperate with the applications written by others in different languages.

Visual Studio 2005 Team Roles

108
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 4-3: Visual Studio Team System overview

Microsoft has mapped the roles of individual members of development team into Visual Studio 2005 Team
System to provide more specialized functionalities specific to their role. Team System’s value is realized in
teams that include project manager, architect, developer, and tester roles. These four roles are in turn mapped to:

Visual Studio 2005 Team Edition for Software Architects


This edition is designed for both the infrastructure and application architecture roles. It includes visual designers,
referred to as the distributed application designers or service-oriented architecture (SOA) designers. The
architect can create diagrams to represent the logical datacenter, the application, application systems, and the
deployment of the application. These designers follow a simple drag, drop, and connect heuristic that has long
been popular with Visual Studio. More than just pretty shapes, the diagrams have intelligence and metadata that
can be validated against well-known and custom defined constraints, and then turned into code with a quick
click. While similarly code within a project can be generated into diagrams just as easily.

Visual Studio 2005 Team Edition for Software Developers


This is the specialized edition for developers or programmers on the team. This will be the most common of the
Team System role-based editions. In addition to all of the base Visual Studio 2005 professional features,

109
The Complete Reference To Professional SOA with Visual Studio 2005

developers will get the static code analyzer (much like FxCop), unit testing (like NUnit), code coverage (like
NCover), and code profiler. Some of the features share with the Visual Studio 2005 Team Edition for Software
Testers. Figure 4-3. It is expected that as a developer some basic testing would be done before the component is
passed onto the software testers.

Visual Studio 2005 Team Edition for Software Testers


This edition provides coverage, quality, and load-testing facilities access to developers and testers to thoroughly
test their solution before deployment. The Team Edition for Testers includes load Web testing (like Application
Center Test), Unit Testing, Code Coverage, as well as test-case management tools for managing all the tests and
running and monitoring them from a centralized area. The ability to plug in whatever manual tests we might
have is also supported in Team Edition for Testers.

Visual Studio 2005 Team Foundation Server


This edition of Visual Studio will provide many back-end databases and Web services to enable the team to
collaborate, by sharing work items, source code, builds and other artifacts. If we intend to run Team system for a
team, as it is advertised, we will need this product to connect all our team members together. Team Foundation
Server is easily integrated into Visual Studio and is more than just an “edition” of Visual Studio 2005 Team
System. It’s the engine behind our software development life cycle. It includes a standalone client called Team
Explorer. This client is essentially a lightweight edition of Visual Studio 2005 that offers an alternate way of
creating and managing work items i.e. Checking in documentation, manage images for Web project and so on.

Visual Studio 2005 Team Suite


For the team member who plays more than one role, or for the consultant who plays all the roles, there’s the
Team Suite. Microsoft has wrapped up all three roles based editions (architect, developer, and tester) into a
single edition for simplicity.

Visual Studio 2005 Editions


Team System is not part of all editions of Visual Studio. For novices, hobbyists, students and professional
developers, there are express, standard, and professional editions of Visual Studio.

Visual Studio 2005 Express Editions


The Visual Studio 2005 Express Editions were made for hobbyists, students, novices and enthusiasts in general.
You can select from Microsoft Visual C# Express, Visual Basic express, Visual C++, Visual J#, and Web
Developer Express. Express editions are made available to almost anyone who wants them so that developers
will start using Visual Studio 2005. The Express Edition is Free and is downloadable from Microsoft.

Visual Studio 2005 Standard Edition


Visual Studio 2005 Standard Edition is similar to standard editions of the previous versions of Visual Studio.
This is the entry level for anyone who is serious about developing applications. The intended audience includes
Web Professionals, Visual Basic 6.0 developers, and part-time developers who want to build standalone
applications in Visual Basic 2005 or C#.

Visual Studio 2005 Professional Edition

110
The Complete Reference To Professional SOA with Visual Studio 2005

Similar to the professional editions of the previous versions of Visual Studio, this is the edition for serious
development in Visual Studio. This edition is for consultants, solo professionals, and those who work in small
teams for which team System may be more than they need. The professional edition also differs from the
standard edition in that it has all the features required to build distributed applications.

The Visual Studio IDE


Microsoft’s Visual Studio 2005 IDE is one of the most advanced IDE in the industry today. For developers who
had used the previous version, Visual Studio .NET 2003 it is an obvious choice to use Visual Studio 2005. It
offers valuable benefits in terms of being a Rapid Application Development (RAD) tool.

* Visual Studio is WYSIWYG developing application whether it is for windows or web is extremely simple.
Simply drag and drop the required controls to create an executable application. The code can be modified
easily to allow custom functionalities.

* Visual Studio offers Intellisense to aid coding, Intellisense helps to format your code as you type, indenting and
automatic code coloring to distinguish different elements within your class. This makes your code much more
easier to read and also debug. Intellisense also provides code snippets that provide templates for simplifying
common coding tasks

* Visual Studio helps to auto-generates our code. For example when we need to access a Web service Visual
Studio takes care of creating the proxy class for us. The code generated is a strongly typed proxy class which
provides us with all the details that we need to develop.
* Visual Studio takes care of these basic tasks to provide us with an intuitive and efficient development
environment.

* Visual Studio comes with an integrated web server. Usually to host an ASP.NET application such as a Web
service, we need a web server software like IIS installed. The web server waits for web requests and serves the
appropriate pages. Setting up IIS is not difficult but it may be inconvenient. Thanks to the integrated
development web server in Visual Studio, we can run a website directly from the design environment.
* Visual Studio supports multiple languages. This allows us to effectively code in our favorite language or
languages of choice using the same development environment. Visual Studio 2005 adds the ability to put web
pages coded in C# in the same project as web pages written in Visual Basic. The only limitation is that we can’t
use more than one language in the same web page (which will create obvious confusion).
* Visual Studio is geared with many features to allow us to get our work done faster. Convenience features allow
users to develop applications at a much faster rate.
* Visual Studio comes with a suite of debugging tools and utilities. We can execute code one line at a time, set
intelligent breakpoints based on certain conditions, and view current in-memory information at any time.

Visual Studio IDE has a wealth of features that allow us to better project manage, integrate source code and has
rich extensibility features.

Web Service Template


When the IDE first loads, it shows an initial start page. The start page contains recent projects that we have
worked on as well as a MSDN section which shows the latest news. To start using the Web service template,
choose File -> New -> Web Site to create a new ASP.NET Web Service application. Visual Studio will then
show the New Web Site dialog box see Figure 4-4.

111
The Complete Reference To Professional SOA with Visual Studio 2005

TIP: We don’t use Visual Studio’s File -> New Project command. That is because web applications are regarded as separate to traditional
windows based applications such as WinForm and Console application projects.

Figure 4-4 New Project

Since we will be developing for XML Web service we will be predominantly using the New Web Site to create
ASP.NET Web service. The New Web Site window allows us to specify the templates, location of the project
and as well as the language we would like to use.

Template: In the New Web Site we can select several Templates. We can select:

* ASP.NET Web Site


* ASP.NET Web Service
* Personal Web Site Starter Kit

* Empty Web Site

* ASP.NET Crystal Reports Web Site

We will be working with Web based applications which include both ASP.NET Web Site and ASP.NET Web
Service. So determining what we type of project we will be creating first is essential to selecting the right
templates. The Web Site and Web Service applications are actually compiled and executed in the same way. We
can also add Web pages to a Web service application and vice versa. The only difference is that by selecting a
template we are asking Visual Studio to create specific pre-defined files for us. In a Web service application we
will start with a sample service whilst in Web Site application we start with a sample Web page.

Location: The location section determines where we will be storing the working files. Previously in Visual
Studio 2003 we could only specify HTTP locations this meant that we could only save files to a Web service
with IIS. However in Visual Studio 2005, we can take advantage of a number of modes. We can now save our
working files to the File System or store the files to a network address. We can also save our project to a FTP or

112
The Complete Reference To Professional SOA with Visual Studio 2005

a HTTP location. The best part is that Visual Studio 2005 now comes with an integrated Web server called
ASP.NET Development Server. This server is launched when our Web based projects are stored on the file
system. However if we want to work on a live remote website we should use the Remote Site option, though care
should be taken when working on a production server as changes can be irreversible.
Rather than typing the location details in we can alternatively use the browse button which will show a
Choose Location dialog window. There are four types of locations that we can select here File System, Local IIS,
FTP Site.

Language: We have the option of selecting Visual Basic, Visual C# and Visual J# (In the following example we
will be using Visual C#)

Figure 4-5. File System

File System: The file system is preferred by most developers because its easily accessible we can save to
any particular location we like figure 4-5. In Visual Studio 2005 when execution occurs an Integrated Web server
called ASP.NET Development Server will be launched. This environment is essentially what hosts the Web
application during execution. If we want to create a new directory for our application, just click the Create New
Folder icon above the top right corner of the directory tree. We can also specify a new directory to create by
adding a new directory name to the end of our path.

113
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 4-6. Local IIS

Local IIS : Selecting the Local IIS option will allow us to browse through the Virtual Directory lists made
available through the IIS figure 4-6. We can also create a new virtual directory by using the Create New Web
application icon on the top right hand corner of the dialog window.

Figure 4-7. FTP Site

FTP Site : By selecting FTP Site we are essentially connecting to a FTP server from where our working files
will be stored figure 4-7. To do this we need to specify the server details, credential information as well as the
directory we want to store the files in.

114
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 4-8. Remote Web Server

Remote Web Server: Selecting the Remote Site means that we will be storing the files on a remote IIS
server with FrontPage Extension installed figure 4-8. We will be prompted for username and password
information upon successful connection to the site.

Language: The language option allows us to select between Visual Basic, Visual C# and Visual J#. The
language that we choose will become the default language for the project. We can explicitly add Visual Basic
web pages to a J# website, and vice versa. And if the project is in a solution we can also add other projects that is
using different language to our project.
Once we have completed our selection simply click Open Visual Studio returns us to the Create Web Site
dialog box. Click OK, and Visual Studio will create the new web service application. The new Web Service
starts with the file called Service.asmx.

115
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 4-9 A newly generated Web Service from the ASP.NET Web Service template.

Visual Studio 2005 Projectless Development


In the past with Visual Studio .NET 2003 each web application must be contained in their own particular web
project. Web Service must be in a Web Service project while ASP.NET Web Site must be in a Web Site project.
In Visual Studio 2005 this limitation is removed web applications no longer need to be contained within a
project for what they do. In Visual Studio 2005 web applications no longer contain files, such as .csproj project
files and .sln solution files. Instead, every file in our web folder automatically is considered part of the web
application.
Now when we create a web application, Visual Studio stores project information in a user-specific directory,
like c:\Documents and Settings\[UserName]\Visual Studio 2005\Projects\[ProjectName]. This is because even
though Visual Studio no longer creates a project file and a solution file (.csproj, .vbproj, .sln) it must still retain
some project information. For example if we have added more class library projects to our current web project or
if we have configured special build modes. Those details will be stored in the solution file under the user
directory so that on Visual Studio startup the project will be displayed under Recent Projects section.

Migrating to Visual Studio 2005 Project


Visual Studio has traditionally come with an upgrade utility that allowed developers to migrate their projects
created from the previous version of Visual Studio 2005. We can start the migration process simply by opening
the project in Visual Studio 2005 Visual Studio 2005. When we do, Visual Studio begins the Conversion
Wizard. The Conversion Wizard will prompt us to choose whether to create a backup and, if so, where it should
be placed Figure 4-10. If this is our only copy of the application, a backup is a good idea in case some aspects of
our application can not be converted successfully.

116
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 4-10 Project Conversion Wizard

One the wizard has completed the process we select Finish to begin the conversion process,. Any errors and
warnings are added to a conversion log, which we can display when the conversion is complete. In general we
will always receive one warning about IIS reference. Figure 4-11.
A quick look at the ConversionReport.txt shows the following:

Listing 4-1. Conversion Report

This report shows the steps taken to convert your Web application from ASP.NET 1.1 to ASP.NET 2.0.
There may be some unresolved conversion issues you will need to manually fix.
For more information, please refer to http://go.microsoft.com/fwlink/?LinkId=46995 or search for the help topic "Converting from Visual
Studio .NET 2002 or 2003".
Conversion Started on project file WebService1.csproj at March 14 2006, 13:17:48.

=========================ERRORS===================

=========================WARNINGS=================
Warning: This web project was converted as a file-based web application. If your site contained any IIS meta-information, e.g. sub-folders
marked as virtual directories, it is recommended that you close this web site and re-open it using the Open Web Site command and
selecting the Local IIS tab.

=========================COMMENTS=================
Web.Config: Added 'xhtmlConformance' attribute.
Removed attribute Codebehind from file Global.asax.
Added folder App_Code.
Moved file Global.asax.cs to the App_Code\ directory.
Moved file Service1.asmx.cs to the App_Code\ directory.
Moved file AssemblyInfo.cs to the App_Code\ directory.
Changed HTML validation schema for all projects to 'Internet Explorer 6.0'.

117
The Complete Reference To Professional SOA with Visual Studio 2005

Removed file Bin\WebService1.dll.


Removed file Bin\WebService1.pdb.
Removed file WebService1.csproj.
Removed file WebService1.csproj.webinfo.
Project WebService1.csproj has been converted successfully at March 14 2006, 13:17:56.

Figure 4-11. Converted project

Visual Studio IDE


Microsoft’s Visual Studio is one of the most advanced IDE in the world. Visual Studio is smart enough to help
developers through the daily repetitive tasks, while at the same time ensuring the quality of the overall project.

118
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 4-12. Visual Studio IDE

Table 4-1 Visual Studio Windows

Windows Description

Solution Explorer Lists all of the files that are used in the project directory.

Toolbox Shows built-in controls and any third-party controls or custom controls that we have
built ourselves and added to the Toolbox. These controls can be used to build user
interface quickly or to implement certain actions such as retrieving data from a
database. To use these control simply drag and drop or double click. Controls can be
written in any language and used in any language.

Server Explorer Server Explorer provide details on Servers that are accessible these could include
database connections to SQL Server or to Crystal Reports Services, Event Logs,
Message Queues, Managed Classes, other Services on the System and Performance
Counters. From the Server Explorer we can have direct connection to the SQL
Database allowing to perform live queries and test commands.

Properties Allows us to configure the currently selected element, whether it’s a file in the
Solution Explorer or a control on the design surface of a web form. To access the
properties window we can right click on any object on the design surface and then
select properties.

119
The Complete Reference To Professional SOA with Visual Studio 2005

Error List During development Visual Studio helps us to keep track of potential issues that may
arise. This occurs while we develop or after we have built an application. These issues
are reported in the Error List window.

Task List Task List can list comments that are predefined through aliases through out the code.
For example if we wanted to leave a comment about a section of code that we’re still
yet to implement we can use the //TODO: <comment> syntax to leave a message.
This message will then be populated under Task List.

Document The document window or otherwise known as the source code window allow us to
modify the actual code behind a web based application. The document window can
also support file types, such as static HTML and XML files.

Class View The Class View window organizes a code in a class into a logical tree with methods,
properties and events represented in different nodes.

Solution Explorer

Figure 4-13. Solution Explorer

The Solution Explorer is very much like a file explorer where we can explore all the files contained with a
project figure 4-13 above. It is also very versatile because we can add files outside of a project into the project.
The solution explorer also comes with a number of tools for specific file types. We can view the difference in
options for different file extensions by right clicking on the file.

Table 4-2 Typical Web Service File Types

File Description

Ends with .asmx All files represented with .asmx are used as ASP.NET Web Services. When a
request is received to a .asmx file the request is passed to the .NET Runtime where
it is handled. Depending on the request for example ?WSDL a request for a WSDL
document ?DISCO for discovery files a response is generated. A direct request to
the .asmx from a browser could result in the generation of a web based test page
which we can use to invoke the Web service.

120
The Complete Reference To Professional SOA with Visual Studio 2005

web.config This is the XML-based configuration file used for our ASP.NET application. It
includes settings for customizing security, state management, memory
management, and much more. Visual Studio adds a web.config file when we need
it. (For example, it adds a web.config file that supports debugging if we attempt to
run our web application.) When we first create a website, we don’t have a
web.config file. We can nest one web.config in each of the directory the web.config
within the directory will overwrite settings of the higher level web.config.
Generally only one web.config is maintained for a project for ease maintenance.

global.asax The global.asax file is used to define global events that occur in an application. This
could be when an error from a specific web application occurs in this case a custom
error handler will then be invoked to process the error.

Ends with .vb These are files that contain Visual Basic 2005 code classes.

Ends with .cs These are files that contain C# code classes.

Within a project we can include other resources that are not ASP.NET file types. These can be XML, XSLT
and XSD file types that are used by our Web service application. Visual Studio can also distinguish between
different file types there are associated tools that help us to modify specific file types. We can view these tools
by simply right click on the specific files. For example right mouse click on a XML file will give us the option of
viewing the file in a browser.
The solution explorer is incredibly handy in development it allows us to add predefined file types into the
project figure 4-14 below. To add a new item to a project simply right click on the solution explorer and select
“Add New Item”. We can add different types of files these range from HTML Page to DataSet to Class files to
XML Schemas.

Figure 4-14. New Items

121
The Complete Reference To Professional SOA with Visual Studio 2005

To add an existing item simply right click and select “Add Existing Item” from which we can browse for a
particular file that we want to add to the project. We also have the ability to drag and drop files in and out of the
solution explorer.
One of the features of Solution Explorer is that it allows us to exclude certain items from the project. This
means that even though the specific item exist in the project it is not compiled and evaluated. This is handy when
we’re working on a piece of code that we know will cause errors. We can simply exclude that specific CS or VB
file from the project temporally to compile the project and see if the rest of the code is working.
Visual Studio also helps us to keep track of files modified. If a file is changed outside of Visual Studio,
Visual Studio will prompt us to either refresh or keep our changes. This is important when we need to modify a
particular file in the solution outside of Visual Studio using possibly a third-party tool.

Document Window
The document window is what allows us to modify changes to the design of an application. Not all applications
have a Graphical User Interface (GUI) for example windows service, console applications and XML Web
service. However each file type has a default editor assigned to it for example an ASPX file would open the
Visual Studio HTML editor which can be used to modify HTML code and as well as view the visual
representation of the HTML. We can view or change the default editor by selecting the file in solution explorer
and then right click on the file to bring up the context menu. For example selecting a Web service .asmx file and
then selecting the “Open With” option will bring up an Open With dialog window figure 4-15 below.

Figure 4-15. Open With

The default editor used by that file type will be labeled with a (Default) after the editor name. Also
depending on the applications that we have installed we may also see additional editors appearing in the Open
With dialog window.

Toolbox
The Toolbox window works in conjunction with the designer window. The toolbox stores a number of controls.
These controls are either internal to the .NET Framework or they can be custom controls that we have developed
and included onto the toolbox. Simply by selecting the tool and drag and drop onto the design surface will create
the tool on the designer surface. The content of the Toolbox depends on the context of the current designer
window that we are working in as well as the current project type.

122
The Complete Reference To Professional SOA with Visual Studio 2005

In the toolbox we can add/remove tools as well as add tabs and remove tabs. We can also drag and drop
tools from one tag group to another.

Error List
The Error List manages the error and the warning information that’s generated by Visual Studio during
development. Each entry in the Error List contains a description column, a file column to show which file the
error is located in, a line column to shown which line the error is on, a code column is also shown to show the
location of the error, lastly a project column is also shown incase we have more than one project in the solution.
We can select whether we want to see each of the column by right click on the Error List window Figure 4-16
below.

Figure 4-16. Columns

To go to the offending error we can simply double click on the error message. This will take us straight there.
The error list window also has a number of options we can select on the columns to view the column of
interest. We can also sort the error list by right click on the Error List and sorting either by category, default
order, description, file, line, column or project.

Figure 4-17. Sort by

With the default Visual Studio settings, the Error List appears automatically whenever we build a project that has
errors. In the example below we will intentionally leave an error by leaving the hello world message unclosed
with quote see Figure 4-18.

Listing 4-1. Desmonstration of error in Visual C#

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService

123
The Complete Reference To Professional SOA with Visual Studio 2005

{
public () {

//Uncomment the following line if using designed components


//InitializeComponent();
}

[WebMethod]
public string HelloWorld() {
return "Hello World
}

Figure 4-18. Error List

Task List
There are two lists of tasks that exists these are User Tasks and Comments. User tasks are entries that we have
added specifically to the list. These are things that we want to do but have not quite started. To create a User
Task simply click the icon next to the drop down list in the Task List window. There are three things we can
assign to a User Task item we can specify the priority of the item, add a description to the item, and select to
indicate whether the item has been complete Figure 4-19.

124
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 4-19. User Task List

The comment list of the Task List allow us to add comments as we program. To do this we can simply add a
//TODO <comment> alias which is a comment but whatever is after the TODO will be displayed under the
comments list of the Task List. For example
// TODO: Debug this section
Because our comment uses the alias TODO, Visual Studio recognizes it and automatically adds it to the
Task List figure 4-20 below. To remove the comment from the task list simply remove the //TODO: <comment>
from the code. Visual Studio will automatically update the Task List.

Figure 4-20 Task List with TODO comment

Figure 4-21. Task List

125
The Complete Reference To Professional SOA with Visual Studio 2005

By default Visual Studio comes with several aliases for Task List comments. There is Hack, TODO,
UNDONE and UnresolvedmergeConflict. However we can always add more. Simply enter a name under the
Tokens section and select Add button to add the token.

Server Explorer

Figure 4-22. Server Explorer

The Server Explorer provides an integrated means for us to access different resources all from the comfort of
Visual Studio. It allows us to access databases, establish a connection to services such as Crystal reports
Services, Event Logs, Management Classes, management Events, Message Queues, Performance Counters, and
other Services on the system figure 4-22.
The Server Explorer allows us to interact with the above server resources. For example we can execute
database queries and display the result all from the Server Explorer in much the same way as we would
otherwise use SQL Server’s Management Studio To find out what we can do with a server item on the server
explorer, simply right-click it. In the example below we are opening a table definition in a database. We can then
add/modify/remove definition from the table just as we would from the Enterprise Manager Figure 4-23.

126
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 4-23. Using Server Explorer to open a database table.

Code Window
The code window is where majority of our development will be done in. It is here that we will spend majority of
our time developing ASP.NET XML Web services. To start developing we can select a particular file in the
solution explorer right click then select View Code.

Outlining
Outlining is a very useful function as it provides as an indicator where a class or a method starts and ends. We
can also collapse the outline to reduce the clutter in the code window. It allows us to view only the code that
interests us whilst blocking out the rest. To collapse a block of code simply click on the [-] minus outline to the
left of the code. To expand a block of code simply click on the [+] plus outline to expand the section see Figure 4-
24.

127
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 4-24. Code outline

IntelliSense Code Member List


IntelliSense provide us with an automatic way of completing code as well as perform automatic syntax check.
This proves as an important tool for Rapid Application Development (RAD). With IntelliSense Visual Studio
makes it easy for us to interact with class, controls and objects. IntelliSense is automatic as soon as we type a
class name or a object name Visual Studio will display a list of methods or properties that we can access and use
in our code Figure 4-25. The intellisense will also provide a list of parameters and their data types when we need
to call a method. Simply hover the mouse over the interested method and use the up and down key to scroll
through a list of overloads for the method and their requirements in terms of data types and parameters Figure 4-
26.

128
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 4-25 Intellisense member list

Figure 4-26 Intellisense shows the overload requirements

Error Underlining
One of the most useful feature during development is the intellisense’s ability to automatically underline code that
contain errors. This automatic underlining underlines all problematic code with a red underline. Because it is automatic
we can see the error almost immediately without the need to wait for compiling. Thus it’s the first line of defense
against code error. Visual Studio is able to detect a variety of error conditions, such as properties, undefined variables,
invalid data type conversions and missing code elements. We can place our mouse over the underlined error to see a
brief tooltip description of the problem Figure 4-27.

Figure 4-27 Intellisense Error underlining

129
The Complete Reference To Professional SOA with Visual Studio 2005

If an error is detected during the compiling stage Visual Studio will prompt us whether we want to continue. If
we choose to continue Visual Studio will use the last successful build of our application to execute because it can
not build a program with error. It is always a good habit to correct the error as soon as we are made aware.

Summary
In this chapter we have examined the role of the 2.0 version of the .NET Framework and the role that Visual
Studio 2005 plays in helping developers develop their service-oriented web applications.

* .NET is a comprehensive and yet flexible framework that allows developers to develop Console Application,
Windows GUI Application, ASP.NET Application, XML Web Service Application, Windows Service
Application and Mobile Applications. It is further enhanced with the release of .NET 2.0. All this is possible
from the Visual Studio 2005 IDE.
* .NET is more than just one language it is a framework that can be developed using different languages.

* .NET uses Common Language Runtime to provide the execution environment to .NET applications. All .NET
language compiles into MSIL code.

* .NET has a common type system where common data types, value and object types are common regardless the
.NET language we use to develop. This means all languages are equally powered.
* .NET ensures type safety, .NET Framework ensures that operations to be performed on one value or object are
performed on that value or object only.

* .NET manages code execution. The .NET Framework manages the state of objects during the program
execution. The Framework ensures automatic memory allocation and garbage collection.
* .NET supports side-by-side execution, allowing us to develop multiple versions of an application on a system
by using assemblies.

130
The Complete Reference To Professional SOA with Visual Studio 2005

Chapter 5 XML Web Services


Standards and Concepts
Web services are definitely changing the way we think about distributed software systems. In this chapter we
will examine the concepts behind the basic Web services technologies and their implementations.
An XML Web service is a programmable component that supports interoperability between distributed
systems. This is achieved through Web service’s adoption of vendor neutral standards such as XML and other
Internet standards. XML Web service relies on the internet standard Hyper Text Transfer Protocol (HTTP) as its
message delivery protocol. By adopting XML Web service we can create an infrastructure that supports
interoperability at all levels and ease the process towards SOA.
XML Web service is quite flexible we can use it internally within our enterprise or expose the service for
external access over the internet. This allows an enterprise to expose internal intellectual properties to the public
and develop a customer base from third-party application implementers. XML Web service allows access
through a standard generic interface thus it distributed components to work together as a single unit through
integration.
XML Web service is defined through an interface and an implementation of that interface. This abstraction
from interface allows a XML Web service to reside above existing system components, such as application
servers, messaging applications and other packaged applications. Web services because of their support for
vendor neutral technology can work with any operating system, hardware platform or programming language.
Developers no longer have to find ways to work between different protocols, standards and technology for
two piece of applications to work together. Using XML based messaging both service consumers and service
providers do not require more knowledge than each other’s input, output and location details
Web services are distributed applications based on standards. In essence, this chapter introduces the major
standards that we are likely to encounter in our Web services development: SOAP, WSDL, XML, XML Schema
(XSD), HTTP, and WSDL. See figure 5-1

Figure 5-1. Web service technology stack

131
The Complete Reference To Professional SOA with Visual Studio 2005

.NET Web Service Message Flow


In the following sections, we will be exploring how to build a web service with ASP.NET and how to test it
using different protocols.

Listing 5-1. Demonstrates a simple web service using Visual C#

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
public Service () {

//Uncomment the following line if using designed components


//InitializeComponent();
}

[WebMethod]
public string HelloWorld(string param1)
{
return "Hello " + param1;
}

Listing 5-2. Demonstrates a simple web service using Visual Basic .NET

Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols

<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class Service
Inherits System.Web.Services.WebService

<WebMethod()> _
Public Function HelloWorld(ByVal param1 As String) As String
Return "Hello " & param1
End Function

End Class
Using the HelloWorld Web service example in listing 5-1 and listing 5-2. The process of invoking a web
service involves sending a message to the Web service itself. When a request first enters into IIS for the
HelloWorld (WebMethod), SimpleWebService (Web service) we had constructed earlier, it looks something like
this:

132
The Complete Reference To Professional SOA with Visual Studio 2005

POST /SOAWebService/CSSimpleWebService/Service.asmx HTTP/1.1


Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/HelloWorld"

<?xml version="1.0" encoding="utf-8"?>


<soap:Envelope
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<HelloWorld xmlns="http://tempuri.org/" />
</soap:Body>
</soap:Envelope>

This flow of the message to the Web service itself is shown below in figure 5-2.

Figure 5-2. Web service message routing

1. IIS examines the request and determines that it is being sent a request that ends with the extension .asmx. The
ASP.NET handler is registered with IIS as handling this extension; therefore, the request in its entirety is
handed over to the ASP.NET process.

2. At this point, the ASP.NET worker process examines the request and discovers that it has a handler registered
in machine.config, the system-level .NET configuration file, for a request for resources with the extension
.asmx. It therefore kicks up this handler and passes the request onto it.

3. Next, the handler creates an instance of the class defined in the handler, and uses reflection to examine which
operations the class supports and how those operations should be routed. By default, operations are mapped to
methods using the SOAPAction HTTP header, but this can be changed to map to the first child element of the
SOAP body.

4. Once the message is routed, the handler uses the XML Serializer to deserialize the request XML into the
parameters that the method is expecting. Once the method returns, this return value and any out parameters are
mapped back into XML with the XML Serializer. Then, a response SOAP message is created that wraps this
XML, and the response is sent back, via ASP.NET’s HttpResponse context.

5. If an exception is thrown, then it is wrapped inside of a SoapException, and a SOAP fault is returned instead,
with the HTTP status code set to 500. (For non-error responses, the status code is 200, or OK.). These
messages typically transferred through HTTP.

133
The Complete Reference To Professional SOA with Visual Studio 2005

HTTP
Hyper Text Transfer Protocol (HTTP) is a World Wide Web Consortium (W3C) standard protocol for
transferring documents on the Internet. XML Web services use HTTP for communication. It is a generic,
stateless, protocol, which can be used for many tasks in addition its original use for hypertext.
A resource location is specified in HTTP through a mechanism known as a Uniform Resource Locator
(URL). Strictly speaking, the mechanism that is used in HTTP is a Uniform Resource Identifier (URI), but we
can also think of it as a URL.
The syntax of a URL is as follows:
http://host[:port][path[?querystring]]
The following is an example of a URL:
http://www.mswcf.com/url.aspx?id=23

In the preceding example, www.mswcf.com is the host, url.aspx is the path and id=23 is the query string. If
the port number is not specified (as in the preceding example), the default port for HTTP, which is port 80, is
used.
HTTP is a stateless protocol. This means that whenever the client makes a request, the connection to the
server is closed after the client receives the response. Therefore, if any state must be maintained between the
client and the server, the server must pass on state information with the response to the client. This will enable
the server to recover this information from the client when it receives the next request. For example, if we
implement a Web site that displays user-specific content, we would have to implement a mechanism that retains
information about the current user to display personalized content.

Listing 5-3. Demonstrates a HTTP Request

POST /urlpost.aspx HTTP/1.1


Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: 11

Id=23

Listing 5-4. Demonstrates a HTTP Response

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 75

<?xml version="1.0" encoding="utf-8"?>


<id value="23" nexturl="http://www.nextlocation.com" />

Above shows the request and response structure of HTTP.


The first line in an HTTP request is known as the request line, and the methods that a request supports are as
follows:

* OPTIONS

* GET
* HEAD
* POST

* DELETE

134
The Complete Reference To Professional SOA with Visual Studio 2005

* TRACE
* CONNECT
* extension-method

A HTTP response has the following structure format:

Version Status-Code Description


headers
a blank line
message body

The following code shows an example of an HTTP response:

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 75

<?xml version="1.0" encoding="utf-8"?>

The GET and POST Methods


HTTP-Get and HTTP-POST are the most common way of transferring information from one web page to the
next. Both are standard protocols that use HTTP (Hypertext Transfer Protocol) for the encoding. These protocols
will encode and pass values in a name /value pair from one web page to the next. This information is part of the
HTTP request headers which contains requesting information as well as the location of the page that we’re
requesting for. If the request is successful HTTP will respond with a series of HTTP response headers and the
requested information.
The difference between HTTP-GET and HTTP-POST is that HTTP-GET uses MIME application/x-www-
form-urlencoded to encode its name/value pair parameters in the url. The encoding process ensures that
characters such as space values are in turn encoded to %20 so that a valid and consistent text can be formed. The
appended parameters can also be referred to as a query string. Since the query string is embed in the URL there
is a limit to how much information we can store in the URL the limit for the length for a valid URL is 1024
characters. Listing 5-5 demonstrates using HTTP-GET

Listing 5-5. Demonstrates a HTTP request using GET

GET /url.aspx?id=23 HTTP/1.1


Host: localhost

While HTTP-POST similar to HTTP-GET both uses HTTP, and both uses MIME encoding to encode
name/value pairs. Though HTTP-POST instead of passing the query string as part of the URL, the name/value
pairs are passed inside the actual HTTP request message. Listing 5-6 shows the same request as listing 5-5 with
the same name/value pair using HTTP-POST.

Listing 5-6. Demonstrates a HTTP request using POST

POST /url.aspx HTTP/1.1


Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: 11

id=23

135
The Complete Reference To Professional SOA with Visual Studio 2005

The GET and POST request methods are ideal for communicating with an XML Web service. These
methods are designed specifically for submitting data to a Web server and retrieving a specified resource from a
Web server. This makes it possible to layer a function call model on top of these methods, which is exactly the
model that XML Web services requires.
HTTP GET uses an URL request to communicate information to a Web Page or an XML Web Service. The
most important feature of the request line is the querystring. The querystring is the portion of the URI that
follows the question mark, and consists of a set of URL-encoded name/value pairs.
In an HTTP-GET request, there is typically no message body. The response for an HTTP-GET request is
just a standard HTTP response.

Listing 5-7. Demonstrates a HTTP-POST request:

POST /Trading/GetStockPrice.aspx HTTP/1.1


Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: 11

id=23

In the preceding code, notice that there is no querystring as part of the URI. This is because the information
about the request is contained in the message body. This feature of an HTTP-POST request makes it a very
convenient way of passing larger sets of data to the server in contrast to an HTTP-GET where the size of the
querystring is restricted to 1024 bytes. Also, transmitting the data as part of the message body imposes fewer
restrictions on the kind of data that is sent to the server.

Tip: Both HTTP GET and POST can be applied to web applications as a standard form of execution. However in .NET 2.0 GET is disabled
as form of security precaution. To enable GET we must insert the below configurations into Web.Config.

<configuration>
<system.web>
<webServices>
<protocols>
<add name="HttpGet"/>
</protocols>
</webServices>
</system.web>
</configuration>

Alternatively, we can enable the GET protocol for all Web services on the computer by editing the
<protocols> section in Machine.config. The <protocols> section is located under the <webServices> section.
The following example enables HTTP GET, HTTP POST, and also SOAP and HTTP POST from localhost:

<protocols>
<add name="HttpSoap"/>
<add name="HttpPost"/>
<add name="HttpGet"/>
<add name="HttpPostLocalhost"/>
<add name="Documentation"/>

136
The Complete Reference To Professional SOA with Visual Studio 2005

The Machine.config file can be found at


c:\<windows>\Microsoft.NET\Framework\<version>\config\machine.config

Once HTTP-GET is enabled for Web service we can invoke the methods in the web service directly using
the syntax below:
http://server/webServiceName.asmx/functionName?parameter=parameterValue

Therefore, the call for our Web Service will be


http://localhost/SOAWebService/CSSimpleWebService/service.asmx/HelloWorld?param1=kim

This will produce the same result as clicking the Invoke button.

Figure 5-3. Web service call using HTTP GET

HTTP With .NET


Issuing an HTTP request and receiving a response is easy using the .NET Framework. The following classes in
the .NET Framework provide all of the required basic functionality:

* HttpWebRequest and HttpWebResponse classes in the System.Web namespace

* StreamReader and StreamWriter classes in the System.IO namespace


* WebRequest and WebResponse are abstract base classes in the .NET Framework for accessing data from the
Internet in a protocol-neutral way.

The HttpWebRequest and HttpWebResponse classes, which are derived from WebRequest and WebResponse
respectively, encapsulate the HTTP-specific aspects of the communications with a Web server. Most
importantly, they provide easy access to the HTTP headers, and the underlying request and response streams.
The StreamReader and StreamWriter classes are two utility classes that are used to read and write streams by
using a specific encoding (UTF-8/UTF-16, etc.).
Let’s create a simple console application to call the Web Service we had created earlier using HTTP POST.

TIP: Normally we do not need to call a Web service in this manner. As Visual Studio will automatically create a proxy for us which will
manage all Web service calls for us.

Having launched Visual Studio 2005, select File menu ~TRA New ~TRA Project. We will be presented
with the New Project dialog box, as shown in Figure 5-4. Simply select the language that we want to develop with
under the Project Types section. Then select Console Application from the Templates section.

137
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 5-4. New Project

Note If we are developing using Visual Basic .NET we can select the Console Application Template from the Visual Basic list

Once the template starts we will be presented with an empty code template shown in Figure 5-5.

Figure 5-5. Console program template is automatically created for you

Listing 5-8. Demonstrates a console application to send a HTTP POST request to a Web service using Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;

namespace CSHTTPRequest

138
The Complete Reference To Professional SOA with Visual Studio 2005

{
class Program
{
static void Main(string[] args)
{
string url = "http://localhost/soawebservice/" +
"firstservicecs/service.asmx/HelloWorld";
string contentType = "application/x-www-form-urlencoded";
string method = "POST";
string content = "";
HttpWebRequest req =
(HttpWebRequest)WebRequest.Create(url);
req.ContentType = contentType;
req.Method = method;
req.ContentLength = content.Length;
Stream s;
s = req.GetRequestStream();
StreamWriter sw = new StreamWriter(s, Encoding.ASCII);
sw.Write(content);
sw.Close();

HttpWebResponse res = (HttpWebResponse)


req.GetResponse();
s = res.GetResponseStream();

StreamReader sr = new StreamReader(s, Encoding.ASCII);


StringBuilder sb = new StringBuilder();
char[] data = new char[1024];
int nBytes;
do
{
nBytes = sr.Read(data, 0, (int)1024);
sb.Append(data);
} while (nBytes == 1024);
Console.WriteLine(sb);
Console.ReadLine();
}
}
}

Listing 5-9. Demonstrates a console application to send a HTTP POST request to a Web service using Visual Basic .NET

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Net
Imports System.IO
Namespace VBHTTPRequest

Module Program

Sub Main()
Dim url As String = "http://localhost/soawebservice/" + _
"firstservicecs/service.asmx/HelloWorld"

139
The Complete Reference To Professional SOA with Visual Studio 2005

Dim contentType As String = _


"application/x-www-form-urlencoded"
Dim method As String = "POST"
Dim content As String = ""
Dim req As HttpWebRequest = _
CType(WebRequest.Create(url), HttpWebRequest)
req.ContentType = contentType
req.Method = method
req.ContentLength = content.Length
Dim s As Stream
s = req.GetRequestStream
Dim sw As StreamWriter = _
New StreamWriter(s, Encoding.ASCII)
sw.Write(content)
sw.Close()
Dim res As HttpWebResponse = _
CType(req.GetResponse, HttpWebResponse)
s = res.GetResponseStream
Dim sr As StreamReader = _
New StreamReader(s, Encoding.ASCII)
Dim sb As StringBuilder = New StringBuilder
Dim data(1024) As Char
Dim nBytes As Integer
Do
nBytes = sr.Read(data, 0, CType(1024, Integer))
sb.Append(data)
Loop While nBytes = 1024
Console.WriteLine(sb)
Console.ReadLine()
End Sub
End module
End Namespace
Once we have completed the code simply press F5 to run and debug or CTRL + F5 to run without
debugging. We should see the message returned from the Web service invocation see Figure 5-6.

Note: If you are not using IIS and are using the ASP.NET Development Server as your web server then you will need to adjust the port
number for example http://localhost/webservice would become http://localhost:portnumber/webservice.

Figure 5-6. Result from Web service call

To use HttpWebRequest simply use WebRequest.Create the return value is converted to HttpWebRequest.

140
The Complete Reference To Professional SOA with Visual Studio 2005

HttpWebRequest req = (HttpWebRequest )WebRequest.Create(url);

In most cases, the WebRequest and WebResponse classes provide all of the functionality that we need to
perform a HTTP request. However, if we need to access HTTP-specific features such as HTTP headers, we need
a protocol-specific derived class of WebRequest.

req.ContentType = contentType
req.Method = method
req.ContentLength = content.Length

In the above code HTTP-specific properties such as the ContentType, Method of call and ContentLength are
set.

Listing 5-10. Demonstrates content steam using Visual C#

Stream s;
s = req.GetRequestStream();
StreamWriter sw = new StreamWriter(s, Encoding.ASCII);
sw.Write(content);
sw.Close();

Listing 5-11. Demonstrates content steam using Visual Basic .NET

Dim s As Stream
s = req.GetRequestStream
Dim sw As StreamWriter = New StreamWriter(s, Encoding.ASCII)
sw.Write(content)
sw.Close()

The content for the request is written to a stream named content. Note that the type of encoding is specified
as ASCII for the stream.

Listing 5-12. Demonstrates using GetResponse in Visual C#

HttpWebResponse res = (HttpWebResponse)


req.GetResponse();

Listing 5-13. Demonstrates using GetResponse in Visual Basic .NET

Dim res As HttpWebResponse = CType(req.GetResponse, HttpWebResponse)

The HTTP response is retrieved through the use of GetResponse().

XML
XML is used to implement XML Web services in a number of ways. This includes the use of XML as the wire
format between an XML Web service consumer and the XML Web service, and the use of XML to describe the
XML Web service interface. XML is a big topic and full coverage is out of scope of this book. If you’re
unfamiliar with XML it is highly recommended that you find additional information on XML. We will cover
some basic notion of XML here, while later in the book we will focus on XML data manipulation with .NET 2.0.
It is recommended that the XML Web service developer have a solid understanding of XML.
XML is a complete tag-based language which uses tagged syntax to structure data. Documents that conform
to XML schema is structured from a variety of elements, namespace declarations, and attributes. Let’s have a
closer look.

141
The Complete Reference To Professional SOA with Visual Studio 2005

Elements
<tagname></tagname>
<tagname/>
<tagname>Value</tagname>

Elements make up majority of the XML document. There exist exactly one top level element known as the
document element. Elements have a name and may also contain child elements.

An element with children

<Person>
<name>John Doe</name>
<age>44</age>
</Person>

The child of elements can be elements themselves or they can also be processing instructions, or CDATA
sections. The children of an element can contain attributes and or namespaces. Attributes and namespaces
contained by the elements are unordered.
Elements are defined by an open tag and a close tag. The open tag consists of a less angle bracket <
followed by the name of the element, then followed by a closing greater than angle bracket >. The syntax for the
close tag is essentially the same but with a forward slash /: close tags consist of a less than angle bracket <
followed by a / then the same tagname followed by a greater than angle bracket >.
The children of an element are contained between the open and close tags of their parent. In cases when an
element has no children, the element is said to be “empty”.

An empty element

<Paid></Paid>

A short hand way of writing an empty element is simply to complete the start tag with a forward slash
immediately after the tag name.

Empty element shorthand

<Paid/>

XML itself does not define any particular element names, it allows the developer of the XML document to
choose any name for the tag. There are a few restricts such as XML names are case sensitive and must begin
with a letter or an underscore. The initial characters may be followed by any number of alpha numerical
characters as well as hyphens - and underscores _.

Elements, namespaces, and namespace declarations


<prefix:localname xmlns:prefix='namespace URI'/>
<prefix:localname xmlns:prefix='namespace URI'>
</prefix:localname>
<prefix:localname xmlns:prefix='namespace URI'>
children
</prefix:localname>

Since XML allows us to define our own tagname for elements it is thus possible to define the same tagname
twice. To be able to distinguish between the two tagnames XML offers namespaces as a means to distinguish

142
The Complete Reference To Professional SOA with Visual Studio 2005

between the two elements. This is done by associating an element with a namespace. A namespace acts as the
scope containing all the elements that have been associated to it.
A namespace name is defined by a uniform resource identifier (URI). URI serves as an ideal unique
identifier string. The namespace name and the local name together forms a globally unique name called
“Qualified Name”.
Namespace declarations associated with the element will be defined within the element’s start tag. A
typically shorter string known as the “namespace prefix” will be used. The syntax for the namespace declaration
will be xmlns:prefix='URI'. It is also possible not to map a namespace declaration to a prefix. We can use the
default namespace declaration. The syntax for a default namespace declaration is xmlns='URI'. In eiher cases
only one default namespace declaration may appear on an element. The URI can be defined by either single
quotes ‘ or double quotes “. It is also possible to map the same namespace to more than one prefix.
All namespaces have a scope to which is applied for the element on which it is declared and all of the
element’s descendants. The mapping of a given prefix for a namespace can be overridden by associating the
prefix with a new mapping for the element’s descendants. The in-scope default namespace if not using a prefix
can also be overridden by providing a new namespace declaration.
All names of elements in a XML document that conform to the Namespace are regarded as qualified names
(QNames).

In the following example an element with a local name of Person and a prefix of pre is mapped to a namespace URI of
urn:example-org:People. The element person has decendents or child elements of name and age. Both child elements are
assigned to the prefix of pre with the namespace URI of urn:example-org:People.

<pre:Person xmlns:pre='urn:example-org:People' >


<pre:name>John Doe </pre:name>
<pre:age>44</pre:age>
</pre:Person>

Syntactically all Qualified Names have an associated local name and prefix is optional. Both the local name
and also the prefix can be referred to as a NCName, an NCName is a name that does not contain a colon. The
syntax for an element associated with the prefix is defined by the prefix followed by colon then the local name of
the element. A namespace must be defined if prefix is to be used.
If the local name does not contain a prefix then the element is contained by the default namespace
declaration. However, if no default namespace had been declared in the scope the element then the element is
regarded as an unqualified element, which simply means that it does not have a namespace.

In the example below an element contains a local name of person is assigned a prefix name of pre that is mapped with the
namespace uri of urn:example-org:People. The person element has two decendents or two child elements of name and age
and none of them are associated with the pre prefix. This means that both of these child elements are unalified elements as
they are not contained in any namespace

<pre:Person xmlns:pre='urn:example-org:People' >


<name>John Doe</name>
<age>44</age>
</pre:Person>

The namespace URI of an unqualified element is defined by the empty string “”. If a default namespace
declaration is defined and in scope then an unqualified namespace is required. We can overwrite the default
namespace declaration by defining the URI as an empty string in the form of xmlns=”” on the element.

The example below demonstrates using default namespace declaration. An element with the local name of person is assigned
a default namespace uri of urn:example-org:People. The element has two decendents or child elements of name and age.

143
The Complete Reference To Professional SOA with Visual Studio 2005

Both elements are not assigned to any prefix. As such they both automatically fall under the namespace of its parent element
of urn:example-org:People. This example is equivalent to the previous example

<Person xmlns='urn:example-org:People' >


<name>John Doe</name>
<age>44</age>
</Person>

Attributes and Namespaces


name='value'
name="value"

In XML, elements can be decorated with attributes. An attribute is used to provide data or metadata about an
element. Attributes are a way of providing additional information to what the element already describes.
Attributes are defined as name/value pairs separated by the equal sign =.

A simple example would be that the person element can contain two attributes describing properties about that particular
person. These are defined as attributes rather than child elements.

<Person name='John Doe' age='44' />

Attributes are defined by the same requirement as the element in that it must be alphanumerical and its value
must be quoted using either a single quote ‘ or a double quote “. An element may have a number of attributes but
they must contain the different names so that they can be distinguished.

Some elements with metadata attributes

<age base='16' units='years' >20</age>


<age base="10" units="years" >32</age>

Attribute names are also Qualified Names (QNames). The namespace of an attribute is defined in the in-
scope namespace declaration for the prefix. Attributes that are not defined in the namespace declaration are
considered to be unprefixed even if default namespace is declared in the scope.

In the following example an element of person contains an child element of name and age. The age element contains
attributes of base and units. Base attribute is associated to the namespace of urn:example-org:People:base through a prefix
of ‘b’ while the Units attribute is associated with the namespace of urn:example-org:units with a prefix of ‘u’.

<Person xmlns='urn:example-org:People'
xmlns:b='urn:example-org:People:base'
xmlns:u='urn:example-org:units' >
<name>John Doe</name>
<age b:base='10' u:units='years' >44</age>
</Person>

Comments
<!-- comment text -->

In XML, document comments are also supported. Comments are used to provide additional human readable
information about the XML content. The comments begin with <!--followed by the comments and end with the -
->. Comments are never used as data and they can appear anywhere in the XML document. The text in the

144
The Complete Reference To Professional SOA with Visual Studio 2005

comment itself is situated between the start <!-- sequence and the end --> sequence. Character sequences such as
– may not appear within the comments.
<!-- this is a comment about xml -->

Whitespace
In XML whitespace characters refer to space characters, tabs, or carriage return and line feed characters. XML
requires that attributes and namespace declarations are separated from each other using whitespace. Whitespace
is also required between the text section of the XML comment and that of the comment’s closing sequence -->.
Other than the above requirements we can use whitespaces anywhere else in the document. These can be inside
element contents, processing instructions, comment texts and attribute values. Whitespace can also be used
within attribute name and namespace declarations. We can not use white space in an element between the
opening angle bracket < and its tag name. It also can not be used between the prefix colon local name sequence.

In the below example whitespace is used in various locations in the XML document. We can use whitespace between element
values, attribute value and separation of namespace and attribute.

<pre:Vehicle xmlns:pre='urn:example-org:Transport' type='car' >


<seats> 4 </seats>
<colour> Whitespace here </colour>
<engine>
<petrol />
<capacity units='c c' > 4 5 </capacity>
</engine >
</pre:Vehicle >

Prohibited character literals


In XML there are five character entities that can cause issues when used within element content or within the
attribute value. Entity references are symbolic notations that are used to represent these characters. Entities begin
with an ampersand and end with a semicolon ;. The five entity references are &lt;, &gt;, &amp;, &apos; and
&quot;.

* &lt; - Or otherwise known as known as the less than < character. The problem with the less than character is
that it is the first element used for the start tag. As such the less than character can not appear as a child of an
element or inside an attribute value because it will be interpreted as the start of an element
* &gt; - Otherwise known as the greater than > character. The greater than character ends a start tag and as the
end tag it is the last character used.

* &amp; - The ampersand character & is used in the entity markup and it is the first character of a character
entity reference. As such the ampersand can not be in an element or inside an attribute value.

* &apos; - Stands for apostrophe or single quote characters ‘. Apostrophe can be used to encapsulate values in
attribute, thus if an apostrophe is used within a string which is already single quoted then this can cause
problems. Because it would signal the end of the value.
* &quot; - Stands for double quote “. Similar to apostrophe double quote can not be used in strings that already
are encapsulated within double quotes. The quote cannot be used because it would signal the end of the value.

If we need to use these characters then we should use entity reference to represent these characters.

145
The Complete Reference To Professional SOA with Visual Studio 2005

CDATA sections
<![CDATA[ text content possibly containing literal < or & characters ]]>

All text contained in a XML document will be parsed by the parser. Though only text contained in the CDATA
section will be ignored by the parser. As such the CDATA section is quite useful at blocking the requirement to
escape literal texts when using the prohibited characters such as <, >, and &. A CDATA section begins with the
sequence of <![CDATA[ followed by the text area in which the literal characters are ignored followed by the
closing sequence of ]]>. As such the character sequence ]]> which ends the CDATA section must not appear
within the section.

Use of literal less-than characters in a CDATA section

<sometext>
<![CDATA[ They're saying "x < y" & that "z > y" so I guess
that means that z > x ]]>
</sometext>

The XML declaration


<?xml version='1.1' encoding='character encoding' standalone='yes|no'?>

The XML declaration is a way of identifying that the document as being XML. All XML documents should
begin with a XML declaration. If a XML declaration is present in a document it must be the first construct in the
document. The declaration itself can contain up to three attribute name/value pairs used to provide information
about the document. The three attributes are a mandatory version attribute, an optional encoding attribute and a
standalone attribute. The attributes must be ordered in sequence. The declaration must also begin with <?xml and
end with the sequence of ?>. All XML declarations have a version attribute with a value that must be 1.1.

<?xml version='1.1' ?>


<?xml version='1.1' encoding='US-ASCII' ?>

Well-formed XML
A well formed XML document is a XML document that adheres to the strict syntactical rules. These rules are:

There must be exactly one top level element.

All tags must have a corresponding close tag or use shorthand close element syntax.

All tags must also be correctly nested.


All attributes of an element must also have different names.

If attributes are namespace qualified then the combination of namespace and localname must be unique.
All namespace prefixes used must have a corresponding namespace declaration that is in scope.

A well-formed XML document

<?xml version='1.0' encoding='UTF-8' ?>


<p:Cars xmlns:p='urn:example-org:Cars' >
<color>Light Grey</color>
<year>2005</year>
</p:Cars>

146
The Complete Reference To Professional SOA with Visual Studio 2005

XML with Visual Studio 2005


Visual Studio comes with a suite of tools to simplify the process of creating and editing XML documents. The XML
Editor supports native XML rules compliance checking and schema based validation.

The XML editor includes the following functionality:

* Design time well-formedness and validation errors.


* Validation support for Schema, DTD, and XDR.
* Inferring an XSD Schema from an XML instance.

* Converting a DTD or XDR to XSD Schema.


* Context-sensitive Intellisense.
* XSLT editing, viewing the results of the transform.

* Standard Visual Studio code-editing, such as outlining and commenting or un-commenting.

To start the XML editor is simple. Simply go to File->New->File. This will bring up the dialog box. Select
General under Categories and Select “XML File” or “XML Schema” from under the Templates section
depending on what we’re interested in doing. To open an existing XML file, select File->Open. An XML file can
be added to an existing project or solution by using the Add Existing (or Add New) Item option from the context
menu. Any XML file (such as .config) that does not have a default editor associated to it in Visual Studio will be
opened in the XML Editor.

Figure 5-7. Creating a new XML document

From here on we can enter a new xml document or modify an existing document. Visual Studio has a
number of tools that will help format and modify the XML document.

147
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 5-8. XML document within Visual Studio 2005

When editing an XML file Visual Studio provides context-sensitive intellisense. In the example below
figure 5-9, the drop down list contains various valid encoding types. Similarly when editing a XML file that has
a schema attached to it, the XML editor will provide context-sensitive intellisense based on the Schema.

Figure 5-9. Visual Studio 2005 XML Intellisense tool tip, smart indenting and syntax coloring

Once the user starts editing, the XML editor checks the well-formedness for errors in the XML and provides
live feedback to the user via two mechanisms. In the example in the screen shots below, the <xs:sequence> tag is
not closed, the end tag for <xs:sequence> does not match.

148
The Complete Reference To Professional SOA with Visual Studio 2005

The first mechanism is the red squiggly under the sequence of characters that is the cause of the errors. A
yellow vertical line is present next to the region of area. If the user's mouse pointer hovers over the section with
the error, a tool tip will provide the actual error text see figure 5-10.

Figure 5-10. error highlighting

In the second mechanism the error information is provided is through the error list. The Error List can be
selected from the View menu. The error messages contain a description of the error, the file the error resides in,
the line of the error and the column involved. Double clicking on a particular error will take us to the location of
the error figure 5-11.

Figure 5-11. Error list for XML

The Visual Studio XML editor also allows you collapse and expand XML outlines. This is particularly
handy when editing large xml documents.

149
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 5-12. XML document outlining with + and -

XML Schema Definition (XSD)


One of the most important activities involved in designing and implementing XML Web services is specifying
data types that are passed to and returned by an XML Web service. We must define data types unambiguously in
the specifications. The XSD language is best suited for defining such document specifications. Due to the scale
of the topic on xml we can only briefly touch on some notions of XSD.

Datatypes
XML Schema provides a set of built-in datatypes. Some of these types are primitives, described in the
specification, whereas others are derived types described in a schema. Both primitive and derived types are
available to schema authors to use as is or to derive new types from.

Numeric types

Table 5-1.

150
The Complete Reference To Professional SOA with Visual Studio 2005

Type Description

decimal An arbitrary-precision decimal number

integer An arbitrary-length integer

negativeInteger An arbitrary-length negative integer

nonNegativeInteger An arbitrary-length integer with a value of zero or more

positiveInteger An arbitrary-length positive integer

nonPositiveInteger An arbitrary-length integer with a value of zero or less

long A 64-bit signed integer

int A 32-bit signed integer

short A 16-bit signed integer

byte An 8-bit signed integer

unsignedLong A 64-bit unsigned integer

unsignedShort A 16-bit unsigned integer

unsignedInt A 32-bit unsigned integer

unsignedByte An 8-bit unsigned number

float A single-precision floating point number

double A double-precision floating point number

Date and time types

Table 5-2.

Type Description
date A Gregorian calendar date
dateTime An instant in time
duration A duration in time
gDay A Gregorian day-long monthly recurring period
gMonth A Gregorian month
gMonthDay A Gregorian day-long annually recurring period
gYear A Gregorian calendar year
gYearMonth A Gregorian month-long annually recurring period

151
The Complete Reference To Professional SOA with Visual Studio 2005

time An instant in time

Name and string types

Table 5-3.

Type Description

string A general string type

normalizedString A string with normalized whitespace

token A string with normalized whitespace and with


preceding and trailing whitespace removed

QName An XML Name

Name An XML Name

NCName An XML noncolonized name

Boolean
The boolean datatype represents two-value logic.
Value space: true, false. or 1, 0 (where 1 and 0 correspond to true and false respectively).

<row inserted='true' />


<checked>0</checked>

Byte
The byte datatype represents the range of integer values that can be stored in an 8-bit signed field.
Value space: +127 to –128.

<num>+12</num>
<num>-127</num>
<num>0000056</num>
<num>0</num>

Date
The date datatype represents a Gregorian calendar date.
Value: Any date.
A normal date, and a date with negative time zone modifier

<date>2001-02-13</date>
<date>2001-02-13-05:00</date>

dateTime
The dateTime datatype represents an instant in time as a combination of Gregorian date and time-of-day values.

152
The Complete Reference To Professional SOA with Visual Studio 2005

Value: Any instant in time as a combination of Gregorian date and time-of-day values.

An instant in time

<instant>2001-02-13T22:20:00</instant>
<instant>2001-02-13T17:20:00-05:00</instant>

decimal
The decimal datatype represents arbitrary precision decimal numbers.
Value: The infinite set of all decimal numbers.

<num>123456</num>
<num>1.23456</num>
<num>+12.3456</num>
<num>0000123456.0000</num>

double
The double datatype represents IEEE double-precision 64-bit floating point numbers.
Value: +253 x 2970 to –253 x 2970.

<num>123456</num>
<num>1.23456E5</num>
<num>+12.3456E72</num>
<num>0000123456.0000</num>

duration
The duration datatype represents a duration of time in Gregorian years, months, days, hours, minutes, and
seconds according to ISO 8601.
Value: Any duration of time per ISO 8601.

One year, two months, four days

<duration>P1Y2M4D</duration>
<duration>P1Y2M4DT0H0M0S</duration>

gDay
The gDay datatype represents a Gregorian day that recurs, specifically a oneday-long, monthly recurring period.
Value: Any day-long, monthly recurring period.

13th of every month

<day>---13</day>

gMonth
The gMonth datatype represents a Gregorian month that recurs every year.
Value: Any month-long, annually recurring period.

153
The Complete Reference To Professional SOA with Visual Studio 2005

A recurring Gregorian month for February

<monthDay>--02--</monthDay>

gMonthDay
The gMonthDay datatype represents a Gregorian date that recurs, specifically, a day of the year.
Value space: Any day-long, annually recurring period.

A recurring Gregorian date of February 13th

<monthDay>--02-13</monthDay>

gYear
The gYear datatype represents a Gregorian calendar year.
Value space: Any Gregorian calendar year.

A Gregorian year, the year 2001.

<year>2001</year>

gYearMonth
The gYearMonth datatype represents a particular Gregorian month in a particular Gregorian year.
Value space: Gregorian calendar months; any month-long nonrecurring period.

A Gregorian calendar month, February 2001

<month>2001-02</month>

hexBinary
The hexBinary datatype represents hex-encoded binary data.
Value space: Any finite sequence of binary octets.

Hex-encoded data for a prime number sequence for the numbers 1, 2, 3, 5, 7, 9, 11, 13, 17, and 19.

<data>0102030507090B0D1113</data>

int
The int datatype represents the range of integer values that can be stored in a 32-bit signed field.
Value: +2,147,483,647 to –2,147,483,648.

int values, Various int values as element content

<num>1234567890</num>
<num>42</num>
<num>+12</num>
<num>-273</num>

154
The Complete Reference To Professional SOA with Visual Studio 2005

integer
The integer datatype represents arbitrary integer values.
Value: The infinite set of all integers.

<num>123456</num>
<num>42</num>
<num>+12</num>
<num>-273</num>

language
The language datatype represents natural language identifiers according to RFC 1766.
Value: The set of all strings that are language identifiers.

language identifier attributes

<text xml:lang='en'>a man a plan a canal panama</text>


<text xml:lang='en-GB'>Do me a favour!</text>
<text xml:lang='en-US'>Do me a favor</text>

long
The long datatype represents the range of integer values that can be stored in a 64-bit signed field.
Value: +9,223,372,036,854,775,807 to –9,223,372,036,854,775,808.

<num>1000000000000</num>
<num>1234567890</num>
<num>42</num>
<num>+12</num>

Name
The Name datatype represents XML Names, typically used for names of elements and attributes.
Value: The set of all strings that match the Name production in XML Recommendation.

Various XML Names as attribute values

<name val='Person'/>
<name val='age'/>
<name val='height.units'/>

NCName
The NCName datatype represents XML noncolonized names, typically used for the local names of namespace-
qualified elements and attributes; that is, the part after the prefix and the colon.
Value: The set of all strings that match NCName production in XML Recommendation

XML NCNames

<name val='Person'/>
<name val='age'/>
<name val='height.units'/>

155
The Complete Reference To Professional SOA with Visual Studio 2005

negativeInteger
The negativeInteger datatype represents integer values of –1 or less.
Value: The infinite set of all integers with values of –1 or less.

negativeInteger values

<num>-42</num>
<num>-273</num>
<num>-0000056</num>

nonNegativeInteger
The nonNegativeInteger datatype represents the integer values zero or more.
Value: The infinite set of all integers with values of zero or more.

Various nonNegativeInteger values as element content

<num>42</num>
<num>+273</num>
<num>0000056</num>

nonPositiveInteger
The nonPositiveInteger datatype represents the integer values zero or lower.
Value: The infinite set of all integers with values of zero or less.

<num>-42</num>
<num>-273</num>
<num>-0000056</num>

normalizedString
The normalizedString datatype represents strings that have been normalized with respect to whitespace; that is,
all carriage return (#xD), line feed (#xA), and tab ( #x9 ) characters have been converted to space (#x20)
characters.
Value: The set of strings that do not contain carriage return (#xD), line feed (#xA), or tab (#x9) characters.

A normalized string with preceding and trailing whitespace

<speech> Now is the winter of our discontent </speech>

positiveInteger
The positiveInteger datatype represents integer values of 1 or more.
Value: The infinite set of all integers with values of 1 or more.

positiveInteger values, Various positiveInteger values as element content

<num>42</num>
<num>+273</num>
<num>0000056</num>

156
The Complete Reference To Professional SOA with Visual Studio 2005

QName
The QName datatype represents qualified names in XML according to Namespace in XML.
Value: The set of pairs of a namespace name and a local name where a namespace name is a URI reference
and a local name is an NCName.

<elem attr='p:syntax' />


<elem attr='xsd:schema' />

short
The short datatype represents the range of integer values that can be stored in a 16-bit signed field.
Value: +32,767 to –32,768.

short values

<num>4242</num>
<num>+12</num>
<num>-273</num>

string
The string datatype represents Unicode character strings (strictly finite sequences of ISO-10646 character
values).
Value: All finite-length sequences of ISO-10646 characters

Elements containing strings

<greeting>Hello World!</greeting>
<price>$9.95</price>
<price>£9.95</price>

time
The time datatype represents an instant in time that recurs each day.
Value: Any zero-duration daily instant in time.

A time 10:20 PM

<time>22:20:00</time>

token
The token datatype represents “tokenized” strings. These are strings in which all preceding or trailing space
(#x20) characters have been removed, all carriage return (#xD), line feed (#xA), and tab (#x9) characters have
been converted to space characters, and all sequences of two or more space characters have been converted to a
single space character.
Value: The set of strings that do not contain carriage return (#xD), line feed (#xA) or tab (#x9) characters.

A token value

<speech> a Token message</speech>

157
The Complete Reference To Professional SOA with Visual Studio 2005

unsignedByte
The unsignedByte datatype represents the range of integer values that can be stored in an 8-bit unsigned field.
Value: +255 to zero.

<num>255</num>
<num>+12</num>
<num>0000056</num>

unsignedInt
The unsignedInt datatype represents the range of integer values that can be stored in a 32-bit unsigned field.
Value: +4,294,967,295 to zero.

unsignedInt values

<num>1234567890</num>
<num>42</num>
<num>+12</num>

unsignedLong
The unsignedLong datatype represents the range of integer values that can be stored in a 64-bit unsigned field.
Value: 18,446,744,073,709,551,615 to zero.

<num>1000000000000</num>
<num>1234567890</num>
<num>42</num>
<num>+12</num>

unsignedShort
The unsignedShort datatype represents the range of integer values that can be stored in a 16-bit unsigned field.
Value: +65,535 to zero.

<num>4242</num>
<num>+12</num>
<num>0000056</num>

Facets
Facets are used to restrict the set of values a datatype can contain, thus allowing types with different value ranges
to be derived from other types. The new value range must be equal to or narrower than the value range of the
base type. It is not possible to expand the value space of a type using facets.
Multiple facets can be specified in a single type definition, in which case the value space of the type is
constrained by all the facets listed. Any values appearing in the instance must conform to all the listed facets.
There are 12 facet elements, all of which share a common syntax. They each have a mandatory value
attribute that specifies the value for the facet. Although this attribute is of type xs:string, the value must typically
be a valid value of the type to which the facet is applied. For example, if a minExclusive facet is being used to
constrain the decimal datatype then the value must be numerical. Facets also have an optional fixed attribute of
type boolean. If the value of this attribute is true, then the facet cannot be respecified in a derived type. Lastly,
facets have an optional id attribute of type ID that is for application use.

158
The Complete Reference To Professional SOA with Visual Studio 2005

enumeration
<xs:enumeration value='string' fixed='boolean' id='ID' />

Defines a fixed value that the type must match. Multiple enumeration facets can be used to specify multiple legal
values. Thus, multiple enumeration facets have a cumulative effect, allowing multiple possible values.
Values: Any value that matches the type of the base type

<xs:simpleType name='sizes'>
<xs:restriction base='xs:string' >
<xs:enumeration value='small' />
<xs:enumeration value='medium' />
<xs:enumeration value='large' />
</xs:restriction>
</xs:simpleType>

fractionDigits
<xs:fractionDigits value='positiveInteger' fixed='boolean' id='ID' />

Specifies the maximum number of digits to the right of the decimal point for types derived from number. If
totalDigits and fractionDigits facets both appear, the value of the fractionDigits facet must be less than or equal
to the value of the totalDigits facet.
Values: positiveInteger

<xs:simpleType name='frac5' >


<xs:restriction base='xs:decimal' >
<xs:fractionDigits value='5' />
</xs:restriction>
</xs:simpleType>

length
<xs:length value='nonNegativeInteger' fixed='boolean' id='ID' />

Defines the number of characters in a string-based type, the number of octets in a binary-based type, or the
number of items in a list-based type. The length facet may not appear with either the minLength or maxLength
facets.
Values: nonNegativeInteger

Fixed-length types

<xs:simpleType name='String10' >


<xs:restriction base='xs:string' >
<xs:length value='10' />
</xs:restriction>
</xs:simpleType>

maxExclusive
<xs:maxExclusive value='number' fixed='boolean' id='ID' />

Specifies an exclusive upper bound on the value space of the type. The value specified by the facet is not
part of the value space of the new type. The maxExclusive facet may not be combined with the maxInclusive

159
The Complete Reference To Professional SOA with Visual Studio 2005

facet. If the maxExclusive facet appears with either the minInclusive or minExclusive facets, then the value of
the maxExclusive facet must be greater than or equal to the valueof the minInclusive or minExclusive facet.
Values: A value in the value space of the base type

A numerical type with an exclusive upper bound

<xs:simpleType name='notquiteagrand' >


<xs:restriction base='xs:decimal' >
<xs:maxExclusive value='1000' />
</xs:restriction>
</xs:simpleType>

maxInclusive
<xs:maxInclusive value='number' fixed='boolean' id='ID' />

Specifies an inclusive upper bound on the value space of the type. The value specified by the facet is part of
the value space of the new type. The maxInclusive facet may not be combined with the maxExclusive facet. If
the maxInclusive facet appears with either the minInclusive or minExclusive facets, then the value of the
maxInclusive facet must be greater than or equal to the value of the minInclusive or minExclusive facet.
Values: A value in the value space of the base type

A numerical type with an inclusive upper bound

<xs:simpleType name='notquiteagrand' >


<xs:restriction base='xs:decimal' >
<xs:maxInclusive value='999.99' />
</xs:restriction>
</xs:simpleType>

maxLength
<xs:maxLength value='nonNegativeInteger' fixed='boolean' id='ID' />

Defines the maximum number of characters in a string-based type, the maximum number of octets in a
binary-based type, or the maximum number of items in a list-based type. The maxLength facet may not be
combined with the length facet. If both maxLength and minLength facets appear, the value of maxLength must
be greater than or equal to the value of minLength.
Values: nonNegativeInteger

Two types, both with a maximum number of characters

<xs:simpleType name='String10orless' >


<xs:restriction base='xs:string' >
<xs:maxLength value='10' />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name='uri50orless' >
<xs:restriction base='xs:anyURI' >
<xs:maxLength value='50' />
</xs:restriction>
</xs:simpleType>

160
The Complete Reference To Professional SOA with Visual Studio 2005

minExclusive
<xs:minExclusive value='number' fixed='boolean' id='ID' />

Specifies an exclusive lower bound on the value space of the type. The value specified by the facet is not
part of the value space of the new type. The minExclusive facet may not be combined with the minInclusive
facet. If the minExclusive facet appears with either the maxInclusive or maxExclusive facets, then the value of
the minExclusive facet must be less than or equal to the value of the maxInclusive or maxExclusive facet.
Values: A value in the value space of the base type

A numerical type with an exclusive lower bound

<xs:simpleType name='morethanagrand' >


<xs:restriction base='xs:decimal' >
<xs:minExclusive value='1000.00' />
</xs:restriction>
</xs:simpleType>

minInclusive
<xs:minInclusive value='number' fixed='boolean' id='ID' />

Specifies an inclusive lower bound on the value space of the type. The value specified by the facet is part of
the value space of the new type. The minInclusive facet may not be combined with the minExclusive facet. If the
minInclusive facet appears with either the maxInclusive or maxExclusive facets, then the value of the
minInclusive facet must be less than or equal to the value of the maxInclusive or maxExclusive facet.
Values: A value in the value space of the base type

A numerical type with an inclusive lower bound

<xs:simpleType name='atleastagrand' >


<xs:restriction base='xs:decimal' >
<xs:minInclusive value='1000.00' />
</xs:restriction>
</xs:simpleType>

minLength
<xs:minLength value='nonNegativeInteger' fixed='boolean' id='ID' />

Defines the minimum number of characters in a string-based type, the minimum number of octets in a
binary-based type, or the minimum number of items in a listbased type. The minLength facet may not be
combined with the maxLength facet. If both minLength and maxLength facets appear, the value of minLength
must be less than or equal to the value of maxLength.
Values: nonNegativeInteger

Length-restricted types

<xs:simpleType name='String10ormore' >


<xs:restriction base='xs:string' >
<xs:minLength value='10' />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name='uri50ormore' >

161
The Complete Reference To Professional SOA with Visual Studio 2005

<xs:restriction base='xs:anyURI' >


<xs:minLength value='50' />
</xs:restriction>
</xs:simpleType>

pattern
<xs:pattern value='string' fixed='boolean' id='ID' />

Defines a pattern that the type must match based on a regular expression.
Values: A regular expression

A patterned string type

<xs:simpleType name='code' >


<xs:restriction base='string' >
<xs:pattern value='[A-Z]{2}\d{4}' />
</xs:restriction>
</xs:simpleType>

totalDigits
<xs:totalDigits value='positiveInteger' fixed='boolean' id='ID' />

Specifies the maximum number of decimal digits for types derived from number. If totalDigits and
fractionDigits facets both appear, the value of the totalDigits facet must be greater than or equal to the value of
the fractionDigits> facet.
Values: positiveInteger

A numerical type

<xs:simpleType name='dig10' >


<xs:restriction base='xs:decimal' >
<xs:totalDigits value='10' />
</xs:restriction>
</xs:simpleType>

whiteSpace
<xs:whiteSpace value='preserve|replace|collapse' fixed='boolean' id='ID' />

Defines rules for whiteSpace normalization. A value of preserve specifies that whitespace should be left
unchanged. A value of replace specifies that all occurrences of carriage return (#xD), line feed (#xA), and tab
(#x9) characters be converted to space (#x20) characters. A value of collapse specifies that all preceding or
trailing space (#x20) characters be removed; all carriage return (#xD), line feed (#xA), and tab (#x9) characters
be converted to space characters; and all sequences of two or more space characters be converted to a single
space character. Although strictly speaking the whiteSpace facet can be applied to any datatype for list types and
restricted datatypes with a base that is other than string or normalizedString the whiteSpace facet has a value of
collapse and may not be changed. For types derived from string any of the three possible values may be used.
For types derived from normalizedString, either replace or collapse may be used. Because of these limitations on
the use of the facet it is not generally used in schema documents because any derived type that required
particular whitespace normalization would be derived from string, normalizedString, or token as appropriate.
Values: preserve, replace, or collapse

162
The Complete Reference To Professional SOA with Visual Studio 2005

Language constructs
The XML Schema language provides support for defining simple datatypes based on existing simple datatypes.
New types can be defined to be a restriction of a type, a list of a type, or a union of two or more types.
In this section the language constructs for defining simple types, the simpleType, restriction, list, and union
elements, are listed each with syntax, description, list of attributes, list of children, and, in the case of the latter
three, examples.

simpleType
<xs:simpleType id='ID' final='list of token' name='NCName' >
<!-- annotation list restriction union -->
</xs:simpleType>

The simpleType element is used to define new types based on existing simple types. Simple type definitions
appearing as children of a schema element are named types available for use elsewhere in the schema and in
other schemas. Simple types may also appear as the children of element or attribute declarations or of other
simple type definitions, in which case they are anonymous types local to the context in which they appear.

restriction
<xs:restriction id='ID' base='QName' >
<!-- annotation enumeration fractionDigits length
maxExclusive maxInclusive maxLength minExclusive
minInclusive minLength pattern simpleType
totalDigits whiteSpace -->
</xs:restriction>

The restriction element appears as a child of the simpleType element and denotes that the simple type is a
restriction of some other simple type; that is, it has a narrower set of legal values than the base type. The simple
type on which the restricted type is based may be referred to using the base attribute or provided as an inline
anonymous type in a simpleType child element.

list
<xs:list id='ID' itemType='QName'>
<!-- annotation simpleType -->
</xs:list>

The list element appears as a child of the simpleType element and denotes that the simple type is a
whitespace-delimited list of some other, atomic simple type. The simple type on which the list is based may be
referred to using the itemType attribute or may be provided as an inline anonymous type in a simpleType child
element.

A list type

<xs:simpleType name='listOfNumbers' >


<xs:list itemType='xs:decimal' />
</xs:simpleType>

163
The Complete Reference To Professional SOA with Visual Studio 2005

Union
<xs:union id='ID' memberTypes='List of QName' >
<!-- annotation simpleType -->
</xs:union>

The union element appears as a child of the simpleType element and denotes that the simple type is a union
of two or more other simple types. The simple types on which the union is based may be referred to using the
memberTypes attribute and/or may be provided as inline anonymous types in simpleType child elements.

A numerical union

<xs:simpleType name='numbers' >


<xs:union memberTypes='xs:byte xs:short xs:int xs:long' />
</xs:simpleType>

Datatypes with Visual Studio 2005

Figure 5-13. Datatype picker

XML Schema Structures


XML Schema provides a language for describing types in XML. The language is itself expressed in XML and
includes facilities for defining structured and textual types, including types derived from other types. Structured
types are used to describe elements that have child elements or attributes associated with them. Textual types are
used for elements with text-only content and for attribute values. The language provides facilities for binding
types to elements and, in the case of textual types, attributes.

164
The Complete Reference To Professional SOA with Visual Studio 2005

The validity of an XML document is determined by a Document Type Definition (DTD) or an XML
Schema. There are several formats for data validation to choose from. A good listing for XML validation formats
can be found at http://www.oasis-open.org/cover/schemas.html. However, for the purpose of focusing on Web
service we will only be focusing on XML Schema validation.
The W3C Schema is the officially sanctioned Schema definition. Unlike DTDs, the format of W3C Schemas
follows the rules of well-formed XML documents. The Schema also allows for much more granular control over
the data that is being described. Because of the XML format and the detailed format controls, Schemas tend to be
very complex and often much longer than the XML documents that they are describing. Paradoxically, Schemas
are often much more easy for developers to read and follow, due to the less cryptic nature of the references in
Schemas compared to DTDs.
XML documents are evaluated against the rules defined in a XML schema. A well formed XML documents
that meet these rules are regarded as a valid XML document.

TIP: XML documents do not validate themselves. XML validation takes place when a document is parsed. Parsers or parser classes that
don’t support validation are called nonvalidating parsers, and parsers or classes that support validation are called validating parsers.

References to schemas are defined by creating an instance of the XMLSchemainstance namespace.

<rootelement xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"
xsi:noNamespaceSchemaLocation="examplexmlschema.xsd">

In this case, the namespace declaration reference to http://www.w3.org/2001/XMLSchema-instance resolves to


an actual document at that location, which is a brief description of the way that the W3C Schema should be
referenced. The noNamespaceSchemaLocation value tells us that there is no predefined namespace for the
Schema. This means that all of the elements in the XML document should be validated against the schema
specified. The location of the Schema we are using is ExampleXMLSchema.xsd. Because there is no path
defined, the file containing the schema should be located in the same directory as the XML file to be validated
by the Schema.
Alternatively we can also define the schema location and have the location map to a specific namespace by
using the schemaLocation attributed instead of noNamespaceSchemaLocation. We need to declare the namespace
used by the schemaLocation attribute value before we reference the schema in schemaLocation attribute. Here’s
an example of a schemaLocation assignment in a root element of an XML document:

<rootelement
xmlns:fe="http://www.mswcf.com/schemas/xmlschema"
xsi:schemaLocation="http://www.mswcf.com/schemas/xmlschema
">

An XML schema can consist of elements that are simple types or complex types. A complex type can
contain child elements in addition to attributes in its content. A simple type can contain neither child elements
nor attributes in its content. Lets us take a look at the examplexmlschema schema.

<?xml version="1.0" encoding="UTF-8"?>


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="firstelement">
<xs:complexType>
<xs:sequence>
<xs:element ref="level1"/>
</xs:sequence>

165
The Complete Reference To Professional SOA with Visual Studio 2005

<xs:attribute name="position" type="xs:boolean"


use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="level1">
<xs:complexType mixed="true">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="level2"/>
</xs:choice>
<xs:attribute name="children" use="required">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="0"/>
<xs:enumeration value="1"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="level2" type="xs:string"/>
<xs:element name="rootelement">
<xs:complexType>
<xs:sequence>
<xs:element ref="firstelement"/>
<xs:element ref="xelement"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="xelement">
<xs:complexType>
<xs:sequence>
<xs:element ref="level1"/>
</xs:sequence>
<xs:attribute name="position" type="xs:byte"
use="required"/>
</xs:complexType>
</xs:element>
</xs:schema>

The reference URL, http://www.w3.org/2001/XMLSchema, actually resolves to the W3C Website and
provides documentation for Schemas, as well as reference materials for data types and Schema namespace
formatting.

<?xml version="1.0" encoding="UTF-8"?>


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">

The first element definition describes the firstelement as a complex data type, that the element contains one
nested element called level1, and an attribute called position, and that the attribute is required.

<?xml version="1.0" encoding="utf-8"?>


<xs:element name="firstelement">
<xs:complexType>
<xs:sequence>

166
The Complete Reference To Professional SOA with Visual Studio 2005

<xs:element ref="level1"/>
</xs:sequence>
<xs:attribute name="position" type="xs:boolean"
use="required"/>
</xs:complexType>
</xs:element>

The next element describes the level1 element, that it is an optional element (minOccurs=”0”), and that the
level1 element can occur an unlimited number of times in the document (maxOccurs="unbounded"). Nested in the
level1 element is a reference to the level2 element, just as it is in the document. Next, the children attribute is
specified as required, and defined as a simple Schema data type called NMTOKEN value for the base attribute,
which is, for the purposes of this schema, a string. The children string must be one of two predefined values, "0"
and "1", as defined by the enumeration values nested inside of the restriction element.

<xs:element name="level1">
<xs:complexType mixed="true">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="level2"/>
</xs:choice>
<xs:attribute name="children" use="required">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="0"/>
<xs:enumeration value="1"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>

Even though the element level2 is defined separately to the element level1 we can still reference level2
within the level1 element as a nested element via the ref= reference.
In the following example, a schema named rootelement exists. The rooteleement must have both firstelement
and xelement nested under it to be considered a valid XML when using this schema.

<xs:element name="rootelement">
<xs:complexType>
<xs:sequence>
<xs:element ref="firstelement"/>
<xs:element ref="xelement"/>
</xs:sequence>
</xs:complexType>
</xs:element>

In the following example the required schema for the xelement is defined. The xelement contains a
complexType definition. The complexType defines a requirement for a nested element called level1 within
xelement. The xelement must also have an attribute named position of type byte value defined.

<xs:element name="xelement">
<xs:complexType>
<xs:sequence>
<xs:element ref="level1"/>
</xs:sequence>
<xs:attribute name="position" type="xs:byte"

167
The Complete Reference To Professional SOA with Visual Studio 2005

use="required"/>
</xs:complexType>
</xs:element>

Lastly we must close the schema with a equivalent schema close tag.
</xs:schema>

XSD with Visual Studio 2005


Visual Studio 2005 also provides XSD support alongside XML.

Figure 5-14. XSD designer helps to simplify development and designing of XSD

Figure 5-15. Intelligent XSD designer also allows customization of each and every element and attribute.

168
The Complete Reference To Professional SOA with Visual Studio 2005

SOAP
Simple Object Access Protocol (SOAP) is a simple and light weight protocol based on XML. SOAP relies on
XML to provide a structure for exchanging information on the Web. SOAP was designed to be kept as simple as
possible so that it can provide a messaging framework without defining the application or transport semantics.
SOAP thus is modular and very flexible because it is not tied down to any particular technological
implementation.
Due to SOAP’s simplistic definition on application and technology it can easily travel over standard
transport protocols. Commonly SOAP is used over the Web as it provides an excellent means to navigate
existing open architectures and work through firewalls between enterprises. Thus it can be easily supported and
implemented by any system capable of the basic Internet standards.
SOAP is a one-way message, a request from a client, or a response from a server is officially referred to as a
SOAP message. Every SOAP message has a mandatory Envelope element, an optional Header element, and a
mandatory Body element. Each of these elements has an associated set of rules, and understanding the rules will
help us debug our own SOAP applications.

Figure 5-16. shows the SOAP Message structure and how each element is contained within the structure.

The example below demonstrates a typical SOAP message:


POST /Accounts/Gao HTTP/1.1
Host: www.webservicebank.com
Content-Length: nnnn
Content-Type: text/xml; charset="utf-8"
SOAPAction: "Some-URI"

<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/"
SOAP:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP:Header>
<t:Transaction xmlns:t="some-URI" SOAP:mustUnderstand="1">
5
</t:Transaction>
</SOAP:Header>
<SOAP:Body>
<m:Deposit xmlns:m="Some-URI">
<m:amount>200</m:amount>

169
The Complete Reference To Professional SOA with Visual Studio 2005

</m:Deposit>
</SOAP:Body>
</SOAP:Envelope>

SOAP envelope
The envelope defines the SOAP message and is the basic unit required to facilitate exchange between two SOAP
services. It defines the specific rules required for the encapsulation of data being transferred between the
computers. The example below shows a SOAP envelope.

<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/"
SOAP:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
.
.
</SOAP:Envelope>

Every SOAP message has a root Envelope element. In contrast to other specifications, such as HTTP and
XML, SOAP does not define a traditional versioning model based on major and minor release numbers (e.g.,
HTTP 1.0 versus HTTP 1.1). Rather, SOAP uses XML namespaces to differentiate versions. The version must
be referenced within the Envelope element. For example: <SOAP-ENV:Envelope xmlns:SOAP-
ENV="http://schemas.xmlsoap.org/soap/envelope/" The SOAP 1.1 namespace URI is
http://schemas.xmlsoap.org/soap/envelope/, whereas the SOAP 1.2 namespace URI is
http://www.w3.org/2001/09/soap-envelope. If the Envelope is in any other namespace, it is considered a versioning
error.

SOAP Header
The Header element is the first immediate child element of the SOAP Envelope element. All immediate child
elements of the Header element are known as header entries. The SOAP Header element is optional. It is used to
pass data that might be inappropriate to be encoded in the body. This can include transactional information,
routing information, security credential details or encoding information. The header is required if for example
the message is encoded however when the service receives the message it needs to know how to decode the
information in the body. Embedding the encoding information in the body doesn’t make sense as the body is
already encoded. An example of the SOAP header is shown below:

<SOAP:Header>
<t:Transaction xmlns:t="some-URI" SOAP:mustUnderstand="1">
5
</t:Transaction>
</SOAP:Header>

SOAP Body
The SOAP Body contains the content of the message. There is no restriction on how the body can be encoded.
The message body can be a simple string or an array of encoded bytes. An example of the SOAP body is shown
below:

<SOAP:Body>
<m:Deposit xmlns:m="Some-URI">
<m:amount>200</m:amount>
</m:Deposit>
</SOAP:Body>

170
The Complete Reference To Professional SOA with Visual Studio 2005

All immediate child elements of the Body element are called body entries and each body entry is a separate
element within the SOAP Body element. In the context of Web services, the Body element comprises the data
specific to the actual method call, such as the Web service method name and parameters and/or return values for
the method invocation.

SOAP Fault
The SOAP Fault element is used to transport error or status information or both, within a SOAP message. The
SOAP specification specifies the format for error reporting. The fault message must follow the following
structure.

<?xml version="1.0" encoding="utf-8"?>


<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<soap:faultcode>Client.Security</soap:faultcode>
<soap:faultstring>Access denied.</soap:faultstring>
<soap:faultactor>http://abc.com</soap:faultactor>
<soap:detail>
<MyError>
<Originator>File System</Originator>
<Resource>MySecureFile.txt</Resource>
</MyError>
</soap:detail>
</soap:Fault>
</soap:Body>
</soap:Envelope>

Data Encoding
SOAP includes a built-in set of rules for encoding data types. This enables the SOAP message to indicate
specific data types, such as integers, floats, doubles, or arrays. Most of the time, the encoding rules are
implemented directly by the SOAP toolkit we choose, and are therefore hidden from us. It is nonetheless useful
to understand the basics of SOAP encoding, particularly if we are going to intercept SOAP messages and trying
to debug an application. Note also that while the W3C specification encourages the use of SOAP encoding rules,
these rules are not required; this enables us to choose a different encoding schema, should the need arise.
When exploring the SOAP encoding rules, it is important to note that the XML 1.0 specification does not
include rules for encoding data types. The original SOAP specification therefore had to define its own data
encoding rules. Subsequent to early drafts of the SOAP specification, the W3C released the XML Schema
specification. The XML Schema Part 2: Datatypes specification provides a standard framework for encoding
data types within XML documents. The SOAP specification therefore adopted the XML Schema conventions.
However, even though the latest SOAP specification adopts all the built-in types defined by XML Schema, it
still maintains its own convention for defining constructs not standardized by XML Schema, such as arrays and
references.

SOAP Request
The example below demonstrates a typical SOAP request message to invoke an XML Web Service Method.

<?xml version='1.0' encoding='UTF-8'?>


<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

171
The Complete Reference To Professional SOA with Visual Studio 2005

xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Body>
<ns1:getTemp
xmlns:ns1="urn:xmethods-Temperature"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<zipcode xsi:type="xsd:string">10016</zipcode>
</ns1:getTemp>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

There are a couple of important elements to note. First, the request includes a single mandatory Envelope
element, which in turn includes a mandatory Body element.
Second, a total of four XML namespaces are defined. Namespaces are used to disambiguate XML elements
and attributes, and are often used to reference external schemas. In our sample SOAP request, we’ll use
namespaces to disambiguate identifiers associated with the SOAP Envelope
(http://schemas.xmlsoap.org/soap/envelope/), data encoding via XML Schemas
(http://www.w3.org/2001/XMLSchema-instance and http://www.w3.org/2001/XMLSchema), and application
identifiers specific to XMethods (urn:xmethods-Temperature). This enables application modularity, while also
providing maximum flexibility for future changes to the specifications.
The Body element encapsulates the main “payload” of the SOAP message. The only element is getTemp ,
which is tied to the XMethods namespace and corresponds to the remote method name. Each parameter to the
method appears as a subelement. In our case, we have a single zip code element, which is assigned to the XML
Schema xsd:string data type and set to 10016. If additional parameters are required, each can have its own data
type.

SOAP Response
Here is the SOAP response from XMethods:

<?xml version='1.0' encoding='UTF-8'?>


<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Body>
<ns1:getTempResponse
xmlns:ns1="urn:xmethods-Temperature"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<return xsi:type="xsd:float">71.0</return>
</ns1:getTempResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Just like the request, the response includes Envelope and Body elements, and the same four XML
namespaces. This time, however, the Body element includes a single getTempResponse element, corresponding
to our initial request. The response element includes a single return element, indicating an xsd:float data type. In
the example above the temperature for zip code 10016 is 71 degrees Fahrenheit.

SOAP via HTTP


SOAP is not tied to any one transport protocol. In fact, SOAP can be transported via SMTP, FTP, IBM’s
MQSeries, or Microsoft Message Queuing (MSMQ). However, the SOAP specification includes details on
HTTP only, and HTTP remains the most popular SOAP transport protocol.

172
The Complete Reference To Professional SOA with Visual Studio 2005

Quite logically, SOAP requests are sent via an HTTP request and SOAP responses are returned within the
content of the HTTP response. While SOAP requests can be sent via an HTTP GET, the specification includes
details on HTTP POST only. (HTTP POST is preferred because most servers place a character limit on GET
requests.)

Here is a sample request sent via HTTP to the AdventureWorks Service

POST /SOAWebService/adventureworks/service.asmx HTTP/1.1


Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/GetProductName"

<?xml version="1.0" encoding="utf-8"?>


<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetProductName xmlns="http://tempuri.org/">
<productId>int</productId>
</GetProductName>
</soap:Body>
</soap:Envelope>

Here is the response from AdventureWorks Service

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>


<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetProductNameResponse xmlns="http://tempuri.org/">
<GetProductNameResult>string</GetProductNameResult>
</GetProductNameResponse>
</soap:Body>
</soap:Envelope>

.NET ASMX automatically generates the SOAP required to execute a WebMethod.

173
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 5-17. shows the auto-generated SOAP for the WebMethod in the Web Service

Invoking Web Method using .NET HTTP POST, GET and SOAP.
In listing 5-14 and listing 5-15 below, we will demonstrate Web service request using HTTP GET, POST
and SOAP. Using these different methods we will invoke the HelloWorld WebMethod which takes in a string
parameter.

Note: The URL for the listing below may vary depending on the location that it was setup in.

Listing 5-14. Demonstrates invoking a Web service through HTTP GET, POST and SOAP using Visual C#

using System;
using System.Net;
using System.IO;
using System.Text;
using System.Xml;
using System.Collections.Specialized;
using System.Diagnostics;

namespace Technology
{
/// <summary>
/// Summary description for Main.
/// </summary>
class WebMethodCall
{
static void Main(string[] args)
{

174
The Complete Reference To Professional SOA with Visual Studio 2005

//set the location for the calls


string urlGet = "http://localhost/SOAWebService/" +
"CSSimpleWebService/Service.asmx/HelloWorld?param1=kim";
string urlPost = "http://localhost/SOAWebService/" +
"CSSimpleWebService/Service.asmx/HelloWorld";
string urlSoap = "http://localhost/SOAWebService/" +
"CSSimpleWebService/Service.asmx";

Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));
Trace.AutoFlush = true;

// retrieve http result using http get


Console.WriteLine("___________ HTTP GET __________");
GetData(urlGet, "", "GET", "");

// retrieve the result using http post


Console.WriteLine("___________ HTTP POST __________");
GetData(urlPost, "application/x-www-form-urlencoded",
"POST", "param1=kim");

//retrieve the result using SOAP


Console.WriteLine("___________ SOAP _______________");
string strSoap;
string strAction;
strSoap = BuildSOAPMessage();
//we set the soap action
strAction = "SOAPAction: \"http://tempuri.org/HelloWorld\"";
GetData(urlSoap, "text/xml; charset=utf-8",
"POST", strSoap, strAction);
Console.ReadLine();
}

//send the relevant information to the service and then display the
//result from the service call
public static void GetData(string url,
string contentType, string method,
string content, params string[] headers)
{
Stream stream;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
foreach (string header in headers)
req.Headers.Add(header);
if (method.Length > 0)
req.Method = method;
if (contentType.Length > 0)
req.ContentType = contentType;
if (content.Length > 0)
{
req.ContentLength = content.Length;
stream = req.GetRequestStream();
StreamWriter sw = new StreamWriter(stream);
sw.Write(content);
sw.Close();

175
The Complete Reference To Professional SOA with Visual Studio 2005

}
DisplayRequest(req);
HttpWebResponse res = (HttpWebResponse)req.GetResponse();
DisplayResponse(res);
}

// display the result


public static void DisplayRequest(HttpWebRequest req)
{
Trace.WriteLine("*** Request Start ***");
Trace.WriteLine(req.RequestUri.ToString());
DisplayHeaders(req.Headers);
Trace.WriteLine("*** Request End ***");
}

// display the response


public static void DisplayResponse(HttpWebResponse hresp)
{
Trace.WriteLine(null);
Trace.WriteLine("*** Response Start ***");
Trace.WriteLine(hresp.StatusCode);
Trace.WriteLine(hresp.StatusDescription);
DisplayHeaders(hresp.Headers);
DisplayContent(hresp);
Trace.WriteLine("*** Response End ***");
Trace.WriteLine(null);
}

// display the header information


public static void DisplayHeaders(NameValueCollection headers)
{
foreach (string sItem in headers)
{
Trace.WriteLine(sItem + ": " + headers[sItem]);
}
}

//display the content of the response


public static void DisplayContent(HttpWebResponse response)
{
Stream stream = response.GetResponseStream();
if (stream != null)
{
StreamReader sr =
new StreamReader(stream, Encoding.ASCII);
Trace.WriteLine(sr.ReadToEnd());
}
}

//build the soap message for the service call


public static string BuildSOAPMessage()
{
MemoryStream st;

176
The Complete Reference To Professional SOA with Visual Studio 2005

string str;
byte[] buffer;
st = new MemoryStream(1024);

XmlTextWriter tr = new XmlTextWriter(st, Encoding.UTF8);


tr.WriteStartDocument();
tr.WriteStartElement("soap", "Envelope",
"http://schemas.xmlsoap.org/soap/envelope/");
tr.WriteAttributeString("xmlns", "xsi",
null, "http://www.w3.org/2001/XMLSchema-instance");
tr.WriteAttributeString("xmlns", "xsd", null,
"http://www.w3.org/2001/XMLSchema");
tr.WriteAttributeString("xmlns", "soap", null,
"http://schemas.xmlsoap.org/soap/envelope/");

tr.WriteStartElement("Body",
"http://schemas.xmlsoap.org/soap/envelope/");

tr.WriteStartElement(null, "HelloWorld",
"http://tempuri.org/");
tr.WriteElementString("param1", "kim");
tr.WriteEndElement();

tr.WriteEndElement();
tr.WriteEndDocument();
tr.Flush();
buffer = st.GetBuffer();
Decoder d = Encoding.UTF8.GetDecoder();
char[] chars = new char[buffer.Length];
d.GetChars(buffer, 2, buffer.Length - 2, chars, 0);
str = new String(chars);
tr.Close();
st.Close();
return str;
}
}
}

Listing 5-15. Demonstrates invoking a Web service through HTTP GET, POST and SOAP using Visual Basic .NET

Imports System
Imports System.Net
Imports System.IO
Imports System.Text
Imports System.Xml
Imports System.Collections.Specialized
Imports System.Diagnostics
Namespace Technology

Class WebMethodCall

Shared Sub Main()


'set the location for the calls
Dim urlGet As String = "http://localhost/SOAWebService/" + _

177
The Complete Reference To Professional SOA with Visual Studio 2005

"CSSimpleWebService/Service.asmx/HelloWorld?param1=kim"
Dim urlPost As String = "http://localhost/SOAWebService/" + _
"CSSimpleWebService/Service.asmx/HelloWorld"
Dim urlSoap As String = "http://localhost/SOAWebService/" + _
"CSSimpleWebService/Service.asmx"
Trace.Listeners.Add(New TextWriterTraceListener(Console.Out))
Trace.AutoFlush = True

' retrieve http result using http get


Console.WriteLine("___________ HTTP GET __________")
GetData(urlGet, "", "GET", "")

' retrieve the result using http post


Console.WriteLine("___________ HTTP POST __________")
GetData(urlPost, "application/x-www-form-urlencoded", _
"POST", "param1=kim")

'retrieve the result using SOAP


Console.WriteLine("___________ SOAP _______________")
Dim strSoap As String
Dim strAction As String
strSoap = BuildSOAPMessage()
'we set the soap action
strAction = "SOAPAction: ""http://tempuri.org/HelloWorld"""
GetData(urlSoap, "text/xml; charset=utf-8", _
"POST", strSoap, strAction)
Console.ReadLine()
End Sub

'send the relevant information to the service and then display the
'result from the service call
Public Shared Sub GetData(ByVal url As String, _
ByVal contentType As String, ByVal method As String, _
ByVal content As String, ByVal ParamArray headers As String())
Dim stream As Stream
Dim req As HttpWebRequest = _
CType(WebRequest.Create(url), HttpWebRequest)
For Each header As String In headers
req.Headers.Add(header)
Next
If method.Length > 0 Then
req.Method = method
End If
If contentType.Length > 0 Then
req.ContentType = contentType
End If
If content.Length > 0 Then
req.ContentLength = content.Length
stream = req.GetRequestStream
Dim sw As StreamWriter = New StreamWriter(stream)
sw.Write(content)
sw.Close()
End If

178
The Complete Reference To Professional SOA with Visual Studio 2005

DisplayRequest(req)
Dim res As HttpWebResponse = _
CType(req.GetResponse, HttpWebResponse)
DisplayResponse(res)
End Sub

'display the result


Public Shared Sub DisplayRequest(ByVal req As HttpWebRequest)
Trace.WriteLine("*** Request Start ***")
Trace.WriteLine(req.RequestUri.ToString)
DisplayHeaders(req.Headers)
Trace.WriteLine("*** Request End ***")
End Sub

'display the response


Public Shared Sub DisplayResponse(ByVal hresp As HttpWebResponse)
Trace.WriteLine(Nothing)
Trace.WriteLine("*** Response Start ***")
Trace.WriteLine(hresp.StatusCode)
Trace.WriteLine(hresp.StatusDescription)
DisplayHeaders(hresp.Headers)
DisplayContent(hresp)
Trace.WriteLine("*** Response End ***")
Trace.WriteLine(Nothing)
End Sub

'display the header information


Public Shared Sub DisplayHeaders _
(ByVal headers As NameValueCollection)
For Each sItem As String In headers
Trace.WriteLine(sItem + ": " + headers(sItem))
Next
End Sub

'display the content of the response


Public Shared Sub DisplayContent _
(ByVal response As HttpWebResponse)
Dim stream As Stream = response.GetResponseStream
If Not (stream Is Nothing) Then
Dim sr As StreamReader = _
New StreamReader(stream, Encoding.ASCII)
Trace.WriteLine(sr.ReadToEnd)
End If
End Sub

'build the soap message for the service call


Public Shared Function BuildSOAPMessage() As String
Dim st As MemoryStream
Dim str As String
Dim buffer As Byte()
st = New MemoryStream(1024)
Dim tr As XmlTextWriter = New XmlTextWriter(st, Encoding.UTF8)
tr.WriteStartDocument()

179
The Complete Reference To Professional SOA with Visual Studio 2005

tr.WriteStartElement("soap", "Envelope", _
"http://schemas.xmlsoap.org/soap/envelope/")
tr.WriteAttributeString("xmlns", "xsi", Nothing, _
"http://www.w3.org/2001/XMLSchema-instance")
tr.WriteAttributeString("xmlns", "xsd", Nothing, _
"http://www.w3.org/2001/XMLSchema")
tr.WriteAttributeString("xmlns", "soap", Nothing, _
"http://schemas.xmlsoap.org/soap/envelope/")
tr.WriteStartElement("Body", _
"http://schemas.xmlsoap.org/soap/envelope/")
tr.WriteStartElement(Nothing, "HelloWorld", _
"http://tempuri.org/")
tr.WriteElementString("param1", "kim")
tr.WriteEndElement()
tr.WriteEndElement()
tr.WriteEndDocument()
tr.Flush()
buffer = st.GetBuffer
Dim d As Decoder = Encoding.UTF8.GetDecoder
Dim chars(buffer.Length) As Char
d.GetChars(buffer, 2, buffer.Length - 2, chars, 0)
str = New String(chars)
tr.Close()
st.Close()
Return str
End Function
End Class
End Namespace
The main code responsible is the GetData function which is used send data to the web service as well as
retriving a response. This is achieved through the use of HttpWebRequest. We use WebRequest.Create(url) to
create an object of request to the Web service. Through this HttpWebRequest request object we’re able to set the
actual method of request whether its GET or POST. As well as the content type of the actual request. By using
GetRequestStream() we are able to obtain a reference to the actual request stream itself. Through the request
stream we can write everything that we wanted to send to Web service into the stream.
Once the request is sent we can use the same request object’s GetResponse() to obtain the HttpWebResponse
object. This will contain all the response information returned by the web service.

Listing 5-16. Demonstrates the GetData function in C#

public static void GetData(string url,


string contentType, string method,
string content, params string[] headers)
{
Stream stream;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
foreach (string header in headers)
req.Headers.Add(header);
if (method.Length > 0)
req.Method = method;
if (contentType.Length > 0)
req.ContentType = contentType;
if (content.Length > 0)
{

180
The Complete Reference To Professional SOA with Visual Studio 2005

req.ContentLength = content.Length;
stream = req.GetRequestStream();
StreamWriter sw = new StreamWriter(stream);
sw.Write(content);
sw.Close();
}
DisplayRequest(req);
HttpWebResponse res = (HttpWebResponse)req.GetResponse();
DisplayResponse(res);
}

Listing 5-17. Demonstrates the GetData function in Visual Basic .NET

Public Shared Sub GetData(ByVal url As String, _


ByVal contentType As String, ByVal method As String, _
ByVal content As String, ByVal ParamArray headers As String())
Dim stream As Stream
Dim req As HttpWebRequest = _
CType(WebRequest.Create(url), HttpWebRequest)
For Each header As String In headers
req.Headers.Add(header)
Next
If method.Length > 0 Then
req.Method = method
End If
If contentType.Length > 0 Then
req.ContentType = contentType
End If
If content.Length > 0 Then
req.ContentLength = content.Length
stream = req.GetRequestStream
Dim sw As StreamWriter = New StreamWriter(stream)
sw.Write(content)
sw.Close()
End If
DisplayRequest(req)
Dim res As HttpWebResponse = _
CType(req.GetResponse, HttpWebResponse)
DisplayResponse(res)
End Sub
The BuildSOAPMessage function is used to build up the SOAP request that we will need to send to the Web
service. Essentially we need to send a request that is compliant with the SOAP schema shown below:
POST /CSSimpleWebService/Service.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/HelloWorld"

<?xml version="1.0" encoding="utf-8"?>


<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>

181
The Complete Reference To Professional SOA with Visual Studio 2005

<HelloWorld xmlns="http://tempuri.org/">
<param1>string</param1>
</HelloWorld>
</soap:Body>
</soap:Envelope>
The BuildSOAPMessage function return a string that is used as the SOAP request. The end result of this is a
SOAP request that is shown below:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<HelloWorld xmlns="http://tempuri.org/">
<param1>kim</param1>
</HelloWorld>
</soap:Body>
</soap:Envelope>

Listing 5-18. Demonstrates building a SOAP request message using Visual C#

public static string BuildSOAPMessage()


{
MemoryStream st;
string str;
byte[] buffer;
st = new MemoryStream(1024);

XmlTextWriter tr = new XmlTextWriter(st, Encoding.UTF8);


tr.WriteStartDocument();
tr.WriteStartElement("soap", "Envelope",
"http://schemas.xmlsoap.org/soap/envelope/");
tr.WriteAttributeString("xmlns", "xsi",
null, "http://www.w3.org/2001/XMLSchema-instance");
tr.WriteAttributeString("xmlns", "xsd", null,
"http://www.w3.org/2001/XMLSchema");
tr.WriteAttributeString("xmlns", "soap", null,
"http://schemas.xmlsoap.org/soap/envelope/");

tr.WriteStartElement("Body",
"http://schemas.xmlsoap.org/soap/envelope/");

tr.WriteStartElement(null, "HelloWorld",
"http://tempuri.org/");
tr.WriteElementString("param1", "kim");
tr.WriteEndElement();

tr.WriteEndElement();
tr.WriteEndDocument();
tr.Flush();
buffer = st.GetBuffer();
Decoder d = Encoding.UTF8.GetDecoder();
char[] chars = new char[buffer.Length];
d.GetChars(buffer, 2, buffer.Length - 2, chars, 0);
str = new String(chars);

182
The Complete Reference To Professional SOA with Visual Studio 2005

tr.Close();
st.Close();
return str;
}

Listing 5-19. Demonstrates building a SOAP request message using Visual Basic .NET

Public Shared Function BuildSOAPMessage() As String


Dim st As MemoryStream
Dim str As String
Dim buffer As Byte()
st = New MemoryStream(1024)
Dim tr As XmlTextWriter = New XmlTextWriter(st, Encoding.UTF8)
tr.WriteStartDocument()
tr.WriteStartElement("soap", "Envelope", _
"http://schemas.xmlsoap.org/soap/envelope/")
tr.WriteAttributeString("xmlns", "xsi", Nothing, _
"http://www.w3.org/2001/XMLSchema-instance")
tr.WriteAttributeString("xmlns", "xsd", Nothing, _
"http://www.w3.org/2001/XMLSchema")
tr.WriteAttributeString("xmlns", "soap", Nothing, _
"http://schemas.xmlsoap.org/soap/envelope/")
tr.WriteStartElement("Body", _
"http://schemas.xmlsoap.org/soap/envelope/")
tr.WriteStartElement(Nothing, "HelloWorld", _
"http://tempuri.org/")
tr.WriteElementString("param1", "kim")
tr.WriteEndElement()
tr.WriteEndElement()
tr.WriteEndDocument()
tr.Flush()
buffer = st.GetBuffer
Dim d As Decoder = Encoding.UTF8.GetDecoder
Dim chars(buffer.Length) As Char
d.GetChars(buffer, 2, buffer.Length - 2, chars, 0)
str = New String(chars)
tr.Close()
st.Close()
Return str
End Function

183
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 5-18. Shows the result from the execution

Listing 5-20. Demonstrates a HTTP GET request and response

*** Request Start ***


http://localhost/SOAWebService/CSSimpleWebService/
Service.asmx/HelloWorld?param1=kim
*** Request End ***

*** Response Start ***


OK
OK
MicrosoftOfficeWebServer: 5.0_Pub
Content-Length: 94
Cache-Control: private, max-age=0
Content-Type: text/xml; charset=utf-8
Date: Wed, 07 Jun 2006 08:52:24 GMT
Server: Microsoft-IIS/6.0

184
The Complete Reference To Professional SOA with Visual Studio 2005

X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://tempuri.org/">Hello kim</string>
*** Response End ***

Listing 5-21. Demonstrates a HTTP POST request and response

*** Request Start ***


http://localhost/SOAWebService/CSSimpleWebService/Service.asmx/HelloWorld
Content-Type: application/x-www-form-urlencoded
Host: localhost
Content-Length: 10
Expect: 100-continue
*** Request End ***

*** Response Start ***


OK
OK
MicrosoftOfficeWebServer: 5.0_Pub
Content-Length: 94
Cache-Control: private, max-age=0
Content-Type: text/xml; charset=utf-8
Date: Wed, 07 Jun 2006 08:52:24 GMT
Server: Microsoft-IIS/6.0
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://tempuri.org/">Hello kim</string>
*** Response End ***

Listing 5-22. Demonstrates a SOAP request and response

*** Request Start ***


http://localhost/SOAWebService/CSSimpleWebService/Service.asmx
SOAPAction: "http://tempuri.org/HelloWorld"
Content-Type: text/xml; charset=utf-8
Host: localhost
Content-Length: 1024
Expect: 100-continue
*** Request End ***

*** Response Start ***


OK
OK
MicrosoftOfficeWebServer: 5.0_Pub
Content-Length: 361
Cache-Control: private, max-age=0
Content-Type: text/xml; charset=utf-8
Date: Wed, 07 Jun 2006 08:52:24 GMT
Server: Microsoft-IIS/6.0
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
<?xml version="1.0" encoding="utf-8"?><soap:Envelope

185
The Complete Reference To Professional SOA with Visual Studio 2005

xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body>
<HelloWorldResponse xmlns="http://tempuri.org/">
<HelloWorldResult>Hello kim</HelloWorldResult></HelloWorldResponse>
</soap:Body></soap:Envelope>
*** Response End ***

Web Services Description Language (WSDL)


The WSDL itself is an XML document. The WSDL document is used to describe a Web service, it defines the
methods that are available in a Web service and the parameters these methods take and the data type that is
returned by each method. In short it defines a contract to the requesting service consumer of the functionalities
that the service provider provides.
WSDL describes four critical pieces of data:

* Interface information describing all publicly available functions


* Data type information for all message requests and message responses

* Binding information about the transport protocol to be used


* Address information for locating the specified service

By using WSDL, a client application can locate a Web service and invoke any method that is defined in the
WSDL. Visual Studio comes with WSDL to code tool which we can use to convert these public methods defined
in the WSDL into code. This is called proxying and it allows us to integrate new Web services with little or no
manual code. WSDL is an critical part of the success of XML Web service this is because it provides a common
language to describe the implementation.
In the case of .NET, WSDL generation is automatic, having defined our code and what we want to expose in
the Web service. We can simply access the .asmx web service and use the ?wsdl syntax to retrieve the WSDL
document for example http://localhost/adventureworks/service.asmx?wsdl.
The WSDL specification defined by The World Wide Web Consortium (W3C)
(http://www.w3.org/TR/wsdl) defines six major elements:

definitions
The definitions element is the first element. It must be the root element of the entire WSDL document. It
defines the name of the Web service and holds information about the service and its attributes. It also defines
multiple namespaces that are used throughout the WSDL document. The use of namespaces is important for
differentiating between different elements, and it enables the document to reference multiple external
specifications, including the WSDL specification, the SOAP specification, and the XML Schema specification.
In the case of demonstrating the definitions element in WSDL from the Adventure works. The definitions
element specifies that the WSDL document is the AdventureWorks Service. It also specifies numerous
namespaces that will be used throughout the remainder of the document:

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:tns="http://tempuri.org/"
xmlns:s="http://www.w3.org/2001/XMLSchema"

186
The Complete Reference To Professional SOA with Visual Studio 2005

xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
targetNamespace="http://tempuri.org/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">

types
The types element is used to describe the data types that are used to exchange messages between the client and the
server. WSDL uses the W3C XML Schema specification as its default specification.
<wsdl:types>
<s:schema elementFormDefault="qualified"
targetNamespace="http://tempuri.org/">
<s:element name="GetProductName">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1"
name="productId" type="s:int" />
</s:sequence>
</s:complexType>

</s:element>
<s:element name="GetProductNameResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1"
name="GetProductNameResult" type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="string" nillable="true" type="s:string" />

</s:schema>
</wsdl:types>

message
The message element serves as a cross reference between the message and its definition within the schema.
Because we can use multiple schema definition formats within a WSDL document, it is necessary to have a
common way of identifying the messages. The message element provides this common level of abstraction that
will be referenced in other parts of the WSDL document.

<wsdl:message name="GetProductNameSoapIn">
<wsdl:part name="parameters" element="tns:GetProductName" />
</wsdl:message>
<wsdl:message name="GetProductNameSoapOut">
<wsdl:part name="parameters" element="tns:GetProductNameResponse" />
</wsdl:message>
<wsdl:message name="GetProductNameHttpGetIn">

<wsdl:part name="productId" type="s:string" />


</wsdl:message>
<wsdl:message name="GetProductNameHttpGetOut">

187
The Complete Reference To Professional SOA with Visual Studio 2005

<wsdl:part name="Body" element="tns:string" />


</wsdl:message>
<wsdl:message name="GetProductNameHttpPostIn">
<wsdl:part name="productId" type="s:string" />
</wsdl:message>
<wsdl:message name="GetProductNameHttpPostOut">

<wsdl:part name="Body" element="tns:string" />


</wsdl:message>

.NET’s ASMX generates the WSDL, automatically catering to the three types of calls that can be made to
the web service, SOAP GetProductNameSoap, HTTP GET GetProductNameHttpGet, and HTTP POST
GetProductNameHttpPost.
Each of these messages contains a single part element. For the request, the part specifies the function
parameters. The part element’s type attribute specifies an XML Schema data type. The value of the type attribute
must be specified as an XML Schema QName - this means that the value of the attribute must be namespace-
qualified. If the function expects multiple arguments or returns multiple values, we can specify multiple part
elements.

portType
A portType can be thought of as an interface definition in which each method can be defined as an operation. A
port type is composed of a set of operation elements that define a particular action. The operation elements are
composed of the messages defined within the WSDL document. WSDL defines four types of operations, known
as operation types these are: Request/response, One way, Solicit/response and Notification.

* Request-response RPC-style communication in which the client makes a request and the server issues a
corresponding response.

* One-way Document-style communication in which the client sends a message but does not receive a response
from the server indicating the result of the processed message.

* Solicit-response the opposite of the request-response operation. The server sends a request, and the client sends
back a response.

* Notification The opposite of the one-way operation. The server sends a document-style communication to the
client.

A portType can (and frequently does) define multiple operations.

<wsdl:portType name="ServiceSoap">
<wsdl:operation name="GetProductName">
<wsdl:input message="tns:GetProductNameSoapIn" />
<wsdl:output message="tns:GetProductNameSoapOut" />
</wsdl:operation>
</wsdl:portType>
<wsdl:portType name="ServiceHttpGet">

<wsdl:operation name="GetProductName">
<wsdl:input message="tns:GetProductNameHttpGetIn" />
<wsdl:output message="tns:GetProductNameHttpGetOut" />
</wsdl:operation>
</wsdl:portType>

188
The Complete Reference To Professional SOA with Visual Studio 2005

<wsdl:portType name="ServiceHttpPost">
<wsdl:operation name="GetProductName">
<wsdl:input message="tns:GetProductNameHttpPostIn" />
<wsdl:output message="tns:GetProductNameHttpPostOut" />

</wsdl:operation>
</wsdl:portType>

In the above example the portType element defines a single operation, called GetProductName. The
operation itself consists of a single input message GetProductNameSoapIn or GetProductNameHttpGetIn or
GetProductNameHttpPostIn and a single output message of GetProductNameSoapOut or
GetProductNameHttpGetOut or GetProductNameHttpPostOut.

binding
The binding element contains binding definitions for binding a protocol such as SOAP to a particular
bindingType. The binding definitions specify message formatting and protocol details. For example, the binding
information specifies whether you can access an instance of a portType in an RPC-like manner.
The binding definitions also indicate the number of network communications required to perform a
particular action. For example, a SOAP RPC call over HTTP might involve one HTTP communication
exchange, but that same call over SMTP would involve two discrete SMTP communication exchanges.

<wsdl:binding name="ServiceSoap" type="tns:ServiceSoap">


<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="GetProductName">
<soap:operation soapAction="http://tempuri.org/GetProductName"
style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>

<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>

service
A service is a group of related ports and is defined by the service element. A port is a particular endpoint for the
Web service that is referenced by a single address. Ports defined within a particular service are as output cannot
serve as the input of another.

<wsdl:service name="Service">
<wsdl:port name="ServiceSoap" binding="tns:ServiceSoap">
<soap:address
location="http://localhost/SOAWebService/adventureworks/service.asmx" />
</wsdl:port>

<wsdl:port name="ServiceSoap12" binding="tns:ServiceSoap12">


<soap12:address
location="http://localhost/SOAWebService/adventureworks/service.asmx" />

189
The Complete Reference To Professional SOA with Visual Studio 2005

</wsdl:port>
<wsdl:port name="ServiceHttpGet" binding="tns:ServiceHttpGet">
<http:address
location="http://localhost/SOAWebService/adventureworks/service.asmx" />
</wsdl:port>
<wsdl:port name="ServiceHttpPost" binding="tns:ServiceHttpPost">
<http:address
location="http://localhost/SOAWebService/adventureworks/service.asmx" />
</wsdl:port>

</wsdl:service>

.NET Web Service WSDL


In .NET the ASMX file autogenerates the WSDL document upon request. A developer does not need to concern
themselves with the definition of the document. .NET creates the WSDL document based on the WebMethod
call.
The syntax for WSDL is http://server/webServiceName.asmx?WSDL

Figure 5-19. shows the autogenerated .NET WSDL document.

UDDI v3
UDDI is a technical specification for describing, discovering, and integrating web services. UDDI is therefore a
critical part of the emerging web service protocol stack, enabling companies to both publish and find web
services.
At its core, UDDI consists of two parts:

* UDDI was originally developed as a distributed directory for businesses and web services. The directory has a
set of API to allow searching existing data and publishing new data.
* The UDDI Business Registry is a fully operational implementation of the UDDI specification. Launched in
May 2001 by Microsoft and IBM.

In 2005 UDDI v3 was launched. UDDI Version 3 (http://uddi.org/pubs/uddi_v3.htm) builds on the previous
vision of a “meta service” for locating web services by enabling robust queries against rich metadata. With a vast

190
The Complete Reference To Professional SOA with Visual Studio 2005

array of enhancements, including multi-registry topologies, increased security features, improved WSDL
support, a new subscription API and core information model advances. The Version 3 specification offers clients
and implementers a comprehensive and complete blueprint of a description and discovery foundation for a
diverse set of Web services architectures.
The data captured within UDDI is divided into three main categories:

White pages: This includes general information about a specific company - for example,
business name, business description, contact information, address and phone numbers. It can
also include unique business identifiers, such as a Dun & Bradstreet D-U-N-S® Number.
Yellow pages: This includes directory for the company and the service offered as well as their
contact details. For example, this information can include business, industry, product, or
geographic codes can all be searched on.
Green pages: This category contains technical information about a web service. Generally,
this includes a pointer to an external specification and an address for invoking the web
service. UDDI is not restricted to describing web services based on SOAP. Rather, UDDI can
be used to describe any service, from a single web page or email address all the way up to
SOAP, CORBA, and Java RMI services.

Support for digital signature


One of the major improvement in the Version 3 specification for UDDI is its support now for digital signatures.
This dramatically improves data integrity and data authenticity through digital signing. This provides confidence
to the register consumer that the data has not altered and it is exactly as the publisher intended it to be.
Consumers can now have confidence that through digital signing that publishers are not being
misrepresented by someone else pretending to be the UDDI entity. Once the publisher has signed the response
data the consumer can be confident of its validity. In version 3 data can now also be shared between registries
and have confidence that no data had been altered during the process. This allows registries to network together
and thus provide a higher level of integrity of service to its consumers.
Ultimately, by adopting digital signature, we can provide non-repudiation requirements for e-commerce
where digital signatures are a must. This allows UDDI to work with Web service at a new trusted level.
Full coverage of UDDI is out of scope in this book for full specification you can go to
http://uddi.org/pubs/uddi_v3.htm

UDDI SDK
Microsoft provides a UDDI SDK for developing UDDI-enabled applications. The UDDI SDK includes both a
.NET and a COM-based object model for simplifying interaction with the registry. It also includes a standalone
UDDI registry for development purposes.
As at the time of writing, the UDDI SDK v2.0 is still in beta and is distributed as a separate download.
Microsoft currently does not have plans to ship the release to manufacture (RTM) version of the SDK in
conjunction with the .NET Framework. Instead, it plans to ship the RTM version of the UDDI .NET object
model on a release schedule separate from that of the .NET Framework..
The UDDI .NET SDK V2.0 Beta 1 can be downloaded from Microsoft.

191
The Complete Reference To Professional SOA with Visual Studio 2005

WS-* Standards
The WS-* family of standards provides a set of XML and Web Services standard formats, grammars, and
message sequences for communicating policy information and addressing the various security challenges across
different types of networks. This family of standards was introduced in 2002 by IBM and Microsoft as part of
their overall Web Services roadmap. The roadmap introduced WS-Security, which built on XML encryption and
XML signature to create a foundation layer. It also introduced several higher-level standards including:

WS-Policy: Defines the syntax and grammar for communicating policies as a set of
assertions.
WS-Security: Defines the syntax and grammar for communicating security tokens, digital
signatures, and message encryption information
WS-Trust: Defines the syntax and grammar for establishing trust relationships and
communicating with third-party trust brokers
WS-SecureConversation: Improves the efficiency of exchanges by defining a way to
exchange multiple messages within a single context or session
WS-Federation: Lays the foundation for creating federated trust relationships across multiple
domains

Since the initial roadmap was introduced, a number of supporting standards and standards proposals have
been introduced. These Include:

WS-SecurityPolicy: Builds on WS-Policy, adding security-specific assertion elements for


communicating security token, integrity, and confidentiality constraints.
WS-PolicyAttachment: Defines the mechanisms for associating policies with a subject
inherently, as part of its intrinsic definition, or through either its associated Web Services
Description Language (WSDL) or Universal Description, Discovery, and Integration (UDDI)
description
XKMS: Is the XML key management specification (XKMS) builds on XML signature and
XML encryption, providing a service for registering and distributing public keys for those
standards.
SAML: The Security Assertion Markup language (SAML) defines a framework for
exchanging authentication and authorization information across domains in the form of
Assertions rather than identities or traditional security tokens.
XACML: The eXtensible Access Control Markup Language (XACML) defines a hierarchical
model for defining and evaluating policies.

We will be focusing on the coverage of these standards using WSE and WCF in later chapters.

Summary
The HTTP is a World Wide Web Consortium (W3C) standard protocol for transferring documents on the
Internet. XML Web services use HTTP for communication. It is a generic, stateless, protocol, which can be used
for many tasks in addition its original use for hypertext.

192
The Complete Reference To Professional SOA with Visual Studio 2005

A resource location is specified in HTTP through a mechanism known as a Uniform Resource Locator
(URL). Strictly speaking, the mechanism that is used in HTTP is a Uniform Resource Identifier (URI), but we
can also think of it as a URL.
Web services use xml to provide interoperability between different platforms. This is achieved through the
use of SOAP, XML and XSD. Considering the central role that XML plays in XML Web services, it is useful to
review some of its important concepts:

* All XML documents must be well-formed. For a document to be well-formed, it must adhere to the following
rules:
* There must be a single root element.

* XML documents are trees, and not forests.

* All elements must be closed, unlike HTML, where many elements (example: <BR>) are not required to be
closed.

* Capitalization of opening and closing tags of elements must be consistent.


* Many browsers allow inconsistent casing when using HTML elements (example: <table>...</TABLE>), but
inconsistent casing is not allowed in XML.

* Elements must be nested correctly.


* Attribute values must be enclosed in quotes. Many browsers allow attribute values to be unquoted, but
unquoted attribute values are not allowed in XML.

* An attribute cannot be repeated in an element.

The service description is created by using the Web Service Description Language (WSDL), which is an
XML-based language. Within the WSDL documents, we can define the XSD schemas that describe the data
types and document structures that are allowed in XML documents. XSD schemas validate XML documents in a
mechanical way. This frees the programmer from the error-prone task of correctly parsing and validating a
complex document structure.

193
The Complete Reference To Professional SOA with Visual Studio 2005

Chapter 6 Database
Programming with ADO.NET
As application development has evolved, new applications have become loosely coupled, often based on the
Web application model. Many applications today rely on XML to encode and transport data over the network.
Web applications are also beginning to rely on HTTP to communicate between tiers. This new model is very
different to the connected and tightly coupled style of programming that represents the client/server relationships
of the past.
Retrieving and processing data seems like a fairly straightforward task in a client/server model, but over the
past decade the way applications use data has changed repeatedly. Developers have moved from simple client
applications that use local databases to distributed systems that rely on centralized databases on dedicated
servers. At the same time, data access technologies have evolved. If you’ve worked with Microsoft languages for
some time, you’ve most likely heard of (and possibly used) a stream of data access technologies that includes
ODBC, DAO, RDO, RDS, and ADO.
In order to meet today’s needs Microsoft has recognized the need for a new programming model for data
access and built it upon the .NET Framework. The Framework would ensure that the data access technology
would remain consistent, as components could be easily shared amongst common type system, design patterns
and naming conventions. ADO.NET was created to address these issues and meet the need of today’s
programming model.
In this chapter we will be covering ADO.NET in detail and how to interact with the database using
DataSets. ADO.NET is an important area as in our Web service development we undoubtedly will be using
database at some stage.

ADO.NET
ADO.NET enables data-centric applications to connect to various data sources and retrieve, manipulate, and
update data. ADO.NET uses XML to transfer data across applications and data sources. ADO.NET provides
consistent access to data sources such as Microsoft SQL Server and XML, as well as to data sources exposed
through OLE DB and ODBC. Data-sharing consumer applications can use ADO.NET to connect to these data
sources and retrieve, manipulate, and update the data that they contain.
One of the advantages of ADO.NET is that it supports a disconnected architecture. Using a disconnected
architecture, applications connect to a database server only to retrieve or update the data. This allows us to
reduce the number of open connections to various database servers. ADO.NET also provides a common data
representation that enables us to access data from multiple and various types of data sources and have it appear
as one entity.
ADO. NET consists of managed classes that allow .NET applications to connect to data sources (usually
relational databases), execute commands, and manage disconnected data. The advantage of ADO.NET is that it
allows us to write the same data access code in web applications that we write for client-server desktop
applications.
ADO.NET provides a separation between data access and data manipulation. ADO.NET includes .NET
Framework data providers for connection to different databases, executing commands on these databases and
retrieving the results. The results retrieved can either be processed directly as it is being retrieved through using
ADO.NET DataReaders or placed into an ADO.NET DataSet object so that it can be returned to the user and

194
The Complete Reference To Professional SOA with Visual Studio 2005

processed later. We can also combine data from multiple sources or data that are from other applications. The
ADO.NET DataSet can also be used to manage data local to the application or sourced from a XML file.
The ADO.NET classes are defined in the System.Data namespace. This namespace contains classes such as
DataSet and DataTable which are all part of the ADO.NET architecture. To use ADO.NET is a simple matter of
adding a reference to the System.Data namespace within our application. In a later section we will be discussing
the ADO.NET architecture in detail.

What is New in .NET 2.0


Developers who have used .NET 1.1 will be familiar with the ADO.NET architecture and structure. So then what
is new in .NET 2.0?

Async Data Access


The earlier versions of ADO.NET 1.0 and 1.1 did not support the async data access model. A database
connection could only process commands in a series. This meant that each command must terminate before the
next can begin. This is model is often enough for a simple transaction processing scenarios where we open a
connection, write a record and then close the connection again. But it was not possible if we want to perform a
series of operations in parallel. Until now.
When using the SqlClient data provider under ADO.NET 2.0, we can now perform true non-blocked async
I/O with the SQL Server database. This is enabled by initializing the connection using the phrase async=true in
the connection string, and then by taking advantage of new methods in the data provider that can express what
we want to perform operations asynchronously.
In the past we used to have the synchronous ExecuteReader method, we now have two new methods,
BeginExecuteReader and EndExecuteReader. Similarly, there's now a BeginExecuteNonQuery /
EndExecuteNonQuery pair, and a BeginExecuteXmlReader / EndExecuteXmlReader pair. The Begin... methods
take all the input parameters and the End... methods take all the output parameters and provide the return value.
These async commands work against SQL Server 7.0, SQL Server 2000 and SQL Server 2005.

Metadata Schemas
When we use Visual Studio 2005 to configuring ADO.NET 2.0 to talk to a live database within our application,
the IDE can pre-populate many of the database access parameters. This is because ASP.NET 2.0 and its data
providers can access metadata about that database, which the IDE can take advantage of to help us with drag-
and-drop functionality as we link the database to our app. The result is that Visual Studio 2005 is more helpful,
when it comes to database development, than any previous version.
By using that metadata, our app can become more flexible, such as being able to link dynamically to
databases and automatically configure itself to discover and use the appropriate tables, columns, stored
procedures and triggers. Alternatively, we can use the metadata to help our users customize their interactions
with databases, such as by creating reports that take advantage of tables or columns that we didn't know about
when we had built our application.
This metadata comes from the database engine itself. Every modern relational database or data source has its
own way of expressing metadata to its access clients. SQL Server 2005, for example, uses a different metadata
system than SQL Server 2000, but both are understood by SqlClient. Oracle has its own metadata system, which
is read the OracleClient data provider.
In ADO.NET 2.0 there is the System.Data.Common.DbMetaDataCollectionNames class which is used to store
the metadata information. Each data provider can import metadata information from the database and populate
the class. The SqlClient and OracleClient data providers included with ADO.NET 2.0 do this. These new

195
The Complete Reference To Professional SOA with Visual Studio 2005

metadata classes work with all data sources supported by ADO.NET 2.0 data providers, and not limited to just
SQL Server 2005.

Query Notification
A lot of applications use databases to store lookup information. This information includes product codes, product
categories, branch locations, state abbreviation, or even office locations. These items don’t often change, so to
improve performance we like to cache this information within the application. However in the past with
Framework 1.0 and 1.1 it was not possible to know when one of those rarely changed tables had actually
changed, so that we could reload the cache.

Figure 6-1: query notification

ADO.NET 2.0 and SQL Server 2005 solve this problem with their new Query Notification signaling
mechanism shown in figure 6-1. The ASP.NET 2.0 cache can now register a request for notification with the
SQL Server 2005 database, through a new SqlNotificationRequest class contained within the SqlCommand. The
SQL Server database will remember that query notification, along with the query and its rowset. If that rowset
changes, SQL Server 2005 will send back a notification to the client's SqlDependency class using the new SQL
Server Service Broker.

Note: This only works with SQL Server 2005;

Multiple Active Result Sets


The original ADO permitted us to maintain multiple active cursorless result sets within a database, but
ADO.NET 1.0 / 1.1 did not. If we tried to open more than one cursorless result set, ADO.NET 1.0 / 1.1 returned
an error condition. The upshot was that in ADO.NET 1.0/1.1, if we needed multiple result sets, we had to close
one SqlDataReader before opening another.
When used in conjunction with SQL Server 2005, ADO.NET 2.0 solves that problem by allowing us to open
multiple result sets at the same time.

196
The Complete Reference To Professional SOA with Visual Studio 2005

User Defined, XML Data Types


In SQL server 2005 we can now use ADO.NET 2.0 to define custom defined data types and XML data types. User
defined types were standardized by the SQL:2003 specification published by the ISO. We can now access them by
using the SqlUdt namespace in the System.Data.SqlTypes namespace, the result is a .NET Object. Similarly, there's a
new SqlXml namespace for XML data; the results are returned as a .NET String. These match up with the new XML
data type within SQL Server 2005; this is a first-class data type, not just something cobbled together from strings, and
we can also access XML using the new SqlCommand.ExecuteXmlReader method.

The ADO.NET Architecture

Figure 6-2 ADO.NET Architecture

ADO.NET enables data transfer between components, such as data sources, DataSets, and the applications that
request data. Together, all of these components constitute the ADO.NET architecture. Figure 6-2 displays the
ADO.NET architecture.Data Sources
A data source is a database server for which the .NET Framework provides a data provider or an XML file.
To access a data source, we create a connection to the data source using the data providers of ADO.NET. The
ADO.NET data providers enable us to establish a connection with a data source and perform other tasks, such as
executing SQL commands on data sources. We will learn more about data providers later in this lesson.

.NET DataSets
The datacentric applications that we create usually need to access data from multiple tables. In addition, we
might need to process data from multiple tables as one entity. For example, an organization might need to access
the names of all its customers and the quantity of each product supplied to them.
The DataSet was explicitly designed so that data access is independent of the data source. As a result the
DataSet can work with multiple and differing data sources or using XML data or managed data local to the
application. It can contain a collection of one or more DataTable objects that is made up of rows and columns of
data. The Datatable object also supports primary key, foreign key and constraint and relation information about
the data.

197
The Complete Reference To Professional SOA with Visual Studio 2005

Data Providers

Figure 6-3 shows ADO.NET Data Access

.NET data providers form the interface between the application and the data source. The data providers that the
.NET Framework provides allow us to connect to a data source, execute commands, and retrieve results. We can
either directly work with the data retrieved by a data provider or store it in an ADO.NET DataSet object.
The .NET Framework provides several data providers these are OLE DB Data Provider, .NET SQL Data
Provider, .NET Oracle Data Provider and ODBC Data Provider. Each provider is designed to be used with a
specific database see figure 6-3.

Connection
This is the object that allows us to establish a connection with the data source. Depending on the actual .NET
data provider involved, connection objects automatically pool database connections for us. It’s important to
realize that they don’t pool connection object instances, but they try and recycle database connections. Examples
of connection objects are OleDbConnection, SqlConnection, OracleConnection, and so on.

Command
This object represents an executable command on the underlying data source. This command may or may not
return any results. These commands can be used to manipulate existing data, query existing data, and update or
even delete existing data. In addition, these commands can be used to manipulate underlying table structures.
Examples of command objects are SqlCommand, OracleCommand.

DataReader
This class reads a forward-only stream of rows from a data source, and the rows can be accessed one at a time.
The connection must stay open while we’re reading the rows from the DbDataReader because the rows are read
directly from the data source when requested. However, the DataReader object allows us to store only one row of
data in memory at any point in time.
There are DataReaders derived from DbDataReader for every data provider:

198
The Complete Reference To Professional SOA with Visual Studio 2005

* If we were accessing a SQL Server database using the .NET SQL Provider then we would use the
SqlDataReader,
* OracleDataReader for the .NET Oracle Provider

* OleDbDataReader for OLE DB Data Provider.


* OdbcDataReader for ODBC Data Provider

DataAdapter
This object enables a database and a DataSet to communicate with each other. We use the DataAdapter object to
transfer data between a data source and a DataSet. In addition, the DataAdapter object can transfer data between a
DataSet and some other applications, such as Microsoft Exchange Server.
There are DataAdapters derived from DbDataAdapter for every data provider:

* If we were accessing a SQL Server database using the .NET SQL Provider then we would use the
SqlDataAdapter,
* OracleDataAdapterfor the .NET Oracle Provider
* OleDbDataAdapter for OLE DB Data Provider.

* OdbcDataAdapter for ODBC Data Provider

XML
XML is an important component of the ADO.NET architecture. ADO.NET uses XML internally to store and
transfer data. We need not explicitly convert data to the XML format or the XML format to data. XML is
integrated with ADO.NET as DataSets. The structure of the DataSet, including table definitions, columns, data
types, and constraints, is defined by using an XML schema. We can serialize the data within a DataSet as XML.
Similarly, we can serialize the structure of the DataSet as an XML schema.

Interoperability
Interoperability is one of the key benefits provided by ADO.NET. Because ADO.NET uses XML to exchange
data, any component that understands XML can receive data from ADO.NET. For example, we can transfer data
between ADO.NET and an application that is running on any platform. The integration of XML and ADO.NET
allows ADO.NET to operate easily with the applications that support XML.

Maintainability
Applications created using ADO.NET are easier to manage and scale than applications created using ADO. For
example, after developing an application, we might need to change its architecture to improve its speed or
increase the number of people who can access the application. Consider the example of an e-commerce site. As
the e-commerce site becomes popular, the number of hits on the site increases. If the number of hits increases,
we might need to change the architecture of the application and increase the number of tiers. However,
increasing the number of tiers in a deployed application is a difficult and time-consuming task. In addition,
problems might occur during data exchange or data transfer between the tiers. ADO.NET enables us to easily
increase tiers in a deployed application because ADO.NET uses XML to transfer data between tiers. This
enables the objects in new tiers to exchange data seamlessly.

199
The Complete Reference To Professional SOA with Visual Studio 2005

Programmability
ADO.NET simplifies programming for various tasks, such as executing SQL commands. This enables us to
increase productivity and minimize the number of errors. For example, we can use the ADO.NET data
commands to execute SQL statements or stored procedures. The actual task of building and executing a SQL
statement is abstract and performed by ADO.NET. In addition, the ADO.NET data classes enable us to use typed
programming to write code. Typed programming allows automatic statement completion. Therefore, it becomes
easy to write code. In addition, typed programming increases the safety of the code and reduces the number of
compilation errors.

Performance
In the past the traditional ADO disconnected recordsets model use COM marshaling to transfer data between
applications. This required a conversion process for COM to recognize the data type. This diminishes the
performance of an application. Alternatively ADO.NET uses XML to transfer data. Therefore, the requirement
to convert the data type does not exist, which increases the performance of an application.

Scalability
With the increase in data and the change in the business models of organizations, the demand for data has
increased rapidly. Consider a Web site that sells sporting goods. When a prospective buyer wants to view
product information, the information is available in the Products database. If several prospective customers
accessing the Web site simultaneously want to view information about the same product, the demand for data
from the Products database increases. ADO.NET enables our applications to scale according to requirements
because it uses disconnected architecture. This enables us to reduce the open connections to the database and
results in optimum usage of resources.

In-Memory Representations of Data


ADO uses a recordset to represent data that is retrieved from tables in memory, whereas ADO.NET uses
DataSets. A standard ADO object can hold multiple recordsets, similar to a dataset. We are able to access each
recordset by calling .movenextrecordset. A recordset usually contains data from a single table. To store data
from multiple tables, we can use a JOIN query. The JOIN query retrieves the data from multiple tables as a
single result table. Alternatively, ADO.NET uses a DataSet to represent data in memory. As mentioned earlier, a
DataSet can store data from multiple tables and multiple sources. In addition, a DataSet can also contain
relationships between tables and the constraints on a table. Therefore, a DataSet can represent the structure of a
database.

Minimized Open Connections


In ADO.NET, we can connect to a database to retrieve and update records. We can retrieve records from a
database, copy them into a DataSet, and then disconnect from the database. Although a recordset can provide
disconnected data access in ADO, ADO was primarily designed for connected scenarios.
In ADO.NET, we can communicate with the database using a DataAdapter or a DataReader that makes calls
to an OLE DB provider or to the APIs provided by the data source.

200
The Complete Reference To Professional SOA with Visual Studio 2005

Sharing Data Between Applications


We can use COM marshaling in ADO to transfer a disconnected recordset from one component to another. In
ADO.NET, we can transfer a DataSet using an XML stream. XML provides the following advantages over COM
marshaling when transferring data:

* Richer data types. COM marshaling can only convert data types that are defined by the COM standard. In an
XML-based data transfer, restrictions on data types do not exist. We can use XML-based data transfer to
transfer any data that is serializable.
* Better Interoperability. Unlike COM marshaling by using an XML stream we allow our application to be
interoperable with any other applications that can receive and read XML. This instantly improves the
interoperability of our applications.

OLE DB Data Provider in .NET


An OLE DB provider is the code that sits between the data consumer and the native API of a data source. It
maps the generic OLE DB API to the data source's native APIs. It is a COM-based solution in which the data
consumer and provider are COM objects that communicate through COM interfaces. Database vendors and third
parties have written OLE DB providers for just about every significant data source. In contrast, far fewer .NET
data providers exist. To provide a bridge to these preexisting OLE DB interfaces, .NET includes an OleDB data
provider that functions as a thin wrapper to route calls into the native OLE DB. Because interoperability with
COM requires switching between managed and unmanaged code, performance can be severely degraded see
Figure 6-4.
The OLE DB .NET data provider enables us to connect to the OLE DB data sources, whereas the SQL
Server .NET data provider allows us to connect from SQL Server 7.0 to SQL Server 2005 and later databases.
System.Data is the namespace which contains the two namespaces required by the OLE DB and SQL Server
.NET data provider: System.Data.OleDb and System.Data.SqlClient. These namespaces contain classes for the
OLE DB .NET and SQL Server .NET data providers, respectively.

Figure 6-4 SQL data provider and Oracle data provider provides better performance than OLE DB data provider.

.NET Data Provider


The .NET data provider provides the same basic service to the client as the OLE DB provider: exposing a data
source's API to a client. Its advantage is that it can directly access the native API of the data source, rather than
relying on an intermediate data access bridge see figure 6-4. Native providers may also include additional
features to manipulate data types native to the data source and improve performance.
.NET provides two specialized data providers. That is Oracle data provider used to provide optimized data
access to Oracle databases and the SQL Data provider which is used for optimized data access to SQL Server
database. These .NET data providers enable an application to connect to a data source, execute commands, and
retrieve results. A .NET data provider consists of the Connection, Command, DataReader, and DataAdapter
objects, which we can use to perform such tasks as connecting to a database and executing SQL commands.

201
The Complete Reference To Professional SOA with Visual Studio 2005

The OleDbConnection Class


The OleDbConnection class allows us to create a connection with a data source. When we want to manipulate data
from a data source, we must create a connection to the data source. To make a connection to a data source, we can
provide the OleDbConnection class information about the data source such as the name of the database, the source
computer, the data provider, the user name, and the password. The syntax for creating a connection using the
OleDbConnection class is shown in the following code.

Listing 6-1. Demonstrates OleDbConnection using Visual C#

using System.Data.OleDb;

OleDbConnection connection = new OleDbConnection();


connection.ConnectionString =
"Provider=Microsoft.Jet.OLEDB.4.0;Password=;User ID=Admin; " +
"Data Source=E:\\SOA\\OleDBAuthors.mdb";
connection.Open();

Listing 6-2. Demonstrates OleDbConnection usingVisual Basic .NET

Imports System.Data.OleDb

Dim Connection As New OleDbConnection()


' Set the ConnectionString property
connection.ConnectionString = _
"Provider=Microsoft.Jet.OLEDB.4.0;Password=;User ID=Admin; " & _
"Data Source=E:\SOA\OleDBAuthors.mdb"
' Open the Connection
connection.Open()

In the preceding code snippet, the ConnectionString property of the OleDbConnection class allowing us to specify the
information required by the .NET Framework to connect to the OleDBAuthors database. In the second line of code
where the ConnectionString property is set, the Provider is Microsoft.Jet.OLEDB.4.0 and the data source refers to the
Microsoft Access database file named OleDBAuthors.mdb. The user ID and password are the credentials required to
access the Authors database. To use the OleDbConnection class, we can import the OleDb namespace that contains the
OleDbConnection class. The OleDb namespace is available in the System.Data namespace.

The SqlConnection Class


The following code shows how to use the SqlConnection class to connect to the Northwind database.

Listing 6-3. Demonstrates SqlConnection using Visual C#

using System.Data.SqlClient;

SqlConnection connection = new SqlConnection();


connection.ConnectionString =
"Data Source=localhost;user id=sa;pwd=;Initial Catalog=Northwind";
connection.Open();

Listing 6-4. Demonstrates SqlConnection using Visual Basic .NET

Imports System.Data.SqlClient

202
The Complete Reference To Professional SOA with Visual Studio 2005

Dim connection As New SqlConnection()


' Set the ConnectionString property
connection.ConnectionString = "Data Source=" & _
"localhost;user id=sa;pwd=;Initial Catalog=Northwind"
' Open the Connection
connection.Open()

The preceding code snippet is similar to the code that uses the OleDbConnection class. The only difference
is that we do not need to provide the Provider attribute in the ConnectionString property. To use the
SqlConnection class, we need to import the SqlClient namespace that contains the SqlConnection class. The
SqlClient namespace is available in the System.Data namespace.

Opening and Closing Connections


The mere act of creating a Connection object and supplying a connection string doesn’t physically open a
connection to the database. Calling the object’s Open method does. A connection opened with Open should be
closed with Close. Both SqlConnection and OleDbConnection feature Open and Close methods. The following
code opens and closes a SQL Server connection:
connection.Open()

and
connection.Close()
Calling Close on a connection that’s not open is not harmful. Structuring our database access code this way
ensures that the connection is closed even in the event of untimely errors. Failing to close open connections is
debilitating to performance and to the very operation of the application. Always close database connections in
finally blocks in production code.

Listing 6-5. Opening and Closing Connections using Visual C#

SqlConnection conn = new SqlConnection


("Data Source=localhost;user id=sa;pwd=;Initial Catalog=Northwind");
try
{
conn.Open();
}
catch (SqlException ex)
{
Console.WriteLine(ex.Message);
}
finally
{
if (conn.State == System.Data.ConnectionState.Open)
conn.Close();
}

Listing 6-6. Opening and Closing Connections using Visual Basic .NET

Dim conn As SqlConnection = New SqlConnection("Data Source=localhost;user id=sa;pwd=;Initial Catalog=Northwind")


Try
conn.Open()
Catch ex As SqlException
Console.WriteLine(ex.Message)

203
The Complete Reference To Professional SOA with Visual Studio 2005

Finally
If conn.State = System.Data.ConnectionState.Open Then
conn.Close()
End If
End Try

Alternatively we could in C#

using (SqlConnection conn = new SqlConnection


("Data Source=localhost;user id=sa;pwd=;Initial Catalog=Northwind"))
{

}

Or in VB
Using conn As SqlConnection = New SqlConnection
("Data Source=localhost;user id=sa;pwd=;
Initial Catalog=Northwind")

End Using

Using is a C# and VB implementation, which through the .NET Framework common language runtime (CLR)
automatically releases the memory used to store objects that are no longer required.
The using statement provides a scope for programmers to specify when objects should be released. A using
statement is exited either when the end of the using statement is reached of if an exception is thrown during the
statement. Thus it provides as an ideal means to manage unmanaged resources such as file handles or database
connections. The object in the using statement need to implement the IDisposable interface. This interface
provides the Dispose method, which should release the object's resources.

Note that we cannot access conn from outside the Using block, because its scope is limited to the block.

The OleDbCommand Class


In the previous sections, we learned how to use the Connection objects to connect to a particular database. In this
section, we will learn how to use the Command objects in the .NET Framework to execute a command against a
data source. There are two types of Command objects: OleDbCommand and SqlCommand.
The OleDbCommand class represents a SQL statement or a stored procedure that we want to execute against a
data source. For example, we can use the OleDbCommand object to execute a batch insert or a batch update
against a data source. The syntax for creating an OleDbCommand object is provided in the following code.

Listing 6-7. Demonstrates using OleDbCommand in Visual C#

OleDbCommand myCommand = new OleDbCommand();


OleDbConnection myConnection = new OleDbConnection();
string mySQL = "Select COUNT(ProductID) from Products";

myConnection.ConnectionString = "Provider=SQLOLEDB.1;data source=" +


"localhost;user id=sa;pwd=;Initial Catalog=Northwind";
myConnection.Open();
myCommand.Connection = myConnection;

204
The Complete Reference To Professional SOA with Visual Studio 2005

myCommand.CommandText = mySQL;

Console.WriteLine(myCommand.ExecuteScalar().ToString());
myConnection.Close();

Listing 6-8. Demonstrates using OleDbCommand in Visual Basic .NET

Dim myCommand as New OleDbCommand()


Dim myConnection as New OleDbConnection()
Dim mySQL as String = "Select COUNT(ProductID) from Products"

myConnection.ConnectionString = "Provider=SQLOLEDB.1;data source=" & _


"localhost;user id=sa;pwd=;Initial Catalog=Northwind"
myConnection.Open()
myCommand.Connection = myConnection

myCommand.CommandText = mySQL.Trim()

Console.WriteLine(myCommand.ExecuteScalar().ToString())
myConnection.Close()

In the preceding code, an OleDbCommand object is declared. After we initialize the OleDbConnection object,
we set the Connection property of the OleDbCommand object to specify which Connection object to use. Next,
the OleDbCommand object requires a SQL statement. This SQL statement specifies the command to be executed
against the specified data source. The SQL statement can be a SELECT statement, an INSERT statement, an
UPDATE statement, or a DELETE statement. A SELECT statement is specified in the string variable mySQL.
This SELECT statement is executed against the data source, and the count of ProductID is retrieved from the
Products table of the Northwind database. The CommandText property of the OleDbCommand object is set to
the string variable mySQL. The CommandText property represents the SQL statement or a stored procedure that
will be executed against a data source.

The ExecuteScalar Method

The ExecuteScalar method executes a SQL statement against a specified data source and returns a single value. The
single value represents the value in the first row and the first column. In addition, the rest of the values are ignored.
The ExecuteScalar method is commonly used to execute aggregate functions on a table. For example, if we want to
retrieve the number of employees residing in the ZIP code 28273, we need to use the COUNT function. The SQL
statement might look like this:

SELECT COUNT(*) from Employees where Zip = 28273

This SQL statement returns just one value that is part of a single row and single column.

The ExecuteReader Method


The ExecuteReader method executes a SQL statement or a stored procedure against the available data source and
returns an OleDbDataReader object.

Listing 6-9. Demonstrates ExecuteReader using Visual C#

OleDbCommand myCommand = new OleDbCommand();

205
The Complete Reference To Professional SOA with Visual Studio 2005

OleDbConnection myConnection = new OleDbConnection();


string mySQL = "Select * from Products";

myConnection.ConnectionString = "Provider=SQLOLEDB.1;data source=" +


"localhost;user id=sa;pwd=;Initial Catalog=Northwind";
myConnection.Open();
myCommand.Connection = myConnection;

myCommand.CommandText = mySQL.Trim();

OleDbDataReader myReader;
myReader = myCommand.ExecuteReader();
Console.WriteLine(myReader.FieldCount.ToString());
myConnection.Close();

Listing 6-10. Demonstrates ExecuteReader using Visual Basic .NET

Dim myCommand as New OleDbCommand()


Dim myConnection as New OleDbConnection()
Dim mySQL as String = "Select * from Products"

myConnection.ConnectionString = "Provider=SQLOLEDB.1;data source=" & _


"localhost;user id=sa;pwd=;Initial Catalog=Northwind"
myConnection.Open()
myCommand.Connection = myConnection

myCommand.CommandText = mySQL

Dim myReader as OleDbDataReader


myReader = myCommand.ExecuteReader()

Console.WriteLine(myReader.FieldCount.ToString())
myConnection.Close()

The ExecuteNonQuery Method


The ExecuteNonQuery method can be used to execute SELECT, INSERT, UPDATE, or DELETE statements.
The ExecuteNonQuery method executes these three statements against the data source and returns an integer
value specifying the number of rows affected by the SELECT, INSERT, UPDATE, or DELETE statements.

Listing 6-11. Demonstrates using ExecuteNonQuery using Visual C#

OleDbCommand myCommand = new OleDbCommand();


OleDbConnection myConnection = new OleDbConnection();
string mySQL = "INSERT INTO PRODUCTS VALUES(..)";

myConnection.ConnectionString = "Provider=SQLOLEDB.1;data " +


"source=localhost;user id=sa;pwd=;Initial Catalog=Northwind";
myConnection.Open();

myCommand.Connection = myConnection;

myCommand.CommandText = mySQL.Trim();

206
The Complete Reference To Professional SOA with Visual Studio 2005

int NoOfRows = 0;
NoOfRows = myCommand.ExecuteNonQuery();
Console.WriteLine("({0}) rows affected.", NoOfRows);
myConnection.Close();

Listing 6-12. Demonstrates using ExecuteNonQuery using Visual Basic .NET

Dim myCommand as New OleDbCommand()


Dim myConnection as New OleDbConnection()
Dim mySQL as String = "INSERT INTO PRODUCTS VALUES (..)"

myConnection.ConnectionString = "Provider=SQLOLEDB.1;data source=" & _


"localhost;user id=sa;pwd=;Initial Catalog=Northwind"
myConnection.Open()
myCommand.Connection = myConnection

myCommand.CommandText = mySQL

dim NoOfRows = myCommand.ExecuteNonQuery()

Console.WriteLine("({0}) rows affected.",NoOfRows)


myConnection.Close()

The SqlCommand Class


The SqlCommand class represents a SQL statement or stored procedure that we want to execute against a SQL
Server data source. For example, to execute a batch insert or a batch update against a SQL Server data source,
we use the SqlCommand object.

Listing 6-13. Demonstrates using SqlCommand using Visual C#

SqlCommand myCommand = new SqlCommand();


SqlConnection myConnection = new SqlConnection();
string mySQL = "Select COUNT(ProductID) from Products";

myConnection.ConnectionString = "data source=localhost;user id=sa; " +


"pwd=;Initial Catalog=Northwind";
myConnection.Open();

myCommand.Connection = myConnection;

myCommand.CommandText = mySQL;

Console.WriteLine(myCommand.ExecuteScalar().ToString());

Listing 6-14. Demonstrates using SqlCommand using Visual Basic .NET

Dim myCommand As New SqlCommand()


Dim myConnection As New SqlConnection()
Dim mySQL As String = "Select COUNT(ProductID) from Products"

myConnection.ConnectionString = "data source=" & _


"localhost;user id=sa;pwd=;Initial Catalog=Northwind"

207
The Complete Reference To Professional SOA with Visual Studio 2005

myConnection.Open()
myCommand.Connection = myConnection

myCommand.CommandText = mySQL

Console.WriteLine(myCommand.ExecuteScalar().ToString())

The usage of the SqlCommand object is very similar to the usage of the OleDbCommand object. However,
we need not specify the name of the provider in the ConnectionString property.
The SqlCommand object consists of four Execute methods: ExecuteScalar, ExecuteReader,
ExecuteNonQuery, and ExecuteXMLReader. The syntax and functionality of these methods are identical to the
syntax and functionality of the OleDbCommand object.

Using Data Adapters


A data adapter forms an interface between the application and the data source for retrieving and saving data. The
OleDbDataAdapter object represents a connection and a set of command objects that helps populate a DataSet
object. We will learn about the DataSet object in the next lesson.
We can use the OleDbDataAdapter object to fill the DataSet object with data. When a DataSet object is
filled, the primary key information available on the table is not implicitly imported to the DataSet object.
Therefore, when we populate a DataSet, we have to import the information explicitly to the DataSet. To use the
OleDbDataAdapter object for filling the DataSet, we can specify properties such as which Command and
Connection objects to use. The OleDbDataAdapter object consists of four properties that we use to specify
Command objects: SelectCommand, InsertCommand, UpdateCommand, and DeleteCommand.

The SelectCommand Property


We use the SelectCommand property to set the SQL statement or a stored procedure that selects data from the
data source. We can set the SelectCommand property of an existing OleDbCommand object, or we can set the
CommandText property of the default Command object that is created when we use the SelectCommand object.
When a SelectCommand property does not return any rows, no table is added to the DataSet and no exception is
thrown.

The InsertCommand Property


We use the InsertCommand property to set the SQL statement or a stored procedure that inserts data into the data
source. We can set the InsertCommand property to an existing OleDbCommand object, or we can set the
CommandText property of the default Command object that is created when we use the InsertCommand object.
The InsertCommand property returns an integer value that specifies the number of rows affected by the
corresponding insert operation.

The UpdateCommand Property


We use the UpdateCommand property to set the SQL statement or a stored procedure that updates data in the
data source. We can set the UpdateCommand property to an existing OleDbCommand object, or we can set the
CommandText property of the default Command object that is created when we use the UpdateCommand object.
When we execute an UpdateCommand object, it returns the number of rows affected by the update operation.

208
The Complete Reference To Professional SOA with Visual Studio 2005

The DeleteCommand Property


We use the DeleteCommand property to set the SQL statement or a stored procedure that deletes data from the
data source. We can set the DeleteCommand property to an existing OleDbCommand object, or we can set the
CommandText property of the default Command object that is created when we use the DeleteCommand object.
When we execute a DeleteCommand property, it returns the number of rows affected by the delete operation.

Listing 6-15. Demonstrates how to use the SelectCommand, InsertCommand, UpdateCommand, and DeleteCommand
properties using Visual C#

string mySQL = "Select * from Products";

OleDbDataAdapter myAdapter = new OleDbDataAdapter();

OleDbCommand myCommand = new OleDbCommand();


OleDbConnection myConnection = new OleDbConnection();

myConnection.ConnectionString =
"Provider=SQLOLEDB.1;data source=localhost;" +
"user id=sa;pwd=;Initial Catalog=Northwind";
myConnection.Open();

myCommand.Connection = myConnection;
myCommand.CommandText = mySQL;

myAdapter.SelectCommand = myCommand;

DataSet myDataSet = new DataSet();


myAdapter.Fill(myDataSet, "Products");

foreach(DataRow myRow in myDataSet.Tables[0].Rows)


{
Console.WriteLine(myRow[0]);
}

mySQL = "INSERT INTO PRODUCTS(PRODUCTNAME) VALUES('Nuts')";


myCommand.CommandText = mySQL;
myAdapter.InsertCommand = myCommand;
int count;
count = myAdapter.InsertCommand.ExecuteNonQuery();
Console.WriteLine("({0}) rows affected", count);

mySQL = "Update PRODUCTS Set PRODUCTNAME = 'Caps' WHERE PRODUCTID = 78";


myCommand.CommandText = mySQL;
myAdapter.UpdateCommand = myCommand;
count = myAdapter.UpdateCommand.ExecuteNonQuery();
Console.WriteLine("({0}) rows affected", count);

mySQL = "DELETE FROM PRODUCTS WHERE PRODUCTID = 78";


myCommand.CommandText = mySQL;
myAdapter.DeleteCommand = myCommand;
count = myAdapter.DeleteCommand.ExecuteNonQuery();
Console.WriteLine("({0}) rows affected", count);

209
The Complete Reference To Professional SOA with Visual Studio 2005

myConnection.Close();

Listing 6-16. Demonstrates how to use the SelectCommand, InsertCommand, UpdateCommand, and DeleteCommand
properties using Visual Basic .NET

Dim myAdapter As New OleDbDataAdapter()


Dim myCommand As New OleDbCommand()
Dim myConnection As New OleDbConnection()
Dim mySQL As String = "Select * from Products"

myConnection.ConnectionString = "Provider=sqloledb.1;data source=" & _


"localhost;user id=sa;pwd=;Initial Catalog=Northwind"
myConnection.Open()
myCommand.Connection = myConnection
myCommand.CommandText = mySQL
myAdapter.SelectCommand = myCommand

Dim myDataSet As New DataSet()


myAdapter.Fill(myDataSet, "Products")
Dim myRow As DataRow
For Each myRow In myDataSet.Tables(0).Rows
Console.WriteLine(myRow("productid"))
Next

mySQL = "INSERT INTO PRODUCTS(PRODUCTNAME) VALUES('Nuts')"


myCommand.CommandText = mySQL
myAdapter.InsertCommand = myCommand
Dim count As Integer
count = myAdapter.InsertCommand.ExecuteNonQuery()
Console.WriteLine("({0}) rows affected", count)

mySQL = "Update PRODUCTS Set PRODUCTNAME = 'Caps' WHERE PRODUCTID = 78"


myCommand.CommandText = mySQL
myAdapter.UpdateCommand = myCommand
count = myAdapter.UpdateCommand.ExecuteNonQuery()
Console.WriteLine("({0}) rows affected", count)

mySQL = "DELETE FROM PRODUCTS WHERE PRODUCTID = 78"


myCommand.CommandText = mySQL
myAdapter.DeleteCommand = myCommand
count = myAdapter.DeleteCommand.ExecuteNonQuery()
Console.WriteLine("({0}) rows affected", count)
myConnection.Close()

The implementation of the SqlDataAdapter class is similar to the OleDbDataAdapter class. If we are using
the SqlDataAdapter class, then we need to use the corresponding Command and Connection objects. The
Command and Connection objects that are used in conjunction with the SqlDataAdapter class are the
SqlCommand and SqlConnection objects, respectively.

The DataReader Class


The DataReader class provides us with read only and forward only access to the data from the data source. The
DataReader object reduces system overhead by only keeping only one row of data in memory at a time. Thus the

210
The Complete Reference To Professional SOA with Visual Studio 2005

DataReader is an efficient means of accessing large amount data. We can create a DataReader object by executing the
ExecuteReader() method of the Command object. There are two data readers the SqlDataReader class and the
OleDbDataReader class. The following sections discuss these two data readers in detail.

The SqlDataReader Class


The SqlDataReader class allows us to read the read-only, forward-only data from a SQL Server database. To
create a SqlDataReader object, we execute the ExecuteReader() method of the SqlCommand class. We need to
call the Open() method on the connection object that the SqlCommand object uses before calling
ExecuteReader(). We can close the SqlDataReader object by using the Close() method to release the
SqlConnection object. The following code shows how to implement the SqlDataReader class.

Listing 6-17. Demonstrates SqlDataReader using Visual C#

string myString;
myString = "data source=localhost; Initial Catalog=Northwind;" +
"user id=sa;pwd=;";
string mySQL = "SELECT lastname, firstname FROM Employees";
SqlConnection myConnection = new SqlConnection(myString);
SqlCommand myCommand = new SqlCommand();
myCommand.CommandText = mySQL;
myCommand.Connection = myConnection;
myConnection.Open();
SqlDataReader myReader;
myReader = myCommand.ExecuteReader();
while (myReader.Read())
{
Console.WriteLine((myReader.GetString(0) + ", " +
myReader.GetString(1)));
}

myReader.Close();
myConnection.Close();

Listing 6-18. Demonstrates SqlDataReader using Visual Basic .NET

Dim myString As String


myString = "data source=localhost; Initial Catalog=Northwind; " & _
"user id=sa; pwd=;"
Dim mySQL As String = "SELECT lastname, firstname FROM Employees"
Dim myConnection As New SqlConnection(myString)
Dim myCommand As New SqlCommand()
myCommand.CommandText = mySQL
myCommand.Connection = myConnection
myConnection.Open()
Dim myReader As SqlDataReader
myReader = myCommand.ExecuteReader()
' Always call Read before accessing data.
While myReader.Read()
Console.WriteLine((myReader.GetString(0) & ", " & _
myReader.GetString(1)))
End While
' Always call Close when done reading.

211
The Complete Reference To Professional SOA with Visual Studio 2005

myReader.Close()
' Close the connection when done with it.
myConnection.Close()

In the code above, the SqlDataReader object is initialized to the object returned by the ExecuteReader() method.
We use the Read() method of the SqlDataReader object to read a row from the data source. Observe that the
DataReader object has just one row at any given time. We can call the Read() method of the SqlDataReader
object to fetch subsequent rows. After reading from the SqlDataReader object, we can close the SqlDataReader
object. After closing the SqlDataReader object, we can call the IsClosed() method and the RecordsAffected
property.

The IsClosed() Method


The IsClosed() method of the SqlDataReader class returns a value indicating whether the SqlDataReader is
closed.

The RecordsAffected Property


The RecordsAffected property of the class returns information on the number of rows that have been inserted,
modified or deleted by the current data operation performed by the Transact SQL statement. The
RecordsAffected property always calls the Close() method before returning the affected rows to ensure an
accurate return of values.

The OleDbDataReader Class


The OleDbDataReader class provides read-only and forward-only access to data from any data source. To create
an OleDbDataReader object, we execute the ExecuteReader() method of the OleDbCommand class. If the
OleDbDataReader object is being used, the associated OleDbConnection provides the required data for the
OleDbDataReader object. During this period, no other operation can use the OleDbConnection object to retrieve
or send data from or to the data source. We close the OleDbDataReader object by using the Close() method to
release the OleDbConnection object.

Data Access Using Visual Studio 2005


In the previous section, we learned about ADO.NET and its components. In addition, we have learned about the
architecture and the benefits of ADO.NET.
We will now create a simple application that will connect to a SQL Server 2005 database. To do this we will
use Visual Studio’s DataAdapter and Connection objects.
Start Visual Studio 2005. You will see something similar to the image below (figure 6-5). Please note that
screenshots may vary slightly depending on the Edition of Visual Studio that you’re using.

212
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 6-5 Visual Studio 2005 Server Explorer

To add a connection to Visual Studio IDE so that we can explore and manage the database we can use the
Server Explorer. To do this simply right click on the Server Explorer and select “Add Connection” see figure 6-
6.

Figure 6-6 Add a New Connection

Selecting “Add Connection” will raise a dialog box. We can specify the Server that we want to connect to as
well as the database and the security information required for access here see figure 6-7.

213
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 6-7: Create a new connection

Once the connection has been successfully registered onto the Server Explorer we will be able to access
database specific information such as Database Diagrams, Tables, Views, Stored Procedures and Database
Functions see figure 6-8.

Figure 6-8 New database connection to AdventureWorks

Open a new project File -> New -> Project.


Select the Windows Application template for our language (Visual C# or Visual Basic)

214
The Complete Reference To Professional SOA with Visual Studio 2005

Again depending on the Edition of Visual Studio that is used the screenshots may differ slightly.

Figure 6-9 New Windows Application Project

By selecting a new windows application Visual Studio 2005 will automatically generate a Windows Form
on the designer see figure 6-10.

Figure 6-10: select DataGridView

To display the information that we wanted to display we can drag and drop a DataGridView control from
under the Data tab in the toolbox onto the screen. The DataGridView is typically used to display information in a
tabular format. Select the little arrow on the top right corner of the DataGridView control. This will bring out a
context menu which shows a list of predefined DataGridView Tasks see figure 6-11.

215
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 6-11: Select a Data Source used to populate the DataGridView

To create a new Data Source select Choose Data Source dropdown list. Select the “Add Project Data
Source” link at the bottom of the Data Source dropdown screen see figure 6-12.

Figure 6-12 Create a new Data Source

Once we have selected the “Add Project Data Source” option we will be prompted to either add a data
source to a Database, Web Service or an Object see Figure 6-13. In this particular example we will be selecting
Database as the source of information.

216
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 6-13: create a new Database data source

By selecting the next option since we have selected the Database as the source location for information we
will prompted to select the source Database location see figure 6-14.

Figure 6-14: select the DataSource from the drop down list or create a new data source connection.

Visual Studio will prompt us whether we wanted to save the connection string into the configuration file. It
is particularly important to keep all connection information in a configuration file. As it will simplify the task of
migrating applications from a development environment to a production environment.

217
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 6-15: Save the connection string as a specified name so that it can be called within the application

Once the we have saved the connection string into the Application configuration file Visual Studio will
connect to the database and retrieve relevant database information see Figure 6-16.

Figure 6-16 Visual Studio will retrieve database information from the specified connection string.

We will be prompted where to retrieve information from in the database. These could include Tables, Views,
Stored Procedures and Functions. The information will then be saved to a DataSet. In this case we have named it
“AdventureWorksDataSet” see Figure 6-17.

218
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 6-17: select the table that we are interested to retrieve the table.

In this particular example we will be retrieving information from the database table Employee. To do this
we must first expand the Tables node. By browsing to the relevant table in this case Employee and then
expanding the Employee table and selecting the relevant columns of interest we can indicate to visual studio
which columns we would like to retrieve from the Employee database table see Figure 6-18.

Figure 6-18 select the table and the columns that we are interested in

Once the selection is made select the Finish button. We will be brought back onto the context menu for the
DataGridView. But notice that from the meta information gathered from the database column that we had
selected Visual Studio will automatically create the Columns for us in the DataGridView. We can also

219
The Complete Reference To Professional SOA with Visual Studio 2005

automatically specify to Enable Adding, Enable Editing and Enable Deleting by checking the boxes see figure 6-
19.

Figure 6-19 DataGridView is now populated with the column information that we had selected

We can run the application by simply clicking on F5 to (Start Debugging) or Ctrl+F5 to (Start without Debugging)

Figure 6-20 shows the end result from the application after it is compiled and ran.

We have seen how simple it is to connect to a database and retrieve information using Visual Studio’s
DataGridView Smart databinding.
Internally Visual Studio 2005 has generated the necessary codes to achieve this. The following code is
placed into the Form_Load event so that the application can use the DataAdapter to populate the dataset at
runtime.

this.employeeTableAdapter.Fill(this.adventureWorksDataSet.Employee);

220
The Complete Reference To Professional SOA with Visual Studio 2005

Working with DataSets


An ADO.NET DataSet provides a disconnected view of a data source. ADO.NET DataSets enable us to store
data from multiple data sources. We can create relationships between the tables in a DataSet, even though
relationships might not exist between tables in the data sources. In addition, we can create different data views
from the data contained within the DataSets.
ADO.NET DataSets support in-memory, disconnected data architecture. We can establish a connection to a
data source, retrieve records from a DataSet, and then close the connection. This enables us to work with the data
without requiring us to connect to the database. In-memory, disconnected data enables us to minimize the
number of live connections to a database. In addition, disconnected data architecture reduces the number of
round trips to a database server and allows the database server to fulfill other requests. The in-memory,
disconnected architecture provides quick access to data because the DataSet is present in the memory of a client
computer, and all data operations, such as updating tables, occur at the client level.
An ADO.NET DataSet is a collection of tables and information about the relationships between tables. Each
table further consists of collections of rows, columns, and constraints. We can access these components using the
properties and collections of a DataSet. We use the following classes to work with DataSets in ADO.NET:

Table 6-1 ADO.NET DataSet Class

Class

DataSet class This class includes the Tables collection of the tables in a DataSet. In addition, the
DataSet class contains the Relations collection that represents the relationships
between the tables in a DataSet.

DataTable class This class includes the Rows and Columns collections that represent rows and
columns. In addition, the DataTable class contains the ChildRelations and
ParentRelations collections that represent relationships between tables.

DataRow class This class includes the RowState property. The RowState property indicates
whether a row has changed after loading the data table from a database. The
RowState property can take the following values: Deleted, Modified, New, and
Unchanged.

One of the advantage of using a DataSet as a disconnected DataSource is that it is stored in memory. This allows
for a faster retrieval of information and removes the need of repeatedly querying the database.
DataSets themselves do not interact with databases directly, instead, they let DataAdapters do the work.
DataAdapter’s purpose is to perform database queries and create DataTables containing the query results. It’s also
capable of writing changes made to the DataTables back to the database.
Let us see an example of adding/inserting values using DataSet into the database.

Note: The connection string embed in the code may vary depending on how the SQL server database was
setup on your system.

Listing 6-19. Demonstrates updating database records using a DataSet in Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;

221
The Complete Reference To Professional SOA with Visual Studio 2005

using System.Data.SqlClient;

namespace CSOleDbCommand2
{
class Program
{
static void Main(string[] args)
{
string mySQL =
"Select * from HumanResources.Department";

SqlDataAdapter myAdapter = new SqlDataAdapter();

SqlCommand myCommand = new SqlCommand();


SqlConnection myConnection = new SqlConnection();

myConnection.ConnectionString =
"Data Source=DEVSERVER01;Initial Catalog=AdventureWorks;" +
"Persist Security Info=True;User ID=Book;password=Book";

myConnection.Open();

myCommand.Connection = myConnection;
myCommand.CommandText = mySQL;

myAdapter.SelectCommand = myCommand;

SqlCommandBuilder builder =
new SqlCommandBuilder(myAdapter);

Console.WriteLine(builder.GetInsertCommand().CommandText);
Console.WriteLine(builder.GetUpdateCommand().CommandText);
Console.WriteLine(builder.GetDeleteCommand().CommandText);

DataSet myDataSet = new DataSet();


myAdapter.Fill(myDataSet);
Console.WriteLine("Row count: " +
myDataSet.Tables[0].Rows.Count);

//add a new record to the database


DataRow newdr = myDataSet.Tables[0].NewRow();
newdr["Name"] = "Department Name";
newdr["GroupName"] = "Group name";
newdr["ModifiedDate"] = DateTime.Now;
myDataSet.Tables[0].Rows.Add(newdr);

Console.WriteLine("Row count after adding row: " +


myDataSet.Tables[0].Rows.Count);
myAdapter.Update(myDataSet);
Console.ReadLine();

//update a row.

222
The Complete Reference To Professional SOA with Visual Studio 2005

DataRow curdr = myDataSet.Tables[0].Rows[17];


curdr["Name"] = " Name";
curdr["GroupName"] = "Group name";
curdr["ModifiedDate"] = DateTime.Now;
myAdapter.Update(myDataSet);

//delete a row
DataRow deldr = myDataSet.Tables[0].Rows[17];
myDataSet.Tables[0].Rows.Remove(deldr);
myAdapter.Update(myDataSet);

myConnection.Close();

}
}
}

Listing 6-20. Demonstrates updating database records using a DataSet in Visual Basic .NET

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Data
Imports System.Data.SqlClient
Module Module1

Sub Main()
Dim mySQL As String =
"Select * from HumanResources.Department"
Dim myAdapter As SqlDataAdapter = New SqlDataAdapter
Dim myCommand As SqlCommand = New SqlCommand
Dim myConnection As SqlConnection = New SqlConnection
myConnection.ConnectionString = _
"Data Source=DEVSERVER01;Initial Catalog=AdventureWorks;" + _
"Persist Security Info=True;User ID=Book;password=Book"
myConnection.Open()
myCommand.Connection = myConnection
myCommand.CommandText = mySQL
myAdapter.SelectCommand = myCommand
Dim builder As SqlCommandBuilder =
New SqlCommandBuilder(myAdapter)
Console.WriteLine(builder.GetInsertCommand.CommandText)
Console.WriteLine(builder.GetUpdateCommand.CommandText)
Console.WriteLine(builder.GetDeleteCommand.CommandText)
Dim myDataSet As DataSet = New DataSet
myAdapter.Fill(myDataSet)

Console.WriteLine("Row count: " + _


myDataSet.Tables(0).Rows.Count.ToString)
Dim newdr As DataRow = myDataSet.Tables(0).NewRow
newdr("Name") = "Department Name"
newdr("GroupName") = "Group name"
newdr("ModifiedDate") = DateTime.Now

223
The Complete Reference To Professional SOA with Visual Studio 2005

myDataSet.Tables(0).Rows.Add(newdr)
Console.WriteLine("Row count after adding row: " + _
myDataSet.Tables(0).Rows.Count.ToString)
myAdapter.Update(myDataSet)
Console.ReadLine()

Dim curdr As DataRow = myDataSet.Tables(0).Rows(17)


curdr("Name") = " Name"
curdr("GroupName") = "Group name"
curdr("ModifiedDate") = DateTime.Now
myAdapter.Update(myDataSet)

Dim deldr As DataRow = myDataSet.Tables(0).Rows(17)


myDataSet.Tables(0).Rows.Remove(deldr)
myAdapter.Update(myDataSet)
myConnection.Close()

End Sub

End Module
In the listing above we’re first creating a connection to the SQL Server AdventureWorks database. Then we
select all the records from the HumanResources.Department table and store it in a DataSet using the Fill()
method. We also used the SqlCommandBuilder object to help automatically generate Transact-SQL statements
for a single-table updates. This works when we set the SelectCommand property of the SqlDataAdapter. Then, any
additional Transact-SQL statements that we do not set are generated by the SqlCommandBuilder. This will be
useful later when we perform insert, update and delete.

Listing 6-21. Demonstrates using SqlCommandBuilder using Visual C#

string mySQL = "Select * from HumanResources.Department";

SqlDataAdapter myAdapter = new SqlDataAdapter();

SqlCommand myCommand = new SqlCommand();


SqlConnection myConnection = new SqlConnection();

myConnection.ConnectionString =
"Data Source=DEVSERVER01;Initial Catalog=AdventureWorks;" +
"Persist Security Info=True;User ID=Book;password=Book";

myConnection.Open();

myCommand.Connection = myConnection;
myCommand.CommandText = mySQL;

myAdapter.SelectCommand = myCommand;

SqlCommandBuilder builder = new SqlCommandBuilder(myAdapter);

Console.WriteLine(builder.GetInsertCommand().CommandText);
Console.WriteLine(builder.GetUpdateCommand().CommandText);
Console.WriteLine(builder.GetDeleteCommand().CommandText);

224
The Complete Reference To Professional SOA with Visual Studio 2005

DataSet myDataSet = new DataSet();


myAdapter.Fill(myDataSet);
Console.WriteLine("Row count: " +
myDataSet.Tables[0].Rows.Count);

Listing 6-22. Demonstrates using SqlCommandBuilder using Visual Basic .NET

Dim mySQL As String = "Select * from HumanResources.Department"


Dim myAdapter As SqlDataAdapter = New SqlDataAdapter
Dim myCommand As SqlCommand = New SqlCommand
Dim myConnection As SqlConnection = New SqlConnection
myConnection.ConnectionString = _
"Data Source=DEVSERVER01;Initial Catalog=AdventureWorks;" + _
"Persist Security Info=True;User ID=Book;password=Book"
myConnection.Open()
myCommand.Connection = myConnection
myCommand.CommandText = mySQL
myAdapter.SelectCommand = myCommand
Dim builder As SqlCommandBuilder = New SqlCommandBuilder(myAdapter)
Console.WriteLine(builder.GetInsertCommand.CommandText)
Console.WriteLine(builder.GetUpdateCommand.CommandText)
Console.WriteLine(builder.GetDeleteCommand.CommandText)
Dim myDataSet As DataSet = New DataSet
myAdapter.Fill(myDataSet)
Console.WriteLine("Row count: " + _
myDataSet.Tables(0).Rows.Count.ToString)

The SqlCommandBuilder will generate the following SQL commands from the select command alone:
Insert
INSERT INTO [HumanResources].[Department] ([Name], [GroupName],
[ModifiedDate]) VALUES (@p1, @p2, @p3)

Update
UPDATE [HumanResources].[Department] SET [Name] = @p1,
[GroupName] = @p2, [ModifiedDate] = @p3
WHERE (([DepartmentID] = @p4) AND ([Name] = @p5) AND
([GroupName] = @p6) AND ([ModifiedDate] = @p7))

Delete
DELETE FROM [HumanResources].[Department] WHERE
(([DepartmentID] = @p1) AND ([Name] = @p2) AND
([GroupName] = @p3) AND ([ModifiedDate] = @p4))

By creating the SqlCommandBuilder object and passing in the SqlDataAdapter object we have created the
above SQL commands and have automatically assigned them to the SqlDataAdapter’s InsertCommand,
UpdateCommand and DeleteCommand. This saves us from manually creating SQL statements and assigning
them to the SqlDataAdapter.

Listing 6-23. Demonstrates inserting a record into the database using DataSet in Visual C#

//add a new record to the database


DataRow newdr = myDataSet.Tables[0].NewRow();
newdr["Name"] = "Department Name";

225
The Complete Reference To Professional SOA with Visual Studio 2005

newdr["GroupName"] = "Group name";


newdr["ModifiedDate"] = DateTime.Now;
myDataSet.Tables[0].Rows.Add(newdr);
Console.WriteLine("Row count after adding row: " +
myDataSet.Tables[0].Rows.Count);
myAdapter.Update(myDataSet);
Console.ReadLine();

Listing 6-24. Demonstrates inserting a record into the database using DataSet in Visual Basic .NET

Dim newdr As DataRow = myDataSet.Tables(0).NewRow


newdr("Name") = "Department Name"
newdr("GroupName") = "Group name"
newdr("ModifiedDate") = DateTime.Now
myDataSet.Tables(0).Rows.Add(newdr)
Console.WriteLine("Row count after adding row: " + _
myDataSet.Tables(0).Rows.Count.ToString)
myAdapter.Update(myDataSet)
Console.ReadLine()

Similarly performing an update operation is just as easy. We simply select the row that we’re interested in.
Alter the contents of the DataRow and update the DataSet DataAdapter.

Listing 6-25. Demonstrates updating a database record using DataSet in Visual C#

DataRow curdr = myDataSet.Tables[0].Rows[17];


curdr["Name"] = "Name";
curdr["GroupName"] = "Group name";
curdr["ModifiedDate"] = DateTime.Now;
myAdapter.Update(myDataSet);

Listing 6-26. Demonstrates updating a database record using DataSet in Visual Basic .NET

Dim curdr As DataRow = myDataSet.Tables(0).Rows(17)


curdr("Name") = "Name"
curdr("GroupName") = "Group name"
curdr("ModifiedDate") = DateTime.Now
myAdapter.Update(myDataSet)

Deleting a record in the database is a similar process. We select the DataRow that we wanted to delete and
remove it from the DataSet this way when we update using DataAdapter. The record that’s marked as delete
within the DataSet will automatically be removed from the database.

Listing 6-27. Demonstrates deleting a database record using DataSet in Visual C#

DataRow deldr = myDataSet.Tables[0].Rows[17];


myDataSet.Tables[0].Rows.Remove(deldr);
myAdapter.Update(myDataSet);
myConnection.Close();

Listing 6-28. Demonstrates deleting a database record using DataSet in Visual Basic .NET

Dim deldr As DataRow = myDataSet.Tables(0).Rows(17)

226
The Complete Reference To Professional SOA with Visual Studio 2005

myDataSet.Tables(0).Rows.Remove(deldr)
myAdapter.Update(myDataSet)
myConnection.Close()

A DataTable also contains the Constraints collection. The Constraints collection allows DataSets to
implement all constraints including the constraints at the database level. When we modify the data of a table in a
DataSet, the DataSet implements all the constraints at the client level. Therefore, when a DataSet connects to a
database to perform an update operation, data is updated quickly; the round trip from the database server to the
client is avoided.

Creating ADO.NET DataSets


We can create an ADO.NET DataSet by creating an object of the DataSet class that is present in the System.Data
namespace. When we create an object of the DataSet class by calling the DataSet constructor, we can optionally
pass the name of the DataSet as an argument to the constructor. The following code shows how to create a
DataSet named Employees.

Listing 6-29. Demonstrating creating a DataSet using Visual C#

//Create a new instance of the DataSet class


DataSet EmployeeDS = new DataSet("Employees");

Listing 6-30. Demonstrating creating a DataSet using Visual Basic .NET

' Create a new instance of DataSet class


Dim EmployeeDS As new DataSet("Employees")

After creating a DataSet, we can populate it by adding tables to the DataSet. To add tables to a DataSet, we
create DataTable objects and add them to a DataSet. The following code shows how to add tables to a DataSet.

Lisitng 6-31. Demonstrates adding a DataTable using Visual C#

DataSet EmployeeDS = new DataSet("Employees");


DataTable EmpTable = EmployeeDS.Tables.Add("Employees");

Lisitng 6-32. Demonstrates adding a DataTable using Visual Basic .NET

Dim EmployeeDS As new DataSet("Employees")


Dim EmpTable As DataTable = EmployeeDS.Tables.Add("Employees")

After we add a table to a DataSet, we add columns to the table according to our requirements. The following
code shows how to populate a table with columns.

Listing 6-33. Demonstrates adding DataColumns using Visual C#

DataSet EmployeeDS = new DataSet("Employees");


DataTable EmpTable = EmployeeDS.Tables.Add("Employees");

//Add columns to the dataset


EmpTable.Columns.Add("EmployeeID", Type.GetType("System.String"));
EmpTable.Columns.Add("LastName", Type.GetType("System.String"));
EmpTable.Columns.Add("FirstName", Type.GetType("System.String"));

Listing 6-34. Demonstrates adding DataColumns using Visual Basic .NET

227
The Complete Reference To Professional SOA with Visual Studio 2005

Dim EmployeeDS As new DataSet("Employees")


Dim EmpTable As DataTable = EmployeeDS.Tables.Add("Employees")

' Add columns to the dataset


EmpTable.Columns.Add("EmployeeID", Type.GetType("System.String"))
EmpTable.Columns.Add("LastName", Type.GetType("System.String"))
EmpTable.Columns.Add("FirstName", Type.GetType("System.String"))

Tip: When we are using DataAdapater’s Fill() method columns are created automatically for us.

When we add columns to a DataSet, we can set constraints, such as a primary key, on the columns by using the
PrimaryKey and Unique properties of the DataColumn object. The following code shows how to add the primary
key constraint on a column.

Listing 6-35. Demonstrates adding Primary key to a DataTable using Visual C#

DataSet EmployeeDS = new DataSet("Employee");


DataTable EmpTable = EmployeeDS.Tables.Add("Employees");

// Specifying an identifier for the primary key column


DataColumn pkCol = EmpTable.Columns.Add("EmployeeID",
Type.GetType("System.String"));
EmpTable.Columns.Add("LastName", Type.GetType("System.String"));
EmpTable.Columns.Add("FirstName", Type.GetType("System.String"));

// Specifying the EmployeeID column as the primary key


EmpTable.PrimaryKey = new DataColumn[] {pkCol};

Listing 6-36. Demonstrates adding Primary key to a DataTable using Visual Basic .NET

Dim EmployeeDS As new DataSet("Employees")


Dim EmpTable As DataTable = EmployeeDS.Tables.Add("Employees")

' Specifying an identifier for the primary key column


Dim pkCol As DataColumn = EmpTable.Columns.Add("EmployeeID", _
Type.GetType("System.String"))
EmpTable.Columns.Add("LastName", Type.GetType("System.String"))
EmpTable.Columns.Add("FirstName", Type.GetType("System.String"))

' Specifying the EmployeeID column as the primary key


EmpTable.PrimaryKey = New DataColumn() {pkCol}

As mentioned earlier, a DataSet object can contain multiple tables. We can also create relationships between the
tables in a DataSet. We can use various methods of the DataRelation object to create and manage relationships
between the tables in a DataSet.
To create a relationship between two tables in a DataSet, we use the Add method of the DataRelation object.
The Add method takes a name for the relationship being created, and the DataColumn references of the columns
that we want to define as the parent and child columns in the relationship. The following code shows how to
create relationships between two tables in a DataSet.

228
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 6-37. Demonstrates adding a data relationship using Visual C#

EmployeeDS.Relations.Add("Employees_Territories",
EmployeeDS.Tables["Employees"].Columns["EmployeeID"],
EmployeeDS.Tables["EmployeeTerritories"].Columns["EmployeeID"]);

Listing 6-38. Demonstrates adding a data relationship using Visual Basic .NET

EmployeeDS.Relations.Add("Employees_Territories", _
EmployeeDS.Tables("Employees").Columns("EmployeeID"), _
EmployeeDS.Tables("EmployeeTerritories").Columns("EmployeeID"))

Manipulating an ADO.NET DataSet


After we create and populate a DataSet, we can manipulate it by performing tasks such as merging DataSet
contents and copying the contents of one DataSet to another DataSet. Each of these tasks is explained in the
following sections.

Merging the Contents of DataSets


We can merge the contents of a DataSet, DataTable, or DataRow object with another DataSet, DataTable, or
DataRow object. When we merge the contents of two DataSets, the data in a DataSet is added to another
DataSet. However, we must remember certain rules before we merge the contents of two DataSets. The
following sections describe these rules.

Check Primary Keys


When we merge the contents of DataSets, the table receiving the new data or schema ensures data integrity by
checking the primary key values. The table receiving the new data matches the primary key values of its existing
rows with those of the rows from the incoming table. The data in the existing rows is modified only if the
columns from the incoming schema match those of the existing schema. In addition, the new rows containing
primary key values that do not match any existing rows are added to the existing table. However, if the table
receiving new data does not have a primary key, new rows from the incoming data are added to the table. If the
incoming and existing tables have primary keys on different columns, an exception is thrown, and the DataSet
raises the MergeFailed event. An exception is also thrown when the incoming and existing tables contain
columns that have the same name but different data types.

Preserve Changes
When we merge a DataSet, DataTable, or DataRow object with a DataSet, we can specify whether to preserve
the changes in the existing DataSet and how to manage the new schema elements in the incoming data. We can
use the PreserveChanges property to specify whether to preserve the changes in the existing DataSet. If the
PreserveChanges property is set to True, the existing values in the table receiving data are not overwritten with
the incoming values. However, if the PreserveChanges flag is set to False, the existing values are overwritten by
the incoming values in the current row version of the existing row.

229
The Complete Reference To Professional SOA with Visual Studio 2005

Apply Constraints
When we merge the contents of two DataSets, constraints are not checked when the Merge method is executed.
After we add the data to a receiving table, constraints are enforced on the current values in the DataSet.
Therefore, we need to ensure that we can handle the exceptions in our code.
We use the Merge method of a DataSet object to combine the contents of a DataSet, DataTable, or DataRow
object with another DataSet, DataTable, or DataRow object.

Listing 6-39. Demonstrates using DataSet’s Merge using Visual C#

SqlConnection DBConn = new SqlConnection("server=localhost; " +


"integrated security=sspi; Database=Northwind");

SqlDataAdapter EmpDA = new SqlDataAdapter("SELECT EmployeeID, " +


"FirstName FROM Employees", DBConn);

DBConn.Open();

DataSet EmpDS = new DataSet();


EmpDA.Fill(EmpDS, "Employees");

DataSet EmpDS2 = new DataSet();


EmpDS2.ReadXml("Employee.xml", XmlReadMode.ReadSchema);
EmpDS2.AcceptChanges();
DBConn.Close();

EmpDS.Merge(EmpDS2, true, MissingSchemaAction.AddWithKey);

Listing 6-40. Demonstrates using DataSet’s Merge using Visual Basic .NET

Dim DBConn As SqlConnection = _


New SqlConnection("server=localhost; " + _
"integrated security=sspi; Database=Northwind")
Dim EmpDA As SqlDataAdapter = _
New SqlDataAdapter("SELECT EmployeeID, " + _
"FirstName FROM Employees", DBConn)
DBConn.Open()
Dim EmpDS As DataSet = New DataSet
EmpDA.Fill(EmpDS, "Employees")
Dim EmpDS2 As DataSet = New DataSet
EmpDS2.ReadXml("Employee.xml", XmlReadMode.ReadSchema)
EmpDS2.AcceptChanges()
DBConn.Close()
EmpDS.Merge(EmpDS2, True, MissingSchemaAction.AddWithKey)

In the listing above we first load the values into our EmpDS DataSet. We also load values from a
Employee.xml file into a second DataSet. We then merge the EmpDS2 DataSet into the EmpDS DataSet using
the merge function. Notice we have used MissingSchemaAction.AddWithKey this will adds the necessary
columns and primary key information to complete the schema of EmpDS if it does not already exist.

230
The Complete Reference To Professional SOA with Visual Studio 2005

Copying DataSet Contents


Sometimes, we might need to work with data without affecting the original data in a DataSet. Alternatively, we
might have to create a subset of the data present in a DataSet. In such cases, we can create a copy of an existing
DataSet instead of connecting to the database server and creating a new DataSet.
ADO.NET allows us to create a copy of a DataSet. We can also create a DataSet that is a subset of an
existing DataSet. Essentially we can create an exact copy of a DataSet including the schema, data, row state
information, and row version.
The following code shows how to create an exact copy of a DataSet.

Listing 6-41. Demonstrates DataSet’s copy function using Visual C#

DataSet EmployeeDS = new DataSet("Employees");


DataSet copyDS = EmployeeDS.Copy();

Listing 6-42. Demonstrates using DataSet’s Merge using Visual Basic .NET

Dim EmployeeDS As new DataSet("Employees")


Dim copyDS As DataSet = EmployeeDS.Copy()

We can also create a copy of a DataSet object that includes only the schema and the modified data. To create a
copy of a DataSet that contains only the modified records, we use the GetChanges method of the DataSet object.
The GetChanges method also allows us to retrieve the rows with specified row states. The following code shows
how to create a copy of a DataSet object that contains only changed records.

Listing 6-43. Demonstrates using DataSet’s GetChanges using Visual C#

DataSet changeDS = EmployeeDS.GetChanges();

Listing 6-44. Demonstrates using DataSet’s GetChanges using Visual Basic .NET

Dim changeDS As DataSet = EmployeeDS.GetChanges()


ADO.NET also allows us to copy only the schema of an existing DataSet object. We can use the Clone
method to create a copy of the schema of a DataSet. The following code shows how to use the Clone method to
copy the schema of a DataSet.

Listing 6-45. Demonstrates DataSet’s clone function using Visual C#

DataSet changeDS = EmployeeDS.Clone();

Listing 6-46. Demonstrates DataSet’s clone function using Visual Basic .NET

Dim changeDS As DataSet = EmployeeDS.Clone()

Creating Data Views


Like a database, a DataSet also allows us to create various views of data. For example, we might want to view a
subset of all the records in a DataSet that fulfill a certain criterion. An ADO.NET DataView object provides us
with a dynamic view of a single set of data. We can then sort and filter the data per our requirements. However,
unlike database views, we cannot treat a DataView object as a table. In addition, we cannot create a view of
joined tables by using a data view. We also cannot exclude columns that are present in the source table or append
columns that are not present in the source table.
We can use an object of the DataView class to create a data view on a DataSet. We can create a DataView
object by using the DataView constructor. When we create an instance of the DataView class, we can invoke the

231
The Complete Reference To Professional SOA with Visual Studio 2005

default constructor of the DataView class and pass a table name as an argument. The following code shows how
to create a DataView object using the DataView constructor.

Listing 6-47. Demonstrates creating a DataView using Visual C#

DataView EmployeeDV = new DataView(EmployeeDS.Tables["Employees"],


"Country = 'USA'", "City", DataViewRowState.CurrentRows);

Listing 6-48. Demonstrates creating a DataView using Visual Basic .NET

Dim EmployeeDV As DataView = New DataView( _


EmployeeDS.Tables("Employees"), "Country = 'USA'", "City", _
DataViewRowState.CurrentRows)

In the above code example, the DataView object named EmployeeDV contains the current rows from the
Employees table of the EmployeeDS DataSet. Only the records that match the condition Country ='USA' are
stored in the DataView object. In addition, the records in the EmployeeDV DataView object are sorted based on
the values in the City column.
The following code shows how to set the Sort and RowFilter properties after creating a DataView object.

Listing 6-49. Demonstrates DataView’s Sort and Filter using Visual C#

DataView EmployeeDV = new DataView(EmployeeDS.Tables["Employees"]);


EmployeeDV.Sort = "City";
EmployeeDV.RowFilter = "Country = 'USA'";

Listing 6-50. Demonstrates DataView’s Sort and Filter using Visual Basic .NET

Dim EmployeeDV As DataView = New DataView(EmployeeDS.Tables( _


"Employees"))
EmployeeDV.Sort = "City"
EmployeeDV.RowFilter = "Country = 'USA'"

Handling ADO.NET DataSet Events


ADO.NET supports event-driven programming, which allows us to capture changes and react to them properly.
The ADO.NET DataSet provides the MergeFailed event, which is raised when a conflict occurs when merging
the contents of two DataSets. For example, when merging the contents of two DataSets, if the incoming and
existing tables contain a column with the same name but different data type, an exception is thrown, and the
MergeFailed event is raised. We can pass the MergeFailedEventArgs parameter to the MergeFailed event.
MergeFailedEvent-Args has a Conflict property that identifies the conflict between the two DataSet objects, and
a Table property that identifies the name of the table in conflict. We can then use these properties to resolve the
conflict. The following code shows how to add the MergeFailed event to an event handler.

Listing 6-51. Demonstrates using the MergeFailed event using Visual C#

DataSet EmployeeDS = new DataSet();

EmployeeDS.MergeFailed += new MergeFailedEventHandler


(DataSetMergeFailed);

private static void DataSetMergeFailed(object sender,


MergeFailedEventArgs args)

232
The Complete Reference To Professional SOA with Visual Studio 2005

{
Console.WriteLine("Merge failed for table " + args.Table.TableName);
Console.WriteLine("Conflict = " + args.Conflict);
}

Listing 6-52. Demonstrates using the MergeFailed event using Visual Basic .NET

Dim EmployeeDS As DataSet = New DataSet()

AddHandler EmployeeDS.MergeFailed, New MergeFailedEventHandler( _


AddressOf DataSetMergeFailed)

Private Sub DataSetMergeFailed(sender As Object, args As _


MergeFailedEventArgs)
Console.WriteLine("Merge failed for table " & args.Table.TableName)
Console.WriteLine("Conflict = " & args.Conflict)
End Sub

In addition to the MergeFailed event, ADO.NET provides certain events for the DataTable object. As with
the MergeFailed event, we can write event-handling code for each of these events. Table 6-2

Table 6-2: DataTable Events

Name Description

ColumnChanged Occurs after a value has been changed for the specified DataColumn in a
DataRow.

ColumnChanging Occurs when a value is being changed for the specified DataColumn in a
DataRow.

RowChanged Occurs after a DataRow has been changed successfully.

RowChanging Occurs when a DataRow is changing.

RowDeleted Occurs after a row in the table has been deleted.

RowDeleting Occurs before a row in the table is about to be deleted.

TableCleared Occurs after a DataTable is cleared.

TableClearing Occurs when a DataTable is cleared.

TableNewRow Occurs when a new DataRow is inserted.

Creating a Typed ADO.NET DataSet


Unlike an untyped DataSet that does not have an XML schema associated with it, a strongly typed DataSet does
have an XML schema associated with it. In addition to the late-bound access to values through weakly typed

233
The Complete Reference To Professional SOA with Visual Studio 2005

variables, the strongly typed DataSets allow us to access tables and columns using user-friendly names and
strongly typed variables.
A typed DataSet is a class that derives from a DataSet. The strongly typed DataSet inherits all the methods,
events, and properties of a DataSet. In addition, a typed DataSet provides us with strongly typed methods,
events, and properties. Therefore, we can access tables and columns by their names instead of using collection-
based methods. This feature of strongly typed DataSets improves the readability of our code and allows the
Visual Studio 2005 code editor to provide the IntelliSense technology, which automatically completes the
statements as we type. The IntelliSense technology increases the quality of our code because it corrects type
mismatch errors at compile time rather than at run time.
We can create a strongly typed DataSet using the command-line utility XSD.exe. The following command
creates a strongly typed DataSet:
xsd.exe /d /l:CS XSDSchemaFileName.xsd /n:XSDSchema.Namespace
We can also use Visual Studio to create Typed DataSet.

Figure 6-21 Generated Typed Data Set

Notice the AdventureWorksDataSet.xsd in the solution explorer. This is the Typed Dataset Visual Studio had
automatically generated for the for the data access example we had just gone through in the previous section.

This allows for IntelliSense to do the grunt of the work for us and thus avoiding mistyping table and column names see
Figure 6-22:

234
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 6-22 intellisense through Typed DataSet

Manually Creating a Typed Dataset


In the previous example the Typed Dataset was automatically generated we’ll now try to manually create a Typed
Dataset.

Open Visual Studio 2005 select File->New->Project. Select the programming language of choice and select Windows
Application as the template of choice. Enter TypedDataSet as the name for the project and select a location to save the
project to see figure 6-23.

235
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 6-23: New Project

To add a new Typed DataSet open Solution Explorer in Visual Studio. If Solution Exploer can’t be found
simply display by selecting View->Solution Explorer. Right click on our project TypedDataSet. On the context
menu select Add->New Item see figure 6-24.

Figure 6-24: Add a new item to the project

By selecting “New Item” a new dialog window appears. It contains a list of Visual Studio Installed
Templates. In this case we want to create a typed DataSet. Select DataSet template from the dialog window.

Figure 6-25 Select a DataSet Template

236
The Complete Reference To Professional SOA with Visual Studio 2005

Right click on the DataSet designer and select Add->TableAdapter. The TableAdapter will help us with
handling the SELECT, INSERT, UPDATE, DELETE operations for the DataSet see figure 6-26.

Tip: To see all of the files associated with the TypedDataSet.xsd file you will need to make sure that the Show All Files button is selected in
the solution explorer.

Figure 6-26: Add a TableAdapter

Once we have selected TableAdapter from the context menu we will be prompted on the location of the
database. Either select an existing ConnectionString or define a new ConnectionString by selecting the New
Connection button see figure 6-27.

237
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 6-27: TableAdapter Configuration Wizard

Selecting the Next button will take us to the next section. Here we are prompted how the TableAdapter is
expected to retrieve the data. We could use SQL statements that we define to access the database. Or we could
create New Stored Procedures to access the database. Lastly we could use existing stored procedures that we had
defined earlier to access the database. In this example we select “Use SQL Statements”.

Figure 6-28: Use SQL statements

We can select the Tables, Views or Functions that we’re interested in. In this case select the Employee table
which is under Human Resources see figure 6-29 and select Add.

238
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 6-29 Visual Studio’s internal Table Listing

We can use Visual Studio’s internal query builder to design the query we need to select from the table see
figure 6-30.

Figure 6-30 Query builder

We can execute our query to validate the result by clicking the Execute Query button. When the wizard has
completed we will have our DataTable see figure 6-31.

239
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 6-31 Employee DataTable

Having a strongly typed DataSet means we will be able to access individual columns within the DataTable
without having to guess the column names. Visual Studio will generate the columns for us. Thus we can access
each column simply by using IntelliSense see figure 6-32.

Figure 6-32 Accessing Typed Dataset

240
The Complete Reference To Professional SOA with Visual Studio 2005

Manually Define Typed Dataset


Alternatively we could manually define Typed Dataset by manually specifying each column name and its data type.

We can do this by right clicking on the Dataset designer and then Add -> DataTable.

We can add columns by selecting the DataTable and then right click and Add -> Column.

Figure 6-33: Manually specified DataTable

We could change the properties of each column by selecting the Column and altering the properties in the properties
window.

Figure 6-34 Properties for DataColumn

241
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 6-35 Typed Dataset Intellisense

Relationships with Typed Dataset


Creating data relationships with Dataset is easy. If a data relationship was already specified in the database. Visual
Studio will mirror that relationship within our Typed Dataset.

Figure 6-36: Visual Studio mirroring a data relationship.

242
The Complete Reference To Professional SOA with Visual Studio 2005

Alternatively if data relationships do not exist we could simply drag and drop the from the Parent key column of one
table to the Foreign key column of another table to establish a new relationship.

Figure 6-37: Data Relation Properties

Just as in the database we could specify the type of constraint to apply to the relationship.

ADO.NET Exception handling in .NET


In the .NET Framework, errors are thrown as exceptions. These exceptions are segmented and protected call
paths, which allow developers to handle errors in a robust manner. We can use a simple try and catch block to
catch and act upon predefined possible error conditions. It is important to note, however, that exceptions are
implemented as classes, and if our catch blocks are looking for a base-class exception before the specific
inherited exception, we may never catch the specific exception. The specific or inherited exception will be
masked by the base class.
Exception handling is important in any application development. However it is important to keep note of the
usage of exception to start from the lowest level of exception to the highest. If we had wanted to catch an
exception that was thrown such as a truncate error we need to start with SqlTruncateException first. Otherwise an
exception handler of catch (Exception ex) will actually catch all exceptions raised and stop the exception from
bubbling up.
An example of incorrect exception usage.

Listing 6-53. Demonstrates the incorrect order of Exception Handling in Visual C#

try
{
...
}
catch (Exception ex)
{

243
The Complete Reference To Professional SOA with Visual Studio 2005

...
}
catch (SqlTypeException sqlTypeEx)
{
...
}
catch (SqlTruncateException sqlTruncateEx)
{
...
}

Listing 6-54. Demonstrates the incorrect order of Exception Handling in Visual Basic .NET

Try
...
Catch ex as Exception
...
Catch sqlTypeEx as SqlTypeException
...
Catch sqlTruncateEx as SqlTruncateException
...
End Try

An example of correct exception usage.

Listing 6-55. Demonstrates the correct order of Exception Handling in Visual C#

try
{
...
}
catch (SqlTruncateException sqlTruncateEx)
{
...
}
catch (SqlTypeException sqlTypeEx)
{
...
}
catch (Exception ex)
{
...
}

Listing 6-56. Demonstrates the correct order of Exception Handling in Visual Basic .NET

Try
...
Catch sqlTruncateEx as SqlTruncateException
...
Catch sqlTypeEx as SqlTypeException
...
Catch ex as Exception
...

244
The Complete Reference To Professional SOA with Visual Studio 2005

End Try

Thus, to write effective exception-handling code, we have to understand the various levels of exception classes
that exist within ADO.NET and use them accordingly.

Writing SQLCLR Stored Procedure with MS SQL


Server 2005
In .NET 2.0 Microsoft allows us to write SQL Server UDT and Stored Procedures within SQL server’s CLR.
This allows developers to add more versatility and flexibility to their development. However we have to keep in
mind that just because we can now imbed .NET C# and VB.NET code within SQL Server does not mean that we
could start embedding business logics within the database layer.

The Context Connection


Inside the SQLCLR, as usual, the basic ADO.NET principles apply. We will need an instance of SqlConnection
in order to connect with the underlying database.
Microsoft created the concept of a context connection so that the database knows to utilize the currently
connected database connection without wastefully creating a new connection. The context connection can be
created using the following connection string: "context connection = true"
Thus, the following instance of SqlConnection holds the context connection, in other words, the same
connection the stored procedure was called upon:

Listing 6-57. Demonstrates setting Context Connection using Visual C#

SqlConnection contextConnection = new SqlConnection("context connection = true");

Listing 6-58. Demonstrates setting Context Connection using Visual Basic .NET

Dim contextConnection as SqlConnection = _


New SqlConnection("context connection = true")
Using a context connection versus a loop-back connection has several advantages:

* By doing so, SQL server skip over the Tabular Data Stream (TDS) protocol layer and the TCP/IP or Named
Pipes protocol layer, and directly get a hold of the connection inside the database.
* We do not need to reauthenticate this saves redundant authorization lookup.
* We have the ability to latch on to a currently running transaction easily.

* Any external noncontext connections created by specifying a full ADO.NET connection string would
automatically try to enlist themselves in the active running transaction and thus be promoted to Microsoft
Distributed Transaction coordinator (MSDTC). The exception to this rule being loop-back connections into the
same SQL Server 2005 database. Such connections cannot enlist themselves in the same transaction and must
use enlist=false in their connection strings to work.

However, there are certain restrictions placed on a context connection as well. These are listed here:

* We can have at most only one open SqlConnection object within the same execution scope.

245
The Complete Reference To Professional SOA with Visual Studio 2005

* Multiple Active Resultsets (MARS) does not work with context connections. (In short, MARS lets us execute
multiple statements and maintain their results on the same connection. It’s important to note that, in reality, the
statements are not executing in parallel, they are only executing on the same connection.)

* SqlBulkCopy does not work with a context connection.


* Update batching does not work with a context connection.
* SqlNotificationRequest cannot be used with commands that execute on a context connection.

* Canceling commands is not supported. SqlCommand.Cancel will be ignored.


* No other connection string keywords can be specified with context connection = true.

We will now look at some examples of using SQL CLR

Figure 6-38: New SQL Server Database Project

Figure 6-39: Use an existing connection or a add a new connection

246
The Complete Reference To Professional SOA with Visual Studio 2005

Alternatively, if we do not have a database reference already set up in our IDE, Visual Studio will prompt us to
create a new database reference.

Figure 6-40: Enable Debugging

Figure 6-40 informs


us that when we debug the CLR stored procedure, all managed threads on the server will stop.
This means that we probably don’t want to do this operation on a critical production server. This operation
should be done on a development machine only. Click YES to accept the new database reference.

Figure 6-41: Create a new Stored Procedure.

We can create a series of SQL Server 2005 items these are, User-Defined Function, Stored Procedure,
Aggregate, Trigger, User-Defined Type.

247
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 6-42 Specify a name for the stored procedure

We can specify the stored procedure name as GetEmployeeByID.cs then click add. A new stored procedure
template with the name we had just entered will appear in the solution explorer.

Figure 6-43 stored procedure template.

Create the first stored procedure by following the Listing 6-1

Listing 6-57. Implementing stored procedure using Visual C#

[Microsoft.SqlServer.Server.SqlProcedure]
public static void GetEmployeeByID(int empid)
{

248
The Complete Reference To Professional SOA with Visual Studio 2005

using (SqlConnection contextConnection =


new SqlConnection("context connection = true"))
{
SqlCommand contextCommand =
new SqlCommand(
"Select * from HumanResources.Employee " +
"where EmployeeID = @empid", contextConnection);
contextCommand.Parameters.AddWithValue("@empid", empid);
contextConnection.Open();
SqlContext.Pipe.ExecuteAndSend(contextCommand);
}
}

Listing 6-57. Implementing stored procedure using Visual Basic .NET

<Microsoft.SqlServer.Server.SqlProcedure()> _
Public Shared Sub GetEmployeeByID(ByVal empid As Integer)
Dim contextConnection As SqlConnection = _
New SqlConnection("context connection = true")
Try
Dim contextCommand As SqlCommand = _
New SqlCommand("Select * from HumanResources.Employee " + _
"where EmployeeID = @empid", contextConnection)
contextCommand.Parameters.AddWithValue("@empid", empid)
contextConnection.Open()
SqlContext.Pipe.ExecuteAndSend(contextCommand)
Finally
CType(contextConnection, IDisposable).Dispose()
End Try
End Sub

Now we can build, and deploy the stored procedures.

249
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 6-44 build the project.

And deploy

Figure 6-45 deploy the project

250
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 6-46

Figure 6-47: MS SQL Server 2005 Management Studio

Now we can execute our first .NET stored procedure. By selecting a new query in SQL Server 2005 Management
Studio and executing it.

exec dbo.getemployeebyid '1'

NOTE: There will most likely be an error message like this:

Msg 6263, Level 16, State 1, Line 1

Execution of user code in the .NET Framework is disabled. Enable "clr enabled"
configuration option.

Tip: In the following example > is used to indicate the command that should be typed.

In order to enable the execution of .NET code inside SQL Server, just issue the following command:

251
The Complete Reference To Professional SOA with Visual Studio 2005

>sp_configure 'show advanced options', 1;

This should give us the message as shown:


Configuration option 'show advanced options' changed from 0 to 1. Run the RECONFIGURE statement to install.
>RECONFIGURE;

This should give us the message as shown:


Command(s) completed successfully.
>sp_configure 'clr enabled', 1

This should give us the message as shown:


Configuration option 'clr enabled' changed from 0 to 1. Run the RECONFIGURE statement to install.
>RECONFIGURE;

This should give us the message as shown:


Command(s) completed successfully.

Now after we had configured SQL Server 2005 to allow .NET CLR we can execute our .NET store procedure
via.
>exec dbo.storedprocedure1 "1"

Figure 6-48: executing the .NET stored procedure.

.NET Stored Procedure with ExecuteReader()


Since we could now embed .NET code within stored procedures, we can manipulate data more easily in the
database. In the following example I am retrieving the Dates that people are hired by their job title.

Listing 6-58. Demonstrates using embed .NET code using Visual C#

[Microsoft.SqlServer.Server.SqlProcedure]
public static void GetEmployeeHireDateByTitle(string Title)

252
The Complete Reference To Professional SOA with Visual Studio 2005

{
// Put your code here
using (SqlConnection contextConnection =
new SqlConnection("context connection = true"))
{
SqlCommand contextCommand =
new SqlCommand(
"Select HireDate from HumanResources.Employee " +
"where Title = @title", contextConnection);
contextCommand.Parameters.AddWithValue("@title", Title);
contextConnection.Open();
// first, create the record and specify the
// metadata for the results
SqlDataRecord rec = new SqlDataRecord(
new SqlMetaData("HireDate", SqlDbType.VarChar, 50)
);
// start a new result set
SqlContext.Pipe.SendResultsStart(rec);
// send rows
SqlDataReader rdr = contextCommand.ExecuteReader();
while (rdr.Read())
{

rec.SetString(0, "Hired on: " +


rdr.GetDateTime(0).ToShortDateString());
SqlContext.Pipe.SendResultsRow(rec);
}
// complete the result set
SqlContext.Pipe.SendResultsEnd();
contextConnection.Close();
}
}

Listing 6-59. Demonstrates using embed .NET code using Visual Basic .NET

<Microsoft.SqlServer.Server.SqlProcedure()> _
Public Shared Sub GetEmployeeHireDateByTitle(ByVal Title As String)
' Using
Dim contextConnection As SqlConnection = _
New SqlConnection("context connection = true")
Try
Dim contextCommand As SqlCommand = _
New SqlCommand
("Select HireDate from HumanResources.Employee " + _
"where Title = @title", contextConnection)
contextCommand.Parameters.AddWithValue("@title", Title)
contextConnection.Open()
Dim rec As SqlDataRecord = _
New SqlDataRecord(New SqlMetaData("HireDate",
SqlDbType.VarChar, 50))
SqlContext.Pipe.SendResultsStart(rec)
Dim rdr As SqlDataReader = contextCommand.ExecuteReader
While rdr.Read

253
The Complete Reference To Professional SOA with Visual Studio 2005

rec.SetString(0, "Hired on: " + _


rdr.GetDateTime(0).ToShortDateString)
SqlContext.Pipe.SendResultsRow(rec)
End While
SqlContext.Pipe.SendResultsEnd()
Finally
CType(contextConnection, IDisposable).Dispose()
End Try
End Sub

In the listings above, we have created a stored procedure using .NET code. This is first achieved by
decorating our method with the Microsoft.SqlServer.Server.SqlProcedure attribute, this tells the compiler that the
method GetEmployeeHireDateByTitle() function is to be deployed as a stored procedure. Because this is a stored
procedure and thus we will use context connection = true as the connection string so that the database will not
waste a new connection back onto itself. Once the connection is established we will create a SqlCommand to
perform our operation that we call contextCommand. This command will be used to perform operations against
the database. As soon as the connection is opened using contextCommand the command executed.
We now need to build the metadata required for the result. This is just a way of telling SQL Server what
type of data we expect to be returned from our execution.

Listing 6-60. Demonstrates building metadata in Visual C#

SqlDataRecord rec = new SqlDataRecord(


new SqlMetaData("HireDate", SqlDbType.VarChar, 50));

Listing 6-61. Demonstrates building metadata in Visual Basic .NET

Dim rec As SqlDataRecord = _


New SqlDataRecord(New SqlMetaData("HireDate", SqlDbType.VarChar, 50))
We then use SqlContext.Pipe which allows us to send the results of executing commands back to the client.
There is a lot of flexibility as we can read the result from our execution back row by row using the
SqlCommand’s ExecuteReader. Once we’re satisfied we can then send the result back to the client using
SqlContext.Pipe.SendResultsRow().

Listing 6-62. Demonstrates how to use SqlContext.Pipe in Visual C#

SqlContext.Pipe.SendResultsStart(rec);
// send rows
SqlDataReader rdr = contextCommand.ExecuteReader();
while (rdr.Read())
{

rec.SetString(0, "Hired on: " +


rdr.GetDateTime(0).ToShortDateString());
SqlContext.Pipe.SendResultsRow(rec);
}
// complete the result set
SqlContext.Pipe.SendResultsEnd();

Listing 6-63. Demonstrates how to use SqlContext.Pipe in Visual Basic .NET

SqlContext.Pipe.SendResultsStart(rec)
Dim rdr As SqlDataReader = contextCommand.ExecuteReader

254
The Complete Reference To Professional SOA with Visual Studio 2005

While rdr.Read
rec.SetString(0, "Hired on: " + _
rdr.GetDateTime(0).ToShortDateString)
SqlContext.Pipe.SendResultsRow(rec)
End While
SqlContext.Pipe.SendResultsEnd()

We can now Build and Deploy.


Once the stored procedure had been deployed we can execute it by simply entering exec
dbo.GetEmployeeHireDateByTitle 'Design Engineer' into SQL Server’s query window. We should get the result
shown below in Figure 6-49:

Figure 6-49: shows the result set from executing the stored procedure.

TIP: .NET 2.0 and Sql Server 2005 is not only restricted to allowing .NET code running in stored procedure. We could also create Stored
Procedure, User-Defined Function, Trigger, Aggregate and User-Defined Type. Unfortunately we can not cover all of these within this
book.

Summary
In this chapter we have learned that ADO.NET enables datacentric applications to connect to various data
sources and retrieve, manipulate, and update data. ADO.NET uses XML to transfer data across applications and
data sources. This enables us to use ADO.NET to access any data source including SQL Server and other
database servers that use OLE DB to expose data.
We have also learned about .NET data providers and that it forms the interface between the application and
the data source. The data providers that the .NET Framework provides allows us to connect to various data
sources such as SQL Server 7.x or later and OLE DB. A data adapter forms an interface between the application

255
The Complete Reference To Professional SOA with Visual Studio 2005

and the data source for retrieving and saving data. The OleDbDataAdapter, SqlDataAdapter and OracleDataAdapter
object represents a connection and a set of Command objects that help populate a DataSet object.
To use ADO.NET we can use an ADO.NET DataReader. The ADO.NET DataReader allows us to read the
read-only, forward-only data from a data source. To create a DataReader object, we can execute the
ExecuteReader() method of the appropriate class.
We have also looked at ADO.NET DataSets and investigated the difference between strongly Typed
Datasets and Untyped DataSets. Strongly Typed Datasets provide typed support to our data structure. The typing
also allows Visual Studio 2005 to provide intellisense support whilst we program. This helps to avoid errors with
names during development.
An ADO.NET DataSet is a collection of tables and information about the relationships between tables. Both
Typed and Untyped DataSets provide a disconnected view of a data source. ADO.NET DataSets enable us to
store data from multiple data sources. We can create relationships between the tables in a DataSet, even though
the relationships might not exist between the tables in the data sources. In addition, We can create different data
views from the data contained within the DataSets.
With the introduction of Visual Studio 2005 and MS SQL Server 2005 we can now execute .NET code
within MS SQL Server 2005. This allows for more flexibility in data manipulation within the database.

256
The Complete Reference To Professional SOA with Visual Studio 2005

Chapter 7 Accessing
Manipulating XML with .NET
XML is central to data exchange between applications in the .NET Framework. We need to know the XML
Document Object Model (DOM) and how to access XML data in our applications. The Microsoft .NET
Framework version 2.0 includes many design and functionality changes to the XML Manipulation. The changes
will provide better efficiency.
In this chapter will be learning how to read and write data to and from an XML document. We will also be
looking at performing operations on XML documents using XPATH. We will also learn how to validate a XML
document against its XML Schema (XSD) using .NET. Lastly we will look at how to populate a DataSet with
data from a XML file and how to write data back into the XML file.

Document Object Model


We will start be examining the XML Document Object Model (XML DOM) and what constitutes a well-formed
XML document. We will also investigate how to use the objects available in the XML DOM to read and write
XML data. Finally, we will look at how to create an XML Parser in Visual Studio .NET.

Listing 7-1. XML document for the CD Catalogue

<?xml version="1.0" encoding="ISO-8859-1"?>


<CATALOG>
<CD>
<TITLE>Empire Burlesque</TITLE>
<ARTIST>Bob Dylan</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>Columbia</COMPANY>
<PRICE>10.90</PRICE>
<YEAR>1985</YEAR>
</CD>
<CD>
<TITLE>Hide your heart</TITLE>
<ARTIST>Bonnie Tyler</ARTIST>
<COUNTRY>UK</COUNTRY>
<COMPANY>CBS Records</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1988</YEAR>
</CD>
<CD>
<TITLE>Greatest Hits</TITLE>
<ARTIST>Dolly Parton</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>RCA</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1982</YEAR>

257
The Complete Reference To Professional SOA with Visual Studio 2005

</CD>
</CATALOG>

In the above example the XML code contains CD information for a record catalog information for three
CDs. The XML document is a well-formed XML document. A well-formed XML document contains an end tag
for every begin tag. For example, for every < CD > tag, a </ CD > tag should be present. A well-formed XML
document can have an associated document type definition (DTD) or an XML Schema that describes the data
and the relationship between the data within an XML document.

Listing 7-2. DTD for the Catalogue

<!ELEMENT ARTIST ( #PCDATA ) >

<!ELEMENT CATALOG ( CD+ ) >

<!ELEMENT CD ( TITLE, ARTIST, COUNTRY, COMPANY, PRICE, YEAR ) >

<!ELEMENT COMPANY ( #PCDATA ) >

<!ELEMENT COUNTRY ( #PCDATA ) >

<!ELEMENT PRICE ( #PCDATA ) >

<!ELEMENT TITLE ( #PCDATA ) >

<!ELEMENT YEAR ( #PCDATA ) >

Listing 7-3. XML Schema

<?xml version="1.0" encoding="UTF-8" ?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="ARTIST">
<xs:complexType mixed="true" />
</xs:element>

<xs:element name="CATALOG">
<xs:complexType>
<xs:sequence>
<xs:element ref="CD" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>

<xs:element name="CD">
<xs:complexType>
<xs:sequence>
<xs:element ref="TITLE" />
<xs:element ref="ARTIST" />
<xs:element ref="COUNTRY" />
<xs:element ref="COMPANY" />
<xs:element ref="PRICE" />
<xs:element ref="YEAR" />

258
The Complete Reference To Professional SOA with Visual Studio 2005

</xs:sequence>
</xs:complexType>
</xs:element>

<xs:element name="COMPANY">
<xs:complexType mixed="true" />
</xs:element>

<xs:element name="COUNTRY">
<xs:complexType mixed="true" />
</xs:element>

<xs:element name="PRICE">
<xs:complexType mixed="true" />
</xs:element>

<xs:element name="TITLE">
<xs:complexType mixed="true" />
</xs:element>

<xs:element name="YEAR">
<xs:complexType mixed="true" />
</xs:element>

</xs:schema>

The DTD similar to a XML Schema specifies the syntax of an application of XML. DTDs have a syntax that
is different from XML. The difference between DTD and XML Schema is that XML Schema uses XML
document syntax. Even though using XML doesn’t necessarily improve the quality of the description. However
it does improve the extensibility. Because of this XML Schemas can have a richer and more complex internal
structure than that of DTD.
Both DTD and XML Schema can be used to validate XML documents.
Using the DOM an XML document is read into memory and a tree of nodes is formed. The node types for
the nodes are decided as they are created. There are several kinds of node types that had been defined by the
World Wide Web Consortium (W3C) for DOM. The following table lists the node types, the object assigned to
that node type, and a short description of each.

Table 7-1. The XML DOM contains different types of nodes. The table below contains the most commonly used nodes and
their descriptions.

DOM node type Object Description


Document XmlDocument Class The container of all the nodes in the tree. It is also
known as the document root, which is not always
the same as the root element.
DocumentFragment XmlDocumentFragment A temporary bag containing one or more nodes
Class without any tree structure.
DocumentType XmlDocumentType Class Represents the <!DOCTYPE…> node.
EntityReference XmlEntityReference Class Represents the non-expanded entity reference
text.
Element XmlElement Class Represents an element node.
Attr XmlAttribute Class Is an attribute of an element.

259
The Complete Reference To Professional SOA with Visual Studio 2005

ProcessingInstruction XmlProcessingInstruction Is a processing instruction node.


Class
Comment XmlComment Class A comment node.
Text XmlText Class Text belonging to an element or attribute.
CDATASection XmlCDataSection Class Represents CDATA.
Entity XmlEntity Class Represents the <!ENTITY…> declarations in
an XML document, either from an internal
document type definition (DTD) subset or from
external DTDs and parameter entities.
Notation XmlNotation Class Represents a notation declared in the DTD.

There is also another of way of reading XML documents that is using Simple API for XML (SAX) to read
data from XML documents. The difference between SAX and DOM is that SAX does not load the entire XML
document into memory. The content is rather read in a sequential manner. Using SAX we can program events to
occur as the XML document is being read. Since SAX does not load the XML document into memory, it is more
efficient for reading larger XML documents. However the limitation of using SAX is that SAX does not
maintain a structure that can be used in more complex operations. We also can not use SAX when we need to
modify the XML document.
We can also read XML documents using .NET Framework’s XmlReader class. The XmlReader class
provides forward only and read only access to XML documents. Unlike the DOM the XmlReader does not load
the XML document into memory.
In the DOM the XML document is structured. The document is represented by the XmlDocument object.
The XmlDocument object is part of the System.Xml namespace.
The XmlDocument object can be used to load and save XML documents. Using the XmlDocument object will provide
us with access to all the nodes in the document. The following example demonstrates using XmlDocument to load a
XML document.

Listing 7-4. Demonstrates loading a XML document using XmlDocument using Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace CSLoadDOM
{
class Program
{
static void Main(string[] args)
{
XmlDocument myDocument = new XmlDocument();
myDocument.Load("cd_catalog.xml");
Console.WriteLine(myDocument.InnerXml.ToString());
Console.ReadLine();
}
}
}

Listing 7-5. Demonstrates loading a XML document using XmlDocument using Visual Basic .NET

Imports System.Xml

260
The Complete Reference To Professional SOA with Visual Studio 2005

Module Program

Sub Main()
Dim myDocument As XmlDocument = New XmlDocument
myDocument.Load("cd_catalog.xml")
Console.WriteLine(myDocument.InnerXml.ToString)
Console.ReadLine()
End Sub

End Module
This code snippet uses the XmlDocument object and loads the XML document into the variable
myDocument (the cd_catalog.xml file is shown in Listing 7-1). There are two ways of loading the XML
document into a variable. We can use the Load method and specify the file name as the parameter. Sometimes
the XML content is not always readily available in a file. Alternatively, we can use the LoadXml method and
specify the XML data as the parameter. The following code snippet shows the usage of the LoadXml method.

Listing 7-6. Demonstrates loading an XML document from a string using Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace CSLoadDOM2
{
class Program
{
static void Main(string[] args)
{
XmlDocument myDocument = new XmlDocument();
myDocument.LoadXml(
@"<?xml version=""1.0"" encoding=""ISO-8859-1\""?>
<CATALOG>
<CD>
<TITLE>Empire Burlesque</TITLE>
<ARTIST>Bob Dylan</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>Columbia</COMPANY>
<PRICE>10.90</PRICE>
<YEAR>1985</YEAR>
</CD>
<CD>
<TITLE>Hide your heart</TITLE>
<ARTIST>Bonnie Tyler</ARTIST>
<COUNTRY>UK</COUNTRY>
<COMPANY>CBS Records</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1988</YEAR>
</CD>
<CD>
<TITLE>Greatest Hits</TITLE>
<ARTIST>Dolly Parton</ARTIST>
<COUNTRY>USA</COUNTRY>

261
The Complete Reference To Professional SOA with Visual Studio 2005

<COMPANY>RCA</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1982</YEAR>
</CD>
</CATALOG>");
Console.WriteLine(myDocument.InnerXml.ToString());
Console.ReadLine();
}
}
}

Listing 7-7. Demonstrates loading an XML document from a string using Visual Basic .NET

Imports System.Xml
Module Module1

Sub Main()
Dim myDocument As XmlDocument = New XmlDocument
myDocument.LoadXml("<?xml version=""1.0"" encoding=""ISO-8859-1""?> " & _
"<CATALOG> "&_
" <CD> "&_
" <TITLE>Empire Burlesque</TITLE> "&_
" <ARTIST>Bob Dylan</ARTIST> "&_
" <COUNTRY>USA</COUNTRY> "&_
" <COMPANY>Columbia</COMPANY> "&_
" <PRICE>10.90</PRICE> "&_
" <YEAR>1985</YEAR> "&_
" </CD> "&_
" <CD> "&_
" <TITLE>Hide your heart</TITLE> "&_
" <ARTIST>Bonnie Tyler</ARTIST> "&_
" <COUNTRY>UK</COUNTRY> "&_
" <COMPANY>CBS Records</COMPANY> "&_
" <PRICE>9.90</PRICE> "&_
" <YEAR>1988</YEAR> "&_
" </CD> "&_
" <CD> "&_
" <TITLE>Greatest Hits</TITLE> "&_
" <ARTIST>Dolly Parton</ARTIST> "&_
" <COUNTRY>USA</COUNTRY> "&_
" <COMPANY>RCA</COMPANY> "&_
" <PRICE>9.90</PRICE> "&_
" <YEAR>1982</YEAR> "&_
" </CD> "&_
"</CATALOG> ")
Console.WriteLine(myDocument.InnerXml.ToString)
Console.ReadLine()
End Sub

End Module
The XmlDocument object can also be used to write XML data into files. To write XML data, you can use
the Save method. The following example shows how to use XmlDocument Save method listing 7-8.

262
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 7-8. Writing an XML document from a string of XML using Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace CSSaveDOM
{
class Program
{
static void Main(string[] args)
{
XmlDocument myDocument = new XmlDocument();
myDocument.LoadXml(
@"<?xml version=""1.0"" encoding=""utf-8"" ?>
<CATALOG>
<CD>
<TITLE>Empire Burlesque</TITLE>
<ARTIST>Bob Dylan</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>Columbia</COMPANY>
<PRICE>10.90</PRICE>
<YEAR>1985</YEAR>
</CD>
<CD>
<TITLE>Hide your heart</TITLE>
<ARTIST>Bonnie Tyler</ARTIST>
<COUNTRY>UK</COUNTRY>
<COMPANY>CBS Records</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1988</YEAR>
</CD>
<CD>
<TITLE>Greatest Hits</TITLE>
<ARTIST>Dolly Parton</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>RCA</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1982</YEAR>
</CD>
</CATALOG>");
myDocument.Save("Catalgue.xml");
Console.WriteLine("Document had been saved.");
Console.WriteLine(myDocument.InnerXml.ToString());
Console.ReadLine();

}
}
}

Listing 7-9. Writing an XML document from a string of XML usingVisual Basic .NET

Imports System.Xml

263
The Complete Reference To Professional SOA with Visual Studio 2005

Module Module1

Sub Main()
Dim myDocument As XmlDocument = New XmlDocument
myDocument.LoadXml("<?xml version=""1.0"" encoding=""utf-8"" ?> " & _
"<CATALOG> "&_
" <CD> "&_
" <TITLE>Empire Burlesque</TITLE> "&_
" <ARTIST>Bob Dylan</ARTIST> "&_
" <COUNTRY>USA</COUNTRY> "&_
" <COMPANY>Columbia</COMPANY> "&_
" <PRICE>10.90</PRICE> "&_
" <YEAR>1985</YEAR> "&_
" </CD> "&_
" <CD> "&_
" <TITLE>Hide your heart</TITLE> "&_
" <ARTIST>Bonnie Tyler</ARTIST> "&_
" <COUNTRY>UK</COUNTRY> "&_
" <COMPANY>CBS Records</COMPANY> "&_
" <PRICE>9.90</PRICE> "&_
" <YEAR>1988</YEAR> "&_
" </CD> "&_
" <CD> "&_
" <TITLE>Greatest Hits</TITLE> "&_
" <ARTIST>Dolly Parton</ARTIST> "&_
" <COUNTRY>USA</COUNTRY> "&_
" <COMPANY>RCA</COMPANY> "&_
" <PRICE>9.90</PRICE> "&_
" <YEAR>1982</YEAR> "&_
" </CD> "&_
"</CATALOG> ")
myDocument.Save("Catalgue.xml")
Console.WriteLine("Document had been saved.")
Console.WriteLine(myDocument.InnerXml.ToString)
Console.ReadLine()
End Sub

End Module

The XML Parser


In this section, we will create an XML parser that reads an XML document and displays the contents in a console
window. The following piece of code shows how to create an XML parser.

Listing 7-10. Demonstrates Parsing an XML document using Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace CSXmlParser
{

264
The Complete Reference To Professional SOA with Visual Studio 2005

class Program
{
static void Main(string[] args)
{
try
{
XmlDocument myDocument = new XmlDocument();

myDocument.Load("cd_catalog.xml");
int i;
int count;
count = 0;
i = 1;
XmlNode node = myDocument.ChildNodes[1];
foreach (XmlNode node1 in node.ChildNodes)
{
Console.WriteLine("\n");

Console.WriteLine(
"The elements under node number: {0}", i);
Console.WriteLine(
"------------------------------------------");
foreach (XmlNode node2 in node1.ChildNodes)
{
Console.WriteLine(
myDocument.DocumentElement.FirstChild.
ChildNodes[count].Name + ": " +
node2.FirstChild.Value);
count = count + 1;
}
i = i + 1;
count = 0;
}
Console.WriteLine("\n");
Console.WriteLine("Press <Enter> to quit...");
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.ReadLine();
}

}
}
}

Listing 7-11. Demonstrates Parsing an XML document using Visual Basic .NET

Imports System.Xml
Module Module1

Sub Main()

265
The Complete Reference To Professional SOA with Visual Studio 2005

Try
Dim myDocument As XmlDocument = New XmlDocument
myDocument.Load("cd_catalog.xml")
Dim i As Integer
Dim count As Integer
count = 0
i=1
Dim node As XmlNode = myDocument.ChildNodes(1)
For Each node1 As XmlNode In node.ChildNodes
Console.WriteLine("")
Console.WriteLine(
"The elements under node number: {0}", i)
Console.WriteLine(
"------------------------------------------")
For Each node2 As XmlNode In node1.ChildNodes
Console.WriteLine(myDocument.DocumentElement _
.FirstChild.ChildNodes(count).Name + ": " + _
node2.FirstChild.Value)

count = count + 1
Next
i=i+1
count = 0
Next
Console.WriteLine("")
Console.WriteLine("Press <Enter> to quit...")
Console.ReadLine()
Catch e As Exception
Console.WriteLine(e.Message)
Console.ReadLine()
End Try

End Sub

End Module

In the code above we’re accessing the first child node in the XML through myDocument.ChildNodes[1].
Then once we have the node object we can iterate through the child nodes and access the node’s Name
myDocument.DocumentElement.FirstChild.ChildNodes[count].Name as well as its Value node2.FirstChild.Value.

XmlReader and XmlWriter


We can use the XmlReader and the XmlWriter classes to read and write XML data from either steam or file. The
XmlReader class provides a fast, non cacheable, read only and forward only means to access XML Data. We
can use XmlReader to determine depth of a node in an XML document and whether the node has attributes, the
number of attributes in that node and the value of a particular attribute.
The XmlTextReader class is a class that is derived from the XmlReader class. The XmlTextReader class can
be used to read XML data. The XmlTextReader class is only for reading xml documents we can not use it to
access or validate a document against its Document Type Definition (DTD) or its XML Schema (XSD)
information. In order to perform validation we must use the XmlValidatingReader class, which is another
derived class of the XmlReader class.

266
The Complete Reference To Professional SOA with Visual Studio 2005

Reading XML using XmlTextReader


The XmlTextReader class is used when we need fast access to XML data but don’t necessarily need to validate
the information against a DTD or XML Schema. The XmlTextReader reads the XML file sequentially thus it
does not store the document in memory.

Table 7-2. Common XmlTextReader properties

Methods Description

AttributeCount Gets an Integer value specifying the number of attributes on the


current node
Depth Gets an Integer value specifying the depth of the current node in an
XML document
HasAttributes Gets a Boolean value specifying whether a node has attributes
HasValue Gets a Boolean value specifying whether the current node can have a
value
IsEmptyElement Gets a Boolean value indicating whether the current node is empty
Item Gets the value of an attribute as String
Value Gets the text value of the current node

Table 7-3. Common XmlTextReader Methods

Methods Description

IsStartElement Checks if the element is the start element


MoveToElement Moves to the element that contains the current attribute node
MoveToFirstAttribute Moves to the first attribute
MoveToNextAttribute Moves to the next attribute
Read Reads the next node from the stream
ReadAttributeValue Reads the attribute value and parses it into one or more nodes
ReadString Reads the content of an element or text node in text
ReadStartElement Checks if the current node is an element and moves the reader
to the next node
ReadEndElement Checks if the current node is an end tag and moves the reader
to the next node
Skip Skips the children of the current node
Using the XmlTextReader is quite simple. We simply create a XmlTextReader object to read data from the
XML document shown in the example below.
Using Visual C#
XmlTextReader textReader = new XmlTextReader("cd_catalog.xml");
Using Visual Basic .NET

267
The Complete Reference To Professional SOA with Visual Studio 2005

Dim textReader As New XmlTextReader("cd_catalog.xml")


We can also initialize an XmlTextReader object to read data from a stream as shown in the following code.

Listing 7-12. Shows how to read XML data from a stream using XmlTextReader with Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace CSXMLReader2
{
class Program
{
static void Main(string[] args)
{
System.IO.StringReader stream;
stream = new System.IO.StringReader(
"<?xml version=\"1.0\"?>" +
"<CATALOG> "+
" <CD> "+
" <TITLE>Empire Burlesque</TITLE> "+
" <ARTIST>Bob Dylan</ARTIST> "+
" <COUNTRY>USA</COUNTRY> "+
" <COMPANY>Columbia</COMPANY> "+
" <PRICE>10.90</PRICE> "+
" <YEAR>1985</YEAR> "+
" </CD> "+
"</CATALOG> ");
XmlTextReader textReader = new XmlTextReader(stream);
}
}
}

Listing 7-13. Shows how to read XML data from a stream using XmlTextReader with Visual Basic .NET

Imports System.Xml
Module Module1

Sub Main()
Dim stream As New System.IO.StringReader( _
"<?xml version=""1.0""?>" & _
"<CATALOG>" & _
" <CD> "&_
" <TITLE>Empire Burlesque</TITLE> "&_
" <ARTIST>Bob Dylan</ARTIST> "&_
" <COUNTRY>USA</COUNTRY> "&_
" <COMPANY>Columbia</COMPANY> "&_
" <PRICE>10.90</PRICE> "&_
" <YEAR>1985</YEAR> "&_
" </CD> "&_
"</CATALOG> ")

Dim textReader As New XmlTextReader(stream)

268
The Complete Reference To Professional SOA with Visual Studio 2005

End Sub

End Module
The following code shows how to read data from an XML file using the XmlTextReader class.

Listing 7-14. Reading an XML document from file using XMLTextReader. We then iterate through the different node types
using Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace CSXMLReader3
{
class Program
{
static void Main(string[] args)
{
XmlTextReader reader = new XmlTextReader("cd_catalog.xml");
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
Console.Write("<" + reader.Name);
while (reader.MoveToNextAttribute())
{
Console.Write(" " + reader.Name + "='" +
reader.Value + "'");
}
Console.Write(">");
if (reader.HasAttributes)
{
while (reader.MoveToNextAttribute())
Console.Write(" " + reader.Value + " ");
}
break;
case XmlNodeType.Text:
Console.Write(reader.Value);
break;
case XmlNodeType.EndElement:
Console.WriteLine(("</" + reader.Name + ">"));
break;
}
}

Console.ReadLine();
}
}
}

269
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 7-15. Reading an XML document from file using XMLTextReader. We then iterate through the different node types
using Visual Basic .NET

Imports System.Xml
Module Module1

Sub Main()
Dim reader As New XmlTextReader("cd_catalog.xml")
While reader.Read()
Select Case reader.NodeType
Case XmlNodeType.Element
Console.Write("<" + reader.Name)
While (reader.MoveToNextAttribute())
Console.Write(" " & reader.Name & "='" & _
reader.Value & "'")
End While
Console.Write(">")
If reader.HasAttributes Then
While reader.MoveToNextAttribute
Console.Write(" " & reader.Value & " ")
End While
End If
Case XmlNodeType.Text
Console.Write(reader.Value)
Case XmlNodeType.EndElement
Console.WriteLine(("</" & reader.Name & ">"))
End Select
End While
Console.ReadLine()
End Sub

End Module
In the code above we’re using XmlTextReader to read in our cd_catalog.xml file. We’re reading one row at a
time by examining reader.NodeType we can determine if the XmlTextReader is currently reading an element
XmlNodeType.Element or the text between the elements XmlNodeType.Text or an end element tag
XmlNodeType.EndElement.

270
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 7-1. XML result from the code

Writing XML Using XmlTextWriter


In the previous section we looked at reading xml using XmlTextReader. Now we will examine the XmlWriter
class. The XmlWriter class is an abstract class that allow us to create XML streams and write data to well-
formed XML documents. XmlWriter is used to perform tasks such as:

* Writing multiple documents into one output stream,

* Writing valid names and tokens into the stream,


* Encoding binary data and writing text output,
* Managing output, and

* Flushing and closing the output stream.

The XmlTextWriter class has the following commonly used properties and methods that can be used to save
XML to file or stream.

Table 7-4. Commonly used properties of XmlTextWriter

Methods Description

BaseStream Gets the stream to which XmlTextWriter writes the output

Formatting Specifies the formatting of the output, which can be Indented


or None. If the Formatting is Indented, the child elements are
indented using the Indentaion and IndentChar properties.

Indentation Specifies the number of the IndentChars to use when writing


the child elements.

IndentChar Gets or sets the indenting character when formatting is set to


Formatting.Indented.

WriteState Gets the state of the writer. The valid values for WriteState
include Start, Element, Attribute, Content, Prolog, and Closed.

Table 7-5. Commonly used methods of XmlTextWriter

Methods Description

WriteStartDocument Writes the following XML declaration to the start of the document: <?xml
version="1.0" ?>

WriteStartElement Writes the start tag of a specified element

WriteElementString Writes an element containing a string value

271
The Complete Reference To Professional SOA with Visual Studio 2005

WriteStartAttribute Writes the start of an attribute

WriteAttributeString Writes the value of a given attribute

WriteEndAttribute Writes the end of an attribute

WriteEndElement Writes the end tag of an element

The following code shows how we can use XmlTextWriter to write XML to a file.

Listing 7-16. Writing XML using XmlTextWriter with Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace CSXMLWriter
{
class Program
{
static void Main(string[] args)
{
XmlTextWriter textWriter =
new XmlTextWriter("catalog_out.xml",
System.Text.Encoding.UTF8);
textWriter.Formatting = Formatting.Indented;
textWriter.WriteStartDocument(false);
textWriter.WriteDocType("CATALOG", null, null, null);
textWriter.WriteComment("XML Catalog output");
textWriter.WriteStartElement("CATALOG");
textWriter.WriteStartElement("CD", null);
textWriter.WriteElementString(
"TITLE", "Empire Burlesque");
textWriter.WriteElementString("ARTIST", "Bob Dylan");
textWriter.WriteElementString("COUNTRY", "USA");
textWriter.WriteElementString("COMPANY", "Columbia");
textWriter.WriteElementString("PRICE", "10.90");
textWriter.WriteElementString("YEAR", "1985");
textWriter.WriteEndElement();
textWriter.WriteEndElement();

//Write the XML to file and close the textWriter


textWriter.Flush();
textWriter.Close();
Console.WriteLine("Press <Enter> to exit.");
Console.Read();

}
}
}

272
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 7-17. Writing XML using XmlTextWriter with Visual Basic .NET

Imports System.Xml
Module Module1

Sub Main()
Dim textWriter As XmlTextWriter =
New XmlTextWriter("catalog_out.xml",
System.Text.Encoding.UTF8)
textWriter.Formatting = Formatting.Indented
textWriter.WriteStartDocument(False)
textWriter.WriteDocType("CATALOG", Nothing, Nothing, Nothing)
textWriter.WriteComment("XML Catalog output")
textWriter.WriteStartElement("CATALOG")
textWriter.WriteStartElement("CD", Nothing)
textWriter.WriteElementString("TITLE", "Empire Burlesque")
textWriter.WriteElementString("ARTIST", "Bob Dylan")
textWriter.WriteElementString("COUNTRY", "USA")
textWriter.WriteElementString("COMPANY", "Columbia")
textWriter.WriteElementString("PRICE", "10.90")
textWriter.WriteElementString("YEAR", "1985")
textWriter.WriteEndElement()
textWriter.WriteEndElement()
textWriter.Flush()
textWriter.Close()
Console.WriteLine("Press <Enter> to exit.")
Console.Read()
End Sub

End Module
In listing 7-16 and listing 7-17 we’re writing out a xml document of the CD catalog. We specify a encoding
type of UTF8 System.Text.Encoding.UTF8 then we ask the text writer to take care of our Xml indenting
Formatting.Indented. Following that we create an Xml DOCTYPE of CATALOG by using WriteDocType. Using
WriteStartElement and WriteEndElement we can write our XML document’s start and end tags. In between the
Xml document’s start and end tags we use WriteElementString to insert the xml elements.
XmlTextWriter also provides WriteComment which allows us to embed an Xml comment anywhere within
the document.

<?xml version="1.0" encoding="utf-8" standalone="no"?>


<!DOCTYPE CATALOG>
<!--XML Catalog output-->
<CATALOG>
<CD>
<TITLE>Empire Burlesque</TITLE>
<ARTIST>Bob Dylan</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>Columbia</COMPANY>
<PRICE>10.90</PRICE>
<YEAR>1985</YEAR>
</CD>
</CATALOG>

The above xml document shows the output from listing 7-16 and listing 7-17.

273
The Complete Reference To Professional SOA with Visual Studio 2005

XPathNavigator
In the previous section we had examined how to read and write XML Documents. In this section we will
examine how to use XPath to access a node or a set of nodes. The .NET Framework provides the
XPathNavigator class which contains the methods that we use to perform XPath queries on an XML document.
XPath allows us to perform specific operations on a XML document through specific XPath expressions.
These operations can manipulate strings, perform calculations and check for conditions. XPath treats a XML
document as a tree that contains different types nodes of elements and attributes. We can create XPath
expressions that identify specific nodes in the document based on their type, name and value. In addition, XPath
expressions can identify relationships between nodes in a document.

XPath
To execute XPath queries we need to first select a set of nodes to perform the XPath queries against. The Select
method provided by the XPathNavigator object is used to select a set of nodes. The Select method is used to
select a particular node which then returns an object of XPathNodeIterator class. We can use then use the
XPathNodeIterator object to iterate through the selected nodes. In addition there are also several other select
methods that can be used these are SelectChildren, SelectAncestors, SelectDecendents. The following example
demonstrates how to iterate a set of nodes using the the XPathNavigator object.

Listing 7-18. Demonstrates how to use XPath query to select a node usingVisual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.XPath;

namespace CSXMLXpath
{
class Program
{
static void Main(string[] args)
{
XPathDocument Doc = new XPathDocument("cd_catalog.xml");
XPathNavigator navigator = Doc.CreateNavigator();
XPathNodeIterator iterator = navigator.Select("/CATALOG/CD/TITLE");
while (iterator.MoveNext())
{
Console.WriteLine(iterator.Current.Name + " -> " +
iterator.Current.Value
);
}
Console.ReadLine();
}
}
}

Listing 7-19. Demonstrates how to use XPath query to select a node using Visual Basic .NET

Imports System.Xml.XPath
Module Module1

274
The Complete Reference To Professional SOA with Visual Studio 2005

Sub Main()
Dim Doc As XPathDocument = New XPathDocument("cd_catalog.xml")
Dim navigator As XPathNavigator = Doc.CreateNavigator
Dim iterator As XPathNodeIterator = _
navigator.Select("/CATALOG/CD/TITLE")
While iterator.MoveNext
Console.WriteLine(iterator.Current.Name + " -> " + _
iterator.Current.Value)
End While
Console.ReadLine()
End Sub

End Module

Figure 7-2. shows the output from listing 7-18 and listing 7-19

Aside from the Select method, the XPathNavigator class also provide additional methods which can be used
to select a set of nodes. These methods allow us to retrieve nodes faster than retrieving nodes using the
corresponding XPath query. The optimized methods are:

* SelectChildren, which selects all the child nodes of the current node that match the selection criteria.

* SelectAncestors, which selects all the ancestor nodes of the current node that have a matching
XPathNodeType.
* SelectDescendants - which selects all the descendant nodes of the current node that match the selection criteria.

* and IsDescendant - Determines whether the specified XPathNavigator is a descendant of the current
XPathNavigator.

Calling the above methods will not affect the state or position of the XPathNavigator object. All the methods
return an XPathNodeIterator object with exception of IsDescendant which returns a Boolean value.

Table 7-6. Navigation Methods of the XPathNavigator Object

275
The Complete Reference To Professional SOA with Visual Studio 2005

Method Description

MoveTo This method allows us to move the XPathNavigator object to another node and make
it the current position. The MoveTo method returns a Boolean value to indicate the
success or failure of the movement.

MoveToNext This method allows us to move the XPathNavigator object to the next sibling of the
current node.

MoveToPrevious This method allows us to move the XPathNavigator object to the previous sibling of
the current node.

MoveToFirst This method allows us to move the XPathNavigator object to the first sibling of the
current node.

MoveToFirstChild This method allows us to move the XPathNavigator object to the first child of the
current node. We can use the MoveToFirstChild method only when the current node
is the root node or is a node that has child nodes. If no child nodes exist then a
Boolean value is returned indicating that the move had failed.

MoveToParent This method allows us to move the XPathNavigator object to the parent node of the
current node. We cannot call the MoveToParent method when the root node is the
current node because the root node does not have a parent node.

MoveToRoot This method allows us to move the XPathNavigator object to the root node.

MoveToId This method allows us to move the XPathNavigator object to the node that has an ID
attribute. You need to specify the ID of the node to which you want the
XPathNavigator to move.

The XPath expression needs to be compiled first using the Compile method to convert the string
representation to an XPathExpression object. Compiling allow us to cache the expression for improved
performance and it also allows for verification to ensure the expression is valid. Once the expression is compiled
we can pass in the compiled XPath expression object and use the Evaluate method. The Evaluate method takes
the XPath expression and executes the expression against the XML document. It returns a typed result. We can
use Evaluate to perform calculations. In the following example we have created an expression to calculate the
sum of all prices in an XML document using Evaluate to execute.

Listing 7-20. Demonstrates executing an XPath expression using Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.XPath;

namespace CSXMLXpath2
{
class Program
{
static void Main(string[] args)

276
The Complete Reference To Professional SOA with Visual Studio 2005

{
XmlDocument XPathDocument = new XmlDocument();
XPathDocument.Load("cd_catalog.xml");
XPathNavigator navigator =
XPathDocument.CreateNavigator();
XPathExpression XPathExpr =
navigator.Compile("sum(//PRICE/text())");
Console.WriteLine(navigator.Evaluate(XPathExpr));
Console.ReadLine();
}
}
}

Listing 7-21. Demonstrates executing an XPath expression using Visual Basic .NET

Imports System.Xml
Imports System.Xml.XPath

Module Module1

Sub Main()
Dim XPathDocument As XmlDocument = New XmlDocument
XPathDocument.Load("cd_catalog.xml")
Dim navigator As XPathNavigator =
XPathDocument.CreateNavigator
Dim XPathExpr As XPathExpression =
navigator.Compile("sum(//PRICE/text())")
Console.WriteLine(navigator.Evaluate(XPathExpr))
Console.ReadLine()
End Sub

End Module
In listing 7-20 and listing 7-21 we load the cd catalog xml document into XPathDocument. We then ask it to
calculate the sum of all prices for the XML Document by compiling and evaluating through the query
sum(//PRICE/text()).

Figure 7-3. Result from the evaluated XML document

XML Schema XSD


In Chapter 5 we had examined XML Schemas. In this section we will read and write XML Schemas using .NET.
A XML Schema is an XML file that is used to define the content and grammar of a XML file. The schema
can then be used to validate the XML file. A file that complies to the requirements of its schema is called Valid.
Listing 7-22 demonstrates an example of XML Schema.

Listing 7-22. cd_catalog.xsd

277
The Complete Reference To Professional SOA with Visual Studio 2005

<?xml version="1.0" encoding="UTF-8" ?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="ARTIST">
<xs:complexType mixed="true" />
</xs:element>

<xs:element name="CATALOG">
<xs:complexType>
<xs:sequence>
<xs:element ref="CD" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>

<xs:element name="CD">
<xs:complexType>
<xs:sequence>
<xs:element ref="TITLE" />
<xs:element ref="ARTIST" />
<xs:element ref="COUNTRY" />
<xs:element ref="COMPANY" />
<xs:element ref="PRICE" />
<xs:element ref="YEAR" />
</xs:sequence>
</xs:complexType>
</xs:element>

<xs:element name="COMPANY">
<xs:complexType mixed="true" />
</xs:element>

<xs:element name="COUNTRY">
<xs:complexType mixed="true" />
</xs:element>

<xs:element name="PRICE">
<xs:complexType mixed="true" />
</xs:element>

<xs:element name="TITLE">
<xs:complexType mixed="true" />
</xs:element>

<xs:element name="YEAR">
<xs:complexType mixed="true" />
</xs:element>

</xs:schema>

We can also programmatically create schemas using the Schema Object Model (SOM). SOM part of the
System.Xml.Schema namespace consists of a set of classes that allow us to read and manipulate schema

278
The Complete Reference To Professional SOA with Visual Studio 2005

definitions. When we manipulate the schema, it resides in memory. We need to validate and compile the schema
before we can write it to a file.

Listing 7-23. Demonstrates creating a Schema programmtically using Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.IO;

namespace CSXMLXsd
{
class Program
{
static void Main(string[] args)
{
try
{
XmlTextReader reader =
new XmlTextReader("cd_catalog.xsd");
XmlSchema myschema = XmlSchema.Read(reader, null);
myschema.Write(Console.Out);
Console.WriteLine("Press <Enter> to exit.");
Console.Read();
FileStream file = new FileStream("New.xsd",
FileMode.Create, FileAccess.ReadWrite);
XmlTextWriter xwriter = new XmlTextWriter(file,
new UTF8Encoding());
xwriter.Formatting = Formatting.Indented;
myschema.Write(xwriter);
}
catch (Exception e)
{
Console.WriteLine(e);
}

}
}
}

Listing 7-24. Demonstrates creating a Schema programmtically using Visual Basic .NET

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Xml
Imports System.Xml.Schema
Imports System.IO

Module Module1

Sub Main()

279
The Complete Reference To Professional SOA with Visual Studio 2005

Try
Dim reader As XmlTextReader =
New XmlTextReader("cd_catalog.xsd")
Dim myschema As XmlSchema =
XmlSchema.Read(reader, Nothing)
myschema.Write(Console.Out)
Console.WriteLine("Press <Enter> to exit.")
Console.Read()
Dim file As FileStream = _
New FileStream("New.xsd",
FileMode.Create, FileAccess.ReadWrite)
Dim xwriter As XmlTextWriter =
New XmlTextWriter(file, New UTF8Encoding)
xwriter.Formatting = Formatting.Indented
myschema.Write(xwriter)
Catch e As Exception
Console.WriteLine(e)
End Try

End Sub

End Module

XML Validation
We can ensure that the XML documents that we create are well formed. Any XML parser can read a well-
formed XML document. We should also ensure that the XML document matches its schema or conforms to the
constraints defined by its DTD. For example, if we specify a specific data type or a specific range for a record
then we need to ensure that the XML document must conform to the condition or it will be considered invalid.
We can ensure the validity of a XML document by using the XmlValidatingReader class. The
XmlValidatingReader class is a derived class of the XmlReader class and adds validation support to the
XmlTextReader class. The XmlValidatingReader class provides the DTD, XML-Data Reduced (XDR), and XSD
schema validation services that allow us to validate an XML document or a fragment of an XML document. The
XmlValidatingReader class takes XmlTextReader as the input and applies the properties that we specify in the
XmlTextReader class.

Listing 7-25. Reading an XML document using XmlReader using Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Schema;

namespace CSXMLValidate
{
class Program
{
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create("cd_catalog.xml");

280
The Complete Reference To Professional SOA with Visual Studio 2005

// Parse the file.


while (reader.Read()) ;
Console.ReadLine();
}
}
}

Listing 7-26. Reading an XML document using XmlReader using Visual Basic .NET

Imports System.Xml
Module Module1

Sub Main()
Dim reader As XmlReader = XmlReader.Create("cd_catalog.xml")
While reader.Read
End While
Console.ReadLine()
End Sub

End Module

In the above code we read in the cd_catalog.xml file using the XmlReader class. In the below example we
will be using XmlSchemaSet to validate our CD catalog against an invalid Xml cd catalog document.
First we will create an invalid Xml CD catalog document by injecting a SubTitle element into the document.

Listing 7-27. cd_catalog_fail.xml which causes the validation to fail

<?xml version="1.0" encoding="ISO-8859-1"?>


<CATALOG xmlns="urn:cd_Catalog-schema">
<CD>
<TITLE>
<SubTitle>This title should throw an error</SubTitle>
</TITLE>
<ARTIST>Bob Dylan</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>Columbia</COMPANY>
<PRICE>10.90</PRICE>
<YEAR>1985</YEAR>
</CD>
<CD>
<TITLE>Hide your heart</TITLE>
<ARTIST>Bonnie Tyler</ARTIST>
<COUNTRY>UK</COUNTRY>
<COMPANY>CBS Records</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1988</YEAR>
</CD>
<CD>
<TITLE>Greatest Hits</TITLE>
<ARTIST>Dolly Parton</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>RCA</COMPANY>
<PRICE>9.90</PRICE>

281
The Complete Reference To Professional SOA with Visual Studio 2005

<YEAR>1982</YEAR>
</CD>
</CATALOG>

In our CD catalog schema file we have not catered for this new SubTitle element as a result it will fail the
validation.

Listing 7-28. cd_catalog.xsd schema file for the cd_catalog Xml documents

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="ARTIST">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="CATALOG">
<xs:complexType>
<xs:sequence>
<xs:element ref="CD" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="CD">
<xs:complexType>
<xs:sequence>
<xs:element ref="TITLE" maxOccurs="1" />
<xs:element ref="ARTIST" minOccurs="1" />
<xs:element ref="COUNTRY" />
<xs:element ref="COMPANY" />
<xs:element ref="PRICE" />
<xs:element ref="YEAR" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="COMPANY">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="COUNTRY">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="PRICE">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="TITLE" nillable="false">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="YEAR">
<xs:complexType mixed="true" />
</xs:element>
</xs:schema>

Listing 7-29. Validating the XML document against the Schema using Visual C#

using System;
using System.Collections.Generic;

282
The Complete Reference To Professional SOA with Visual Studio 2005

using System.Text;
using System.Xml;
using System.Xml.Schema;

namespace CSXMLValidate2
{
class Program
{
static void Main(string[] args)
{
// Create the XmlSchemaSet class.
XmlSchemaSet sc = new XmlSchemaSet();

// Add the schema to the collection.


sc.Add("urn:cd_Catalog-schema", "cd_catalog.xsd");

// Set the validation settings.


XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.Schemas = sc;
settings.ValidationEventHandler +=
new ValidationEventHandler(ValidationCallBack);

// Create the XmlReader object.


XmlReader reader = XmlReader.Create("cd_catalog_fail.xml", settings);

// Parse the file.


while (reader.Read()) ;
Console.WriteLine("__________________");
Console.WriteLine("Parse complete!");
Console.ReadLine();
}

// Display any warnings or errors.


private static void ValidationCallBack
(object sender, ValidationEventArgs args)
{
if (args.Severity == XmlSeverityType.Warning)
Console.WriteLine("\tWarning: Matching schema not found." +
" No validation occurred." + args.Message);
else
Console.WriteLine("\tValidation error: " + args.Message);

}
}

Listing 7-30. Validating the XML document against the Schema using Visual Basic .NET

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Xml

283
The Complete Reference To Professional SOA with Visual Studio 2005

Imports System.Xml.Schema
Module Module1

Sub Main()
Dim sc As XmlSchemaSet = New XmlSchemaSet
sc.Add("urn:cd_Catalog-schema", "cd_catalog.xsd")
Dim settings As XmlReaderSettings = New XmlReaderSettings
settings.ValidationType = ValidationType.Schema
settings.Schemas = sc
AddHandler settings.ValidationEventHandler, AddressOf ValidationCallBack
Dim reader As XmlReader = XmlReader.Create("cd_catalog_fail.xml", settings)
While reader.Read

End While
Console.WriteLine("__________________")
Console.WriteLine("Parse complete!")
Console.ReadLine()

End Sub

Private Sub ValidationCallBack(ByVal sender As Object, _


ByVal args As ValidationEventArgs)
If args.Severity = XmlSeverityType.Warning Then
Console.WriteLine("Warning: Matching schema not found." + _
" No validation occurred." + args.Message)
Else
Console.WriteLine("Validation error: " + args.Message)
End If
End Sub

End Module

Note: In the listing above an error will be thrown. This is because that the XML file cannot be validated against the schema.

After we load the Xml schema using XmlSchemaSet’s Add function where we specify the namespace and
the xsd document, we use the ValidationType property to specify the type of validations that we want to perform
on that document. The default value of ValidationType is Auto. The other values for this property can be DTD,
Schema, XDR, and None.

XML and DataSet


In Chapter 6 we learned about ADO.NET DataSets. They’re an important part of ADO.NET and is a vital part of
.NET development. A DataSet stores data that is obtained from a data source. This data source can be any source,
such as a relational database or an XML document. A DataSet can either be typed or untyped. A typed DataSet is
a class that is derived from a DataSet class and has an associated XML Schema. On the other hand, an untyped
DataSet does not have an XML Schema associated with it.

Table 7-7. A DataSet has the following XML related methods.

284
The Complete Reference To Professional SOA with Visual Studio 2005

Method Description

GetXml This method allows us to retrieve the XML representation of the data stored in a
DataSet in a string variable.
This method allows us to retrieve the XSD schema for the XML representation of
GetXmlSchema
the data stored in the DataSet.

InferXmlSchema This method allows us to extrapolate the structure of data in the DataSet by using
the schema provided in the TextReader, XMLReader, or Stream object.

ReadXml This method reads the XML data and schema into the DataSet.

ReadXmlSchema This method allows us to read XML Schema into the DataSet.

WriteXml This method allows us to write the data of the DataSet into an XML file.

WriteXmlSchema This method allows us to write the data in the DataSet into an XML Schema.

In ADO.NET we have the option to save a DataSet as a XML file and also save its XML schema to a file.
While vice-versa we can also read an XML schema back into a DataSet and load XML file as data into the
DataSet.
To save the content of the DataSet into an XML document we use the WriteXml() method. While to save its
schema we would use the WriteXmlSchema() method.

NOTE: The connectionstring used in each of these examples may vary depending on your Sql Server Database setup.

Listing 7-31. Writing the data and schema to XML files using Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace csDataSet
{
class Program
{
static void Main(string[] args)
{
SqlConnection sqlcon = new SqlConnection(
"Data Source=DEVSERVER\\;Initial Catalog=AdventureWorks;"+
"Integrated Security=True");

285
The Complete Reference To Professional SOA with Visual Studio 2005

sqlcon.Open();
SqlDataAdapter sqladapter = new SqlDataAdapter(
"select * from HumanResources.Employee",
sqlcon);
DataSet employeeDS = new DataSet();
sqladapter.Fill(employeeDS, "EmployeeTable");
int rowcnt = employeeDS.Tables["EmployeeTable"].Rows.Count;
employeeDS.WriteXml("EmployeeTable.xml");
employeeDS.WriteXmlSchema("EmployeeTableSchema.xml");
Console.WriteLine(rowcnt.ToString());
Console.ReadLine();
sqlcon.Close();

}
}
}

Listing 7-32. Writing the data and schema to XML files using Visual Basic .NET

Imports System.Data
Imports System.Data.SqlClient
Module Module1

Sub Main()
Dim sqlcon As SqlConnection = New SqlConnection( _
"Data Source=DEVSERVER\;Initial Catalog=AdventureWorks;" + _
"Integrated Security=True")
sqlcon.Open()
Dim sqladapter As SqlDataAdapter = New SqlDataAdapter( _
"select * from HumanResources.Employee", sqlcon)
Dim employeeDS As DataSet = New DataSet
sqladapter.Fill(employeeDS, "EmployeeTable")
Dim rowcnt As Integer = _
employeeDS.Tables("EmployeeTable").Rows.Count
employeeDS.WriteXml("EmployeeTable.xml")
employeeDS.WriteXmlSchema("EmployeeTableSchema.xml")
Console.WriteLine(rowcnt.ToString)
Console.ReadLine()
sqlcon.Close()
End Sub

End Module

In the listing above we first retrieve the data from the Employee table then will use Fill to enter the data into
the dataset. Once the DataSet is filled we can write out the data contained in the DataSet into the XML document
using the WriteXml() method, we can then write out the Schema using WriteXmlSchema().

Listing 7-33. This is the EmployeeTable.xml document that was created.

<?xml version="1.0" standalone="yes"?>


<NewDataSet>
<EmployeeTable>
<EmployeeID>1</EmployeeID>

286
The Complete Reference To Professional SOA with Visual Studio 2005

<NationalIDNumber>14417807</NationalIDNumber>
<ContactID>1209</ContactID>
<LoginID>adventure-works\guy1</LoginID>
<ManagerID>16</ManagerID>
<Title>Production Technician - WC60</Title>
<BirthDate>1972-05-15T00:00:00+10:00</BirthDate>
<MaritalStatus>M</MaritalStatus>
<Gender>M</Gender>
<HireDate>1996-07-31T00:00:00+10:00</HireDate>
<SalariedFlag>false</SalariedFlag>
<VacationHours>21</VacationHours>
<SickLeaveHours>30</SickLeaveHours>
<CurrentFlag>true</CurrentFlag>
<rowguid>aae1d04a-c237-4974-b4d5-935247737718</rowguid>
<ModifiedDate>2004-07-31T00:00:00+10:00</ModifiedDate>
</EmployeeTable>
.
.
.
</NewDataSet>

Listing 7-34. The EmployeeTableSchema.xml document that was created

<?xml version="1.0" standalone="yes"?>


<xs:schema id="NewDataSet" xmlns=""
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet"
msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="EmployeeTable">
<xs:complexType>
<xs:sequence>
<xs:element name="EmployeeID" type="xs:int" minOccurs="0" />
<xs:element name="NationalIDNumber" type="xs:string" minOccurs="0" />
<xs:element name="ContactID" type="xs:int" minOccurs="0" />
<xs:element name="LoginID" type="xs:string" minOccurs="0" />
<xs:element name="ManagerID" type="xs:int" minOccurs="0" />
<xs:element name="Title" type="xs:string" minOccurs="0" />
<xs:element name="BirthDate" type="xs:dateTime" minOccurs="0" />
<xs:element name="MaritalStatus" type="xs:string" minOccurs="0" />
<xs:element name="Gender" type="xs:string" minOccurs="0" />
<xs:element name="HireDate" type="xs:dateTime" minOccurs="0" />
<xs:element name="SalariedFlag" type="xs:boolean" minOccurs="0" />
<xs:element name="VacationHours" type="xs:short" minOccurs="0" />
<xs:element name="SickLeaveHours" type="xs:short" minOccurs="0" />
<xs:element name="CurrentFlag" type="xs:boolean" minOccurs="0" />
<xs:element name="rowguid"
msdata:DataType="System.Guid, mscorlib,
Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089"
type="xs:string" minOccurs="0" />

287
The Complete Reference To Professional SOA with Visual Studio 2005

<xs:element name="ModifiedDate" type="xs:dateTime" minOccurs="0" />


</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>

Similarly we can write the XML data representation of the DataSet directly into a string.

Listing 7-35. Writing the XML representation of DataSet into a string using Visual C#

String XmlData;
XmlData = employeeDS.GetXml();

Listing 7-36. Writing the XML representation of DataSet into a string using Visual Basic .NET

Dim XmlData As String


XmlData = employeeDS.GetXml()

We can also read the data back into the DataSet by using ReadXml() method. The schema can also be read
back using ReadXmlSchema().

Listing 7-37. Reading the the schema and the XML document containing data back into the DataSet using Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace CSDataSetRead
{
class Program
{
static void Main(string[] args)
{
DataSet employeeDS = new DataSet();
employeeDS.ReadXmlSchema("EmployeeTableSchema.xml");
employeeDS.ReadXml("EmployeeTable.xml");
int rowcnt = employeeDS.Tables["EmployeeTable"].Rows.Count;
Console.WriteLine(rowcnt.ToString());
Console.ReadLine();
}
}
}

Listing 7-38. Reading the the schema and the XML document containing data back into the DataSet using Visual Basic .NET

Imports System.Data
Imports System.Data.SqlClient

288
The Complete Reference To Professional SOA with Visual Studio 2005

Module Module1

Sub Main()
Dim employeeDS As DataSet = New DataSet
employeeDS.ReadXmlSchema("EmployeeTableSchema.xml")
employeeDS.ReadXml("EmployeeTable.xml")
Dim rowcnt As Integer = _
employeeDS.Tables("EmployeeTable").Rows.Count
Console.WriteLine(rowcnt.ToString)
Console.ReadLine()
End Sub

End Module

Summary
In this chapter we have examined how to access and manipulate XML document using .NET. As all modern
systems today can understand and work with XML document it is therefore important part of our development
towards an interoperable architecture.
We have looked XML DOM. XML DOM is a representation of the XML document in memory. The DOM
class allows us to read and write, and manipulate an XML document. The DOM class contains a set of libraries
which allow us to navigate through the XML document to the relevant information.
We have also learnt to write an XML Parser in .NET using XmlDocument. We have looked at Reading and
Writing XML using XmlTextReader and XmlTextWriter. Both classes provide fast access to XML data.
XmlTextReader class should be used when we don’t need to read the entire document into memory. While the
XmlTextWriter a derived class of XmlWriter, allows us to create XML streams and write data to well-formed
XML documents.
We have also examine utilizing XPath queries in our XML documents. In our XML document we can use
XPath to access a particular node. We can also perform XPath queries on an XML document within .NET.
We have looked at validating an XML document through using a XML Schema. This ensures that the XML
document conforms to its schema.
Lastly we looked at the XML options that the ADO.NET DataSet provided which allowed us to save a
DataSet and its schema as XML. Vice versa we could also read the XML schema and the XML document back
into the DataSet.

289
The Complete Reference To Professional SOA with Visual Studio 2005

Chapter 8 .NET XML


Serialization
Serialization is a process through which an object's state is transformed into some serial data format, such as a
XML or a binary format, so that it can be sent over the Internet or be stored in a file so that it can be retrieved at
a later date. In XML Web services serialization plays a vital part of interoperability between services. It allows
information to be converted into a transportable format.
The .NET Framework uses XML serialization extensively to facilitate communication between two XML
Web services. The .NET XML serialization model is responsible for serializing and deserializing XML instances
of .NET types to and from XML. XML serialization is also responsible for serializing .NET type definitions to
XML schemas and deserializing XML schemas to .NET type definitions.
In this chapter we will be looking at serialization using Binary and Soap formatters as well as XML
serialization and customizing serialization handling in .NET.

.NET Serialization
.NET serialization performs a key role in facilitating communication in the .NET Remoting and .NET XML Web
services infrastructure. The serialization process reduces objects into a transportable representation that can be
sent across the wire or stored on disk.

Enable Serialization using Attributes


In .NET not all objects are serializable. The simplest way to support serialization is to include our class with a
Serializable attribute. In listing 8-1 and listing 8-2 we have included our class with a Serializable attribute. This
allows the class to be serialized.

Listing 8-1. Enabling serializable for SerializableClass using Visual C#

[Serializable]
public class SerializableClass
{
private string _name;

public string Name


{
get { return _name; }
set { _name = value; }
}

private string zipCode;

public string ZipCode


{
get { return _zipCode; }

290
The Complete Reference To Professional SOA with Visual Studio 2005

set { _zipCode = value; }


}

Listing 8-2. Enabling serializable for SerializableClass using Visual Basic .NET

<Serializable()> _
Public Class SerializableClass
Private _name As String

Public Property Name() As String


Get
Return _name
End Get
Set
_name = value
End Set
End Property
Private _zipCode As Integer

Public Property ZipCode() As String


Get
Return _zipCode
End Get
Set
_zipCode = value
End Set
End Property
End Class

By default, all members of a class that is marked as Serializable can be serialized. However we can also
restrict this behavior by attaching NonSerialized attribute to certain fields. For example we could specify not to
serialize ZipCode’s value in which case we would add the attribute in front of the zipCode field . See Listing 8-3
and Listing 8-4 below.

Listing 8-3. disable serialization for ZipCode using NonSerialized attribute in Visual C#

[NonSerialized()]
private string _zipCode;

public string ZipCode


{
get { return _zipCode; }
set { _zipCode = value; }
}

Listing 8-4. disable serialization for ZipCode using NonSerialized attribute in Visual Basic .NET

<NonSerialized()> Private _zipCode As Integer

Public Property ZipCode() As String


Get

291
The Complete Reference To Professional SOA with Visual Studio 2005

Return _zipCode
End Get
Set(ByVal value As String)
_zipCode = value
End Set
End Property

Serialization Formatter
.NET offers us two forms of serialization, Binary and SOAP. Binary, form of serialization is more compact
and provides as an excellent model performance wise. The SOAP format allows us to serialize data into a
readable form. This is achieved through the use of a formatter. The formatter helps to determine the serialized
format for the objects that we serialize.
To serialize into a Binary format we need to use the .NET BinaryFormatter class which is a part of the
System.Runtime.Serialization.Formatters.Binary namespace. The BinaryFormatter provides ability to encode
objects into a compact binary format. We need to provide a stream containing the objects to serialize to the
BinaryFormatter see listing 8-5 and listing 8-6 below.

Listing 8-5. Serializing objects to file using Binary formatter in Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace CSBinarySerialization
{
[Serializable]
public class SerializableClass
{
private string _name;

public string Name


{
get { return _name; }
set { _name = value; }
}

private int _zipCode;


public int ZipCode
{
get { return _zipCode; }
set { _zipCode = value; }
}

class Program
{
static void Main(string[] args)
{

292
The Complete Reference To Professional SOA with Visual Studio 2005

SerializableClass sc = new SerializableClass();


sc.Name = "John Doe";
sc.ZipCode = 2000;
SerializeToFile(sc, "SerializedObj.bin");
//read the object back from file
SerializableClass deserializedobj =
DeserializeFromFile("SerializedObj.bin");
Console.WriteLine("Name: " + deserializedobj.Name);
Console.WriteLine("ZipCode: " + deserializedobj.ZipCode);
Console.ReadLine();
}

public static void SerializeToFile(SerializableClass obj,


String filename)
{
Stream str = File.OpenWrite(filename);
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(str, obj);
str.Close();
}

public static SerializableClass DeserializeFromFile(String filename)


{
Stream reader = File.OpenRead(filename);
BinaryFormatter formatter = new BinaryFormatter();
SerializableClass obj =
(SerializableClass)formatter.Deserialize(reader);
reader.Close();
return obj;
}
}
}

Listing 8-6. Serializing objects to file using Binary formatter in Visual Basic .NET

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.IO
Namespace VBBinarySerialization

<Serializable()> _
Public Class SerializableClass
Private _name As String

Public Property Name() As String


Get
Return _name
End Get
Set(ByVal value As String)
_name = value
End Set
End Property

293
The Complete Reference To Professional SOA with Visual Studio 2005

Private _zipCode As Integer

Public Property ZipCode() As Integer


Get
Return _zipCode
End Get
Set(ByVal value As Integer)
_zipCode = value
End Set
End Property
End Class

Class Program

Shared Sub Main(ByVal args As String())


Dim sc As SerializableClass = New SerializableClass
sc.Name = "John Doe"
sc.ZipCode = 2000
SerializeToFile(sc, "SerializedObj.bin")
Dim deserializedobj As SerializableClass = _
DeserializeFromFile("SerializedObj.bin")
Console.WriteLine("Name: " + deserializedobj.Name)
Console.WriteLine("ZipCode: " + _
deserializedobj.ZipCode.ToString())
Console.ReadLine()
End Sub

Public Shared Sub SerializeToFile(ByVal obj As SerializableClass, _


ByVal filename As String)
Dim str As Stream = File.OpenWrite(filename)
Dim formatter As BinaryFormatter = New BinaryFormatter
formatter.Serialize(str, obj)
str.Close()
End Sub

Public Shared Function DeserializeFromFile(ByVal filename As String) _


As SerializableClass
Dim reader As Stream = File.OpenRead(filename)
Dim formatter As BinaryFormatter = New BinaryFormatter
Dim obj As SerializableClass = _
CType(formatter.Deserialize(reader), SerializableClass)
reader.Close()
Return obj
End Function

End Class
End Namespace
In the above example we have created a SerializableClass which includes the Serializable attribute. This
allows the class to be serialized. We then set values for the SerializableClass object which we then pass to the
BinaryFormatter as well as an open stream to a file which we will be writing the result to. Using the Serialize
method the BinaryFormatter then saves the values into the file SerializedObj.bin.

294
The Complete Reference To Professional SOA with Visual Studio 2005

To deserialize the SerializeObj.bin file we use the deserialize method from the BinaryFormatter object.
After the object has been deserialized we need to cast the object back to a particular type before we can access its
value.
The result from the deserialization can be seen in the image figure 8-1 below.

Figure 8-1. Deserialized object

If we open the file in Visual Studio’s binary editor we can see that the information that we had assigned to
the object has been serialized to a binary format. See figure 8-2 below.

Figure 8-2. SerializedObj.bin

To serialize using the SOAP formatter we need to use the .NET SoapFormatter class which is a part of the
System.Runtime.Serialization.Formatters.Soap Namespace. The SoapFormatter allows objects to be serialized
using the SOAP protocol into a ascii format that can be transferred over the web. Using the SoapFormatter class
is similar to the BinaryFormatter class see listing 8-7 and listing 8-8 below.

Tip: To use SOAP formatter we will need to add reference to SOAP formatter we can do this by selecting the References node in the
Solution Explorer right click and select “Add Reference”. Then under the .NET tab browse to the
System.Runtime.Serialization.Formatters.Soap component.

Listing 8-7. Implementing SoapFormatter in Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Soap;

295
The Complete Reference To Professional SOA with Visual Studio 2005

namespace CSSOAPFormatter
{
[Serializable]
public class SerializableClass
{
private string _name;

public string Name


{
get { return _name; }
set { _name = value; }
}

private int _zipCode;


public int ZipCode
{
get { return _zipCode; }
set { _zipCode = value; }
}

class Program
{
static void Main(string[] args)
{
SerializableClass sc = new SerializableClass();
sc.Name = "John Doe";
sc.ZipCode = 2000;
SerializeToFile(sc, "SerializedObj.soap");
//read the object back from file
SerializableClass deserializedobj =
DeserializeFromFile("SerializedObj.soap");
Console.WriteLine("Name: " + deserializedobj.Name);
Console.WriteLine("ZipCode: " + deserializedobj.ZipCode);
Console.ReadLine();

public static void SerializeToFile(SerializableClass obj,


String filename)
{
Stream str = File.OpenWrite(filename);
SoapFormatter formatter = new SoapFormatter();
formatter.Serialize(str, obj);
str.Close();
}

public static SerializableClass DeserializeFromFile(String filename)


{
Stream reader = File.OpenRead(filename);
SoapFormatter formatter = new SoapFormatter();

296
The Complete Reference To Professional SOA with Visual Studio 2005

SerializableClass obj =
(SerializableClass)formatter.Deserialize(reader);
reader.Close();
return obj;
}
}
}

Listing 8-8. Implementing SoapFormatter in Visual Basic .NET

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.IO
Imports System.Runtime.Serialization.Formatters.Soap
Namespace VBSOAPFormatter

<Serializable()> _
Public Class SerializableClass
Private _name As String

Public Property Name() As String


Get
Return _name
End Get
Set(ByVal value As String)
_name = value
End Set
End Property
Private _zipCode As Integer

Public Property ZipCode() As Integer


Get
Return _zipCode
End Get
Set(ByVal value As Integer)
_zipCode = value
End Set
End Property
End Class

Class Program

Shared Sub Main(ByVal args As String())


Dim sc As SerializableClass = New SerializableClass
sc.Name = "John Doe"
sc.ZipCode = 2000
SerializeToFile(sc, "SerializedObj.soap")
Dim deserializedobj As SerializableClass = _
DeserializeFromFile("SerializedObj.soap")
Console.WriteLine("Name: " + deserializedobj.Name)
Console.WriteLine("ZipCode: " + _
deserializedobj.ZipCode.ToString())
Console.ReadLine()

297
The Complete Reference To Professional SOA with Visual Studio 2005

End Sub

Public Shared Sub SerializeToFile(ByVal obj As SerializableClass, _


ByVal filename As String)
Dim str As Stream = File.OpenWrite(filename)
Dim formatter As SoapFormatter = New SoapFormatter
formatter.Serialize(str, obj)
str.Close()
End Sub

Public Shared Function DeserializeFromFile(ByVal filename As String) _


As SerializableClass
Dim reader As Stream = File.OpenRead(filename)
Dim formatter As SoapFormatter = New SoapFormatter
Dim obj As SerializableClass = _
CType(formatter.Deserialize(reader), SerializableClass)
reader.Close()
Return obj
End Function
End Class
End Namespace
Using SOAP formatter is very similar to using the Binary formatter. In the above example we have created a
SerializableClass which is decorated with a Serializable attribute. This allows the class to be serialized. We then
set values for the SerializableClass object. We then pass this object to the SoapFormatter as well as an open stream
to a file which we will be writing the result to. The SoapFormatter the saves the values into the file
SerializedObj.soap.
To serialize we use the Serialize method from the SoapFormatter object. To deserialize we use the
Deserialize method from the SoapFormatter object.

Listing 8-9. SerializedObj.soap

<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<a1:SerializableClass id="ref-1"
xmlns:a1="http://schemas.microsoft.com/clr/nsassem/VBSOAPFormatter
.VBSOAPFormatter/VBSOAPFormatter%2C%20Version%3D1.0.0.0%2C%20Culture%3
Dneutral%2C%20PublicKeyToken%3Dnull">
<_name id="ref-3">John Doe</_name>
<_zipCode>2000</_zipCode>
</a1:SerializableClass>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

In the listing above we can see that the SerializedObj.soap contains the serialized values of the object in a
SOAP format.

298
The Complete Reference To Professional SOA with Visual Studio 2005

XML Serialization
In the previous section we have examined how to serialize objects into binary files and soap files. There is also
another means of serialization which translates serializable objects into XML files. The ASP.NET XML Web
service relies on XML serialization heavily to serialize instances of .NET types to XML and then deserialize
them from XML back to instances of .NET types. Through XML serialization applications can interoperate with
one another.
To serialize objects into XML document we need to use the XMLSerializer class from the
System.Xml.Serialization namespace. In the following example we have serialized the SerializableClass to XML.

Listing 8-10. Implementing XmlSerializer using Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.IO;

namespace CSXMLSerialize
{
public class SerializableClass
{
private string _name;

public string Name


{
get { return _name; }
set { _name = value; }
}

private int _zipCode;


public int ZipCode
{
get { return _zipCode; }
set { _zipCode = value; }
}

class Program
{
static void Main(string[] args)
{
SerializableClass sc = new SerializableClass();
sc.Name = "John Doe";
sc.ZipCode = 2000;
//serialize the object to file
SerializeToFile(sc, "SerializedObj.xml");

//read the object back from file


SerializableClass deserializedobj =
DeserializeFromFile("SerializedObj.xml");
Console.WriteLine("Name: " + deserializedobj.Name);

299
The Complete Reference To Professional SOA with Visual Studio 2005

Console.WriteLine("ZipCode: " + deserializedobj.ZipCode);


Console.ReadLine();

public static void SerializeToFile(SerializableClass obj,


String filename)
{
Stream str = File.OpenWrite(filename);
XmlSerializer xmlserial = new XmlSerializer
(typeof(SerializableClass));
xmlserial.Serialize(str, obj);
str.Close();
}

public static SerializableClass DeserializeFromFile(string filename)


{
TextReader reader = new StreamReader(filename);
XmlSerializer xmlserial = new XmlSerializer
(typeof(SerializableClass));
SerializableClass obj =
(SerializableClass)xmlserial.Deserialize(reader);
reader.Close();
return obj;
}
}
}

Listing 8-11. Implementing XmlSerializer using Visual Basic .NET

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Xml.Serialization
Imports System.IO
Namespace VBXMLSerialize

Public Class SerializableClass


Private _name As String

Public Property Name() As String


Get
Return _name
End Get
Set(ByVal value As String)
_name = value
End Set
End Property
Private _zipCode As Integer

Public Property ZipCode() As Integer


Get
Return _zipCode
End Get

300
The Complete Reference To Professional SOA with Visual Studio 2005

Set(ByVal value As Integer)


_zipCode = value
End Set
End Property
End Class

Class Program

Shared Sub Main(ByVal args As String())


Dim sc As SerializableClass = New SerializableClass
sc.Name = "John Doe"
sc.ZipCode = 2000
'serialize to file
SerializeToFile(sc, "SerializedObj.xml")
'deserialize from file
Dim deserializedobj As SerializableClass = _
DeserializeFromFile("SerializedObj.xml")
Console.WriteLine("Name: " + deserializedobj.Name)
Console.WriteLine("ZipCode: " + _
deserializedobj.ZipCode.ToString())
Console.ReadLine()
End Sub

Public Shared Sub SerializeToFile(ByVal obj As SerializableClass, _


ByVal filename As String)
Dim str As Stream = File.OpenWrite(filename)
Dim xmlserial As XmlSerializer = _
New XmlSerializer(GetType(SerializableClass))
xmlserial.Serialize(str, obj)
str.Close()
End Sub

Public Shared Function DeserializeFromFile(ByVal filename As String) _


As SerializableClass
Dim reader As TextReader = New StreamReader(filename)
Dim xmlserial As XmlSerializer = New XmlSerializer _
(GetType(SerializableClass))
Dim obj As SerializableClass = _
CType(xmlserial.Deserialize(reader), SerializableClass)
reader.Close()
Return obj
End Function
End Class
End Namespace
Serializing using XmlSerializer is similar to using Binary and SOAP formatter. To serialize use the Serialize
method from the XmlSerializer object and to deserialize use the Deserialize method from XmlSeializer object.
The result of the XML serialization is that the objects are saved to a XML file see listing 8-12. As we can see the
objects are serialized to a format that corresponds to the structure of the object.

Listing 8-12. Representation of the SerializableClass in SerializedObj.xml

<?xml version="1.0"?>
<SerializableClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

301
The Complete Reference To Professional SOA with Visual Studio 2005

xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>John Doe</Name>
<ZipCode>2000</ZipCode>
</SerializableClass>

Controlling Serialization
Serialization is automatic. We don’t need to implement anything in code for serialization and deserialization to
occur. It is all taken care of by the .NET runtime. However, sometimes the default serialization and
deserialization process do not meet our requirements. In these instances we need to take control in order to
customize serialization to our needs.
.NET provides a mechanism for altering the way .NET types are serialized to XML. We can do this by using
the attributes defined in the System.Xml.Serialization namespace. See Table 8-1for commonly used attributes.

Table 8-1: lists attributes defined by the System.Xml.Serialization namespace

Name Description

XmlAnyAttribute Gets or sets the XmlAnyAttributeAttribute to override.

XmlAnyElements Gets the collection of XmlAnyElementAttribute objects to override.

XmlArray Gets or sets an object that specifies how the XmlSerializer serializes a public field or
read/write property that returns an array.

XmlArrayItems Gets or sets a collection of objects that specify how the XmlSerializer serializes items
inserted into an array returned by a public field or read/write property.

XmlAttribute Gets or sets an object that specifies how the XmlSerializer serializes a public field or public
read/write property as an XML attribute.

XmlChoiceIdentifier Gets or sets an object that allows you to distinguish between a set of choices.

XmlDefaultValue Gets or sets the default value of an XML element or attribute.

XmlElements Gets a collection of objects that specify how the XmlSerializer serializes a public field or
read/write property as an XML element.

XmlEnum Gets or sets an object that specifies how the XmlSerializer serializes an enumeration member.

XmlIgnore Gets or sets a value that specifies whether or not the XmlSerializer serializes a public field or
public read/write property.

Xmlns Gets or sets a value that specifies whether to keep all namespace declarations when an object
containing a member that returns an XmlSerializerNamespaces object is overridden.

XmlRoot Gets or sets an object that specifies how the XmlSerializer serializes a class as an XML root
element.

XmlText Gets or sets an object that instructs the XmlSerializer to serialize a public field or public
read/write property as XML text.

XmlType Gets or sets an object that specifies how the XmlSerializer serializes a class to which the
XmlTypeAttribute has been applied.

302
The Complete Reference To Professional SOA with Visual Studio 2005

XmlRoot and XmlElement


The first attribute that we need to specify is the XmlRoot attribute. The Root Attribute will represent the root
element within the body of the message. We can then use XmlElement attribute to define the elements in the
XML. Using serialization attributes we can define how the class is to be serialized and in fact change the
behavior of the serialization if required.
In the following example we will rename the attributes of Name and ZipCode in the SerializableClass
object. By controlling the serialization process we will change the name of each of the attribute of the XML file
generated see listing 8-13and listing 8-14.

Tip: We can use the word XmlElement in our code instead of the longer XmlElementAttribute.

Listing 8-13. Implementing XmlRoot and XmlElement attributes using Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.IO;

namespace CSXMLSerialize2
{

[XmlRoot("NewRootName",
Namespace="http://www.CustomNamespace.com",
IsNullable=true)]
public class SerializableClass
{
private string _name;
[XmlElement("NewElementName")]
public string Name
{
get { return _name; }
set { _name = value; }
}

private int _zipCode;


[XmlElement("NewElementZip")]
public int ZipCode
{
get { return _zipCode; }
set { _zipCode = value; }
}

class Program
{
static void Main(string[] args)
{

303
The Complete Reference To Professional SOA with Visual Studio 2005

SerializableClass sc = new SerializableClass();


sc.Name = "John Doe";
sc.ZipCode = 2000;
//serialize the object to file
SerializeToFile(sc, "SerializedObj.xml");

//read the object back from file


SerializableClass deserializedobj =
DeserializeFromFile("SerializedObj.xml");
Console.WriteLine("Name: " + deserializedobj.Name);
Console.WriteLine("ZipCode: " + deserializedobj.ZipCode);
Console.ReadLine();

public static void SerializeToFile(SerializableClass obj,


String filename)
{
Stream str = File.OpenWrite(filename);
XmlSerializer xmlserial = new XmlSerializer
(typeof(SerializableClass));
xmlserial.Serialize(str, obj);
str.Close();
}

public static SerializableClass DeserializeFromFile(string filename)


{
TextReader reader = new StreamReader(filename);
XmlSerializer xmlserial = new XmlSerializer
(typeof(SerializableClass));
SerializableClass obj =
(SerializableClass)xmlserial.Deserialize(reader);
reader.Close();
return obj;
}
}
}

Listing 8-14. Implementing XmlRoot and XmlElement attributes using Visual Basic .NET

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Xml.Serialization
Imports System.IO
Namespace VBXMLSerialize2

<XmlRoot("NewRootName", _
Namespace:="http://www.CustomNamespace.com", _
IsNullable:=True)> _
Public Class SerializableClass
Private _name As String

304
The Complete Reference To Professional SOA with Visual Studio 2005

<XmlElement("NewElementName")> _
Public Property Name() As String
Get
Return _name
End Get
Set(ByVal value As String)
_name = value
End Set
End Property
Private _zipCode As Integer

<XmlElement("NewElementZip")> _
Public Property ZipCode() As Integer
Get
Return _zipCode
End Get
Set(ByVal value As Integer)
_zipCode = value
End Set
End Property
End Class

Class Program

Shared Sub Main(ByVal args As String())


Dim sc As SerializableClass = New SerializableClass
sc.Name = "John Doe"
sc.ZipCode = 2000
SerializeToFile(sc, "SerializedObj.xml")
Dim deserializedobj As SerializableClass = _
DeserializeFromFile("SerializedObj.xml")
Console.WriteLine("Name: " + deserializedobj.Name)
Console.WriteLine("ZipCode: " + _
deserializedobj.ZipCode.ToString())
Console.ReadLine()
End Sub

Public Shared Sub SerializeToFile(ByVal obj As SerializableClass, _


ByVal filename As String)
Dim str As Stream = File.OpenWrite(filename)
Dim xmlserial As XmlSerializer = _
New XmlSerializer(GetType(SerializableClass))
xmlserial.Serialize(str, obj)
str.Close()
End Sub

Public Shared Function DeserializeFromFile(ByVal filename As String) _


As SerializableClass
Dim reader As TextReader = New StreamReader(filename)
Dim xmlserial As XmlSerializer = _
New XmlSerializer(GetType(SerializableClass))
Dim obj As SerializableClass = _

305
The Complete Reference To Professional SOA with Visual Studio 2005

CType(xmlserial.Deserialize(reader), SerializableClass)
reader.Close()
Return obj
End Function
End Class
End Namespace

The example creates a XML file that is shown in the listing 8-15 below.

Listing 8-15. The new SerializedObj.xml

<?xml version="1.0"?>
<NewRootName xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.CustomNamespace.com">
<NewElementName>John Doe</NewElementName>
<NewElementZip>2000</NewElementZip>
</NewRootName>

Compare this xml with the previous xml without using XmlRoot and XmlElement see listing 8-16 below.

Listing 8-16. The old SerializedObj.xml without using XmlRoot and XmlElement

<?xml version="1.0"?>
<SerializableClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>John Doe</Name>
<ZipCode>2000</ZipCode>
</SerializableClass>
As we can see there is a difference between the XML file generated. This is because using XmlRoot and
XmlElement we can control the way XML document is serialized. In the above example we have specified an
XmlRoot name NewRootName this changes the original name SerializableClass to NewRootName. Similarly
using XmlElement we have changed the element name of Name and ZipCode to NewElementName and
NewElementZip respectively.
One property to note is XmlRoot’s IsNullable attribute. Using this attribute we can specify whether the
XML serialization will allow null value. Table 8-2. below describes some of the possible properties of the
XmlRoot attribute.

Table 8-2: Describes the properties exposed by the XmlRootAttribute.

Name Description

DataType Gets or sets the XSD data type of the XML root element.

ElementName Gets or sets the name of the XML element that is generated and recognized by the XmlSerializer
class's Serialize and Deserialize methods, respectively.

IsNullable Gets or sets a value that indicates whether the XmlSerializer must serialize a member that is set
to a null reference (Nothing in Visual Basic) .

306
The Complete Reference To Professional SOA with Visual Studio 2005

Namespace Gets or sets the namespace for the XML root element.

TypeId When implemented in a derived class, gets a unique identifier for this Attribute.

The XmlElement attribute also exposes additional properties that we can use to control how a .NET type is
serialized to XML.

Table 8-3: properties of XmlElementAttribute.

Name Description

DataType Gets or sets the XML Schema definition (XSD) data type of the XML element generated by the
XmlSerializer.

ElementName Gets or sets the name of the generated XML element.

Form Gets or sets a value that indicates whether the element is qualified.

IsNullable Gets or sets a value that indicates whether the XmlSerializer must serialize a member that is set to
a null reference (Nothing in Visual Basic) as an empty tag with the xsi:nil attribute set to true.

Namespace Gets or sets the namespace assigned to the XML element that results when the class is serialized.

Order Gets or sets the explicit order in which the elements are serialized or deserialized.

Type Gets or sets the object type used to represent the XML element.

TypeId When implemented in a derived class, gets a unique identifier for this Attribute.

The XmlElementAttribute can be applied several times to a particular entity. This is useful when we need to
specify an array of objects. This will specify through the Type property different types of values that can be used
within the array. See listing 8-17 and listing 8-18 for an array that accepts both string and integer.

Listing 8-17. Multiple XmlElement using Visual C#


public class Things
{
[XmlElement(DataType = "string", Type = typeof(string)),
XmlElement(DataType = "int", Type = typeof(int))]
public object[] StringsAndInts;
}
Listing 8-18. Multiple XmlElement using Visual Basic .NET

Public Class Things


<Xml.Serialization.XmlElement(DataType:="string", _
Type:=GetType(String)), _
Xml.Serialization.XmlElement(DataType:="int", _
Type:=GetType(Integer))> _

307
The Complete Reference To Professional SOA with Visual Studio 2005

Public StringsAndInts As Object()


End Class

This results in XML with the following structure.

<Things>
<string>Hello</string>
<int>999</int>
<string>World</string>
</Things>

In the following example we will be applying an XmlElement attribute to an array, this instructs the
XmlSerializer to serialize the array as a series of XML elements, instead of a nested set of elements. The
example uses an a organization which contains a particular group located in a building. Each group contains a
manager and employees. See Listing 8-19 and listing 8-20.

Listing 8-19. Implementing XmlElement for array using Visual C#

using System;
using System.Collections;
using System.IO;
using System.Xml.Serialization;

public class Group


{
[XmlElement(
ElementName = "Members",
Namespace = "http://www.cpandl.com")]
public Employee[] Employees;

[XmlElement(DataType = "double",
ElementName = "Building")]
public double GroupID;

[XmlElement(DataType = "hexBinary")]
public byte [] HexBytes;

[XmlElement(DataType = "boolean")]
public bool IsActive;

[XmlElement(Type = typeof(Manager))]
public Employee Manager;

[XmlElement(typeof(int),
ElementName = "ObjectNumber"),
XmlElement(typeof(string),
ElementName = "ObjectString")]
public ArrayList ExtraInfo;
}

public class Employee


{
public string Name;

308
The Complete Reference To Professional SOA with Visual Studio 2005

public class Manager:Employee{


public int Level;
}

public class Run


{
public static void Main()
{
Run test = new Run();
test.SerializeObject("FirstDoc.xml");
test.DeserializeObject("FirstDoc.xml");
}

public void SerializeObject(string filename)


{
// Create the XmlSerializer.
XmlSerializer s = new XmlSerializer(typeof(Group));

// To write the file, a TextWriter is required.


TextWriter writer = new StreamWriter(filename);

/* Create an instance of the group to serialize, and set


its properties. */
Group group = new Group();
group.GroupID = 10.089f;
group.IsActive = false;

group.HexBytes = new byte[1]{Convert.ToByte(100)};

Employee x = new Employee();


Employee y = new Employee();

x.Name = "Jack";
y.Name = "Jill";

group.Employees = new Employee[2]{x,y};

Manager mgr = new Manager();


mgr.Name = "Sara";
mgr.Level = 4;
group.Manager = mgr;

/* Add a number and a string to the


ArrayList returned by the ExtraInfo property. */
group.ExtraInfo = new ArrayList();
group.ExtraInfo.Add(42);
group.ExtraInfo.Add("Answer");

// Serialize the object, and close the TextWriter.


s.Serialize(writer, group);

309
The Complete Reference To Professional SOA with Visual Studio 2005

writer.Close();
}

public void DeserializeObject(string filename)


{
FileStream fs = new FileStream(filename, FileMode.Open);
XmlSerializer x = new XmlSerializer(typeof(Group));
Group g = (Group) x.Deserialize(fs);
Console.WriteLine(g.Manager.Name);
Console.WriteLine(g.GroupID);
Console.WriteLine(g.HexBytes[0]);
foreach(Employee e in g.Employees)
{
Console.WriteLine(e.Name);
}
}
}

Listing 8-20. Implementing XmlElement for array using Visual Basic .NET

Imports System
Imports System.Collections
Imports System.IO
Imports System.Xml.Serialization

Public Class Group


' Set the element name and namespace of the XML element.
<XmlElement(ElementName := "Members", _
Namespace := "http://www.cpandl.com")> _
Public Employees() As Employee

<XmlElement(DataType := "double", _
ElementName := "Building")> _
Public GroupID As Double

<XmlElement(DataType := "hexBinary")> _
Public HexBytes() As Byte

<XmlElement(DataType := "boolean")> _
Public IsActive As Boolean

<XmlElement(GetType(Manager))> _
Public Manager As Employee

<XmlElement(GetType(Integer), _
ElementName := "ObjectNumber"), _
XmlElement(GetType(String), _
ElementName := "ObjectString")> _
Public ExtraInfo As ArrayList
End Class

Public Class Employee

310
The Complete Reference To Professional SOA with Visual Studio 2005

Public Name As String


End Class

Public Class Manager


Inherits Employee
Public Level As Integer
End Class

Public Class Run

Public Shared Sub Main()


Dim test As New Run()
test.SerializeObject("FirstDoc.xml")
test.DeserializeObject("FirstDoc.xml")
End Sub

Public Sub SerializeObject(filename As String)


' Create the XmlSerializer.
Dim s As New XmlSerializer(GetType(Group))

' To write the file, a TextWriter is required.


Dim writer As New StreamWriter(filename)

' Create an instance of the group to serialize, and set


' its properties.
Dim group As New Group()
group.GroupID = 10.089f
group.IsActive = False

group.HexBytes = New Byte() {Convert.ToByte(100)}

Dim x As New Employee()


Dim y As New Employee()

x.Name = "Jack"
y.Name = "Jill"

group.Employees = New Employee() {x, y}

Dim mgr As New Manager()


mgr.Name = "Sara"
mgr.Level = 4
group.Manager = mgr

' Add a number and a string to the


' ArrayList returned by the ExtraInfo property.
group.ExtraInfo = New ArrayList()
group.ExtraInfo.Add(42)
group.ExtraInfo.Add("Answer")

' Serialize the object, and close the TextWriter.


s.Serialize(writer, group)
writer.Close()

311
The Complete Reference To Professional SOA with Visual Studio 2005

End Sub

Public Sub DeserializeObject(filename As String)


Dim fs As New FileStream(filename, FileMode.Open)
Dim x As New XmlSerializer(GetType(Group))
Dim g As Group = CType(x.Deserialize(fs), Group)
Console.WriteLine(g.Manager.Name)
Console.WriteLine(g.GroupID)
Console.WriteLine(g.HexBytes(0))

Dim e As Employee
For Each e In g.Employees
Console.WriteLine(e.Name)
Next e
End Sub
End Class

The example above produces a FirstDoc.xml shown in listing 8-21.

Listing 8-21. FirstDoc.xml

<?xml version="1.0" encoding="utf-8"?>


<Group xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Members xmlns="http://www.serializationexample.com">
<Name>Jack</Name>
</Members>
<Members xmlns="http://www.serializationexample.com">
<Name>Jill</Name>
</Members>
<Building>10.088999748229981</Building>
<HexBytes>64</HexBytes>
<IsActive>false</IsActive>
<Manager>
<Name>Sara</Name>
<Level>4</Level>
</Manager>
<ObjectNumber>42</ObjectNumber>
<ObjectString>Answer</ObjectString>
</Group>

We can see that the result shows each element that was added to the ArrayList if the value is an integer it is
saved as ObjectNumber, if the value is a string it is saved as a ObjectString. Through the XmlElement definition
shown below.

Listing 8-22. Defining XmlElement for arraylist using Visual C#

[XmlElement(typeof(int),
ElementName = "ObjectNumber"),
XmlElement(typeof(string),
ElementName = "ObjectString")]
public ArrayList ExtraInfo;

312
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 8-23. Defining XmlElement for arraylist using Visual Basic .NET

<XmlElement(GetType(Integer), _
ElementName := "ObjectNumber"), _
XmlElement(GetType(String), _
ElementName := "ObjectString")> _
Public ExtraInfo As ArrayList

Ignoring Elements
During serialization if we wanted to we can exclude certain entities from serialization by using the
XmlIgnore attribute.

Listing 8-24. XmlIgnore attribute using Visual C#

[XmlRoot("NewRootName",
Namespace = "http://www.CustomNamespace.com",
IsNullable = true)]
public class SerializableClass
{
private string _name;
[XmlElement("NewElementName")]
public string Name
{
get { return _name; }
set { _name = value; }
}

private int _zipCode;


[XmlIgnore]
public int ZipCode
{
get { return _zipCode; }
set { _zipCode = value; }
}

Listing 8-25. XmlIgnore attribute using Visual Basic .NET

<XmlRoot("NewRootName", _
Namespace:="http://www.CustomNamespace.com", _
IsNullable:=True)> _
Public Class SerializableClass
Private _name As String

<XmlElement("NewElementName")> _
Public Property Name() As String
Get
Return _name
End Get
Set(ByVal value As String)

313
The Complete Reference To Professional SOA with Visual Studio 2005

_name = value
End Set
End Property
Private _zipCode As Integer

<XmlIgnore()> _
Public Property ZipCode() As Integer
Get
Return _zipCode
End Get
Set(ByVal value As Integer)
_zipCode = value
End Set
End Property
End Class

By adding the XmlIgnore attribute the ZipCode attribute is excluded from the serialization process. As we
can see from the listing 8-26 below. The ZipCode has been removed from the result.

Listing 8-26. SerializedObj.xml with ZipCode ignored

<?xml version="1.0"?>
<NewRootName xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.CustomNamespace.com">
<NewElementName>John Doe</NewElementName>
</NewRootName>

Serializing Arrays
Occasionally we need to define an array the serialization attribute for array is XmlArray and the items in the
array XmlArrayItem. In the following example we will define an array of CDs for an online record catalog
system.
The following listing demonstrates how to add an array of CD elements to the array CDS which is part of
the CATALOG class. Two attributes can be used to control how an array is serialized to XML: XmlArray and
XmlArrayItems. Here is the CATALOG class definition:

Listing 8-27. Catalog class using Visual C#

[XmlRoot(IsNullable=false)]
public class CATALOG
{
[XmlArray("CDS", IsNullable=false)]
[XmlArrayItem("CD", IsNullable=false)]
public CD [] CDS;
}

Listing 8-28. Catalog class using Visual Basic .NET

<XmlRoot(IsNullable:=False)> _
Public Class CATALOG
<XmlArray("CDS", IsNullable:=False)> _
<XmlArrayItem("CD", IsNullable:=False)> _

314
The Complete Reference To Professional SOA with Visual Studio 2005

Public CDS As CD()


End Class

The XmlArray attribute is used to control how the root element of the array is serialized. Since we have
specified IsNullable=false in XmlArray("CDS", IsNullable=false) for the CDS array. The CDS array is valid only if
the array of CDS is not null.
The XmlArrayItem attribute is used to control how each item within the array is serialized. Since we have
specified IsNullable=False in XmlArrayItem("CD", IsNullable=False) none of the items within the array can be set
to null.
In XML serialization, by default each element within the array has the same name as the type definition. In
this example, the type definition name is CATALOG. Because the name of the elements within the Items array
should be named CD, we explicitly set the name of the element by specifying it as the first parameter in the
XmlArray and XmlArrayItems attributes.
We can also use the XmlArrayItem attribute to define arrays containing instances of a mixture of datatypes.
We can do this by including an array with multiple XmlArrayItem attributes. The following code defines an
array that can contain items of type string and int:

Listing 8-29. Implementing XmlArrayItem using Visual C#

[XmlArrayItem("MyInt", typeof(int))]
[XmlArrayItem("MyString", typeof(string))]
public object [] TestArray;

Listing 8-30. Implementing XmlArrayItem using Visual Basic .NET

<XmlArrayItem("MyInt", GetType(Integer))> _
<XmlArrayItem("MyString", GetType(String))> _
Public TestArray As Object()

The preceding code will generate the following XML datatype definition:
<element minOccurs="1" maxOccurs="1" name="TestArray" nillable="true" type="s0:ArrayOfChoice1" />

<complexType name="ArrayOfChoice1">
<sequence>
<choice minOccurs="0" maxOccurs="unbounded">
<element minOccurs="1" maxOccurs="1" name="MyInt" type="int" />
<element minOccurs="1" maxOccurs="1" name="MyString" type="string" />
</choice>
</sequence>
</complexType>

Tip: Notice that the TestArray element can contain any combination of child elements of type string and int. To accept data of different
types from the client, the XML mixed array is mapped to a .NET array of type Object. The compiler will not throw an error if the .NET type
is set to something other than Object for example Integer. However, the client will receive a run-time error if the client sends an instance of
an XML datatype that cannot be transformed into the underlying .NET type.

The XmlArray and XmlArrayItems attributes expose additional properties that we can use to control how an
array is serialized to XML.

315
The Complete Reference To Professional SOA with Visual Studio 2005

Table 8-4. Properties of XmlArrayAttribute

Name Description

ElementName Gets or sets the XML element name given to the serialized array.

Form Gets or sets a value that indicates whether the XML element name generated by the
XmlSerializer is qualified or unqualified.

IsNullable Gets or sets a value that indicates whether the XmlSerializer must serialize a member as an
empty XML tag with the xsi:nil attribute set to true.

Namespace Gets or sets the namespace of the XML element.

Order Gets or sets the explicit order in which the elements are serialized or deserialized.

TypeId When implemented in a derived class, gets a unique identifier for this Attribute. (Inherited
from Attribute.)

Table 8-5. Properties of XmlArrayItemAttribute

Name Description

DataType Gets or sets the XML data type of the generated XML element.

ElementName Gets or sets the name of the generated XML element.

Form Gets or sets a value that indicates whether the name of the generated XML element is
qualified.

IsNullable Gets or sets a value that indicates whether the XmlSerializer must serialize a member as an
empty XML tag with the xsi:nil attribute set to true.

Namespace Gets or sets the namespace of the generated XML element.

NestingLevel Gets or sets the level in a hierarchy of XML elements that the XmlArrayItemAttribute
affects.

Type Gets or sets the type allowed in an array.

TypeId When implemented in a derived class, gets a unique identifier for this Attribute.(Inherited
from Attribute.)

XmlAnyElement and XmlAnyAttribute


It is often today for business requirements evolve and mature over time, as a result applications may also be
required to change. This may cause the XML document to contain some unexpected elements or attributes.

316
The Complete Reference To Professional SOA with Visual Studio 2005

Rather than simply throwing an exception and giving up we may want to preserve the content and the structure
of the data from the document so that it can be passed to another component for processing. The .NET
Framework provides two attributes that allow us to capture unknown XML elements and attributes. These are
XmlAnyAttribute and XmlAnyElement:

* XmlAnyElement is used to control how unknown elements.


* XmlAnyAttribute is used to control how unknown attributes.

XmlAnyElementAttribute is essentially a wild card that allows us to access elements that are not previously
defined. To use the XmlAnyAttribute we simply decorate a method with the XmlAnyElement() attribute. We
typically decorate over a property with a return type of XmlNode array this is because overtime there maybe
more than just one unknown node. See listing 8-31. and listing 8-32.

Listing 8-31. Demonstrates using XmlAnyElement with Visual C#

[XmlAnyElement()]
public XmlNode[] OpenElements
{
get { return _openElements; }
set { _openElements = value; }
}

Listing 8-32. Demonstrates using XmlAnyElement with Visual Basic .NET

<XmlAnyElement()> _
Public Property OpenElements() As XmlNode()
Get
Return _openElements
End Get
Set
_openElements = value
End Set
End Property

XmlAnyAttribute is a wild card ability to access attributes that has not been previously defined. To use the
XmlAnyAttribute we simply decorate a method with the XmlAnyAttribute() attribute. Using XmlAnyAttribute is
similar to using XmlAnyElement.

Listing 8-33. Demonstrates using XmlAnyAttribute with Visual C#

[XmlAnyAttribute()]
public XmlNode[] OpenAttributes
{
get { return _openAttributes; }
set { _openAttributes = value; }
}

Listing 8-34. Demonstrates using XmlAnyAttribute with Visual Basic .NET

<XmlAnyAttribute()> _
Public Property OpenAttributes() As XmlNode()
Get
Return _openAttributes

317
The Complete Reference To Professional SOA with Visual Studio 2005

End Get
Set
_openAttributes = value
End Set
End Property

XmlInclude - Derived Data types


We can use .NET serialization to define derived data types. XML serialization supports defining XML datatypes
that are derived by extension from other XML datatypes. We can define derived XML datatype by creating a
derived .NET type and then decorating the base type with the XmlInclude attribute.
In a generic example we define three classes, two of them are the class Car and Truck inherit from the third
Vehicle class. The example applies the XmlInclude attribute to a method that returns an instance of one of the
two derived classes.

Listing 8-35: Implementing XmlIncludeAttribute using Visual C#

public class Vehicle{}

public class Car:Vehicle{}

public class Truck:Vehicle{}

public class Sample


{
[WebMethodAttribute]
[XmlInclude(typeof(Car))]
[XmlInclude(typeof(Truck))]
public Vehicle ReturnVehicle(int i){
if(i == 0)
return new Car();
else
return new Truck();
}
}

Listing 8-36: Implementing XmlIncludeAttribute using Visual Basic .NET

Public Class Vehicle


End Class

Public Class Car


Inherits Vehicle
End Class

Public Class Truck


Inherits Vehicle
End Class

Public Class Sample

<WebMethodAttribute()> _

318
The Complete Reference To Professional SOA with Visual Studio 2005

<XmlInclude(GetType(Car))> _
<XmlInclude(GetType(Truck))> _
Public Function ReturnVehicle(ByVal i As Integer) As Vehicle
If i = 0 Then
Return New Car
Else
Return New Truck
End If
End Function
End Class
The preceding code will generate an XML datatype called Vehicle and two datatypes that derive by
extension from Vehicle these are Car and Truck. Because Car and Truck are extended versions of the Vehicle
datatype, Web service interfaces that accept the Vehicle datatype can also accept instances of Car and Truck.

Datatype Mapping
XML serialization provides a default mapping between .NET types and the built-in datatypes defined by XML
Schema. For example, a int type in .NET by default will be transformed by the XML serialization to the XML
built-in datatype Int32.
XML serialization supports all XML built-in datatypes.

Table 8-6. lists the supported mappings between XML datatypes and .NET types.

XSD data type .NET data type XSD data type .NET data type

anyURI String nonPositiveInteger String

base64Binary Array of Byte objects NOTATION String

boolean Boolean positiveInteger String

Byte SByte QName XmlQualifiedName

Date DateTime recurringDate String

dateTime DateTime duration String

decimal Decimal string String

double Double short Int16

ENTITY String time DateTime

ENTITIES String token String

Float Single unsignedByte Byte

319
The Complete Reference To Professional SOA with Visual Studio 2005

gDay String unsignedInt UInt32

gMonth String unsignedLong UInt64

gMonthDay String unsignedShort UInt16

gYear String IDREF String

gYearMonth String IDREFS String

hexBinary Array of Byte objects int Int32

ID String integer String

negativeInteger String language String

NMTOKEN String long Int64

NMTOKENS String Name String

normalizedString String NCName String

nonNegativeInteger String

Even though XML serialization will transform an XML datatype into its corresponding .NET type, it will
not perform any validation on the data. For example, the XML datatype integer maps to the String .NET type,
but the client can pass non-numeric data to the Web service. Therefore, it is up to the Web service to enforce
additional constraints over and above what is provided by the .NET type.

Strongly Typed XML Serialization


So far we have looked at customizing and controlling XML serialization. In this section we will examine how to
consume and produce XML that conforms to a particular XML schema. To do this we can automatically
generate .NET classes from predefined XML schemas (XSD). These classes use of XML serialization attributes
and can generate XML documents to conform to the schema.
.NET Framework provides an utility to help us with the XSD to .NET class generation process. As creating
serializable classes manually is possible it can easily become quite tedious. To fast track the process the
XSD.exe utility can generate our classes based on a XML schema.
In the following example we are presented with a schema for an online catalogue management system. The
schema contains a catalog the catalog contains a collection of CDs and information relevant to each CD.

Listing 8-37: Shows the XML Schema for the CD catalog document.

<?xml version="1.0" encoding="UTF-8"?>


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="ARTIST">

320
The Complete Reference To Professional SOA with Visual Studio 2005

<xs:complexType mixed="true" />


</xs:element>
<xs:element name="CATALOG">
<xs:complexType>
<xs:sequence>
<xs:element ref="CD" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="CD">
<xs:complexType>
<xs:sequence>
<xs:element ref="TITLE" maxOccurs="1" />
<xs:element ref="ARTIST" minOccurs="1" />
<xs:element ref="COUNTRY" />
<xs:element ref="COMPANY" />
<xs:element ref="PRICE" />
<xs:element ref="YEAR" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="COMPANY">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="COUNTRY">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="PRICE">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="TITLE" nillable="false">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="YEAR">
<xs:complexType mixed="true" />
</xs:element>
</xs:schema>

We can generate a serialization class from this by using .NET XSD.EXE tool,

Enter the command prompt via Start menu -> Microsoft Visual Studio 2005 -> Visual Studio Tools -> Visual Studio
2005 Command Prompt. (All the necessary environment variable will be setup)

The Syntax for the XSD tool is.


xsd /c cd_catalog.xsd

Tip: we can specify different languages using the /language:<language> parameter. For VB.NET we can specify
/language:VB to generate classes that are VB.NET syntax

xsd /c cd_catalog.xsd /language:VB

321
The Complete Reference To Professional SOA with Visual Studio 2005

Image 8-3: using XSD

The result is a cd_catalog.cs

Listing 8-38. cd_catalog.cs

using System.Xml.Serialization;

//
// This source code was auto-generated by xsd, Version=2.0.50727.42.
//

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class ARTIST {

private string[] textField;

/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public string[] Text {
get {
return this.textField;
}
set {
this.textField = value;
}
}
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]

322
The Complete Reference To Professional SOA with Visual Studio 2005

[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class CATALOG {

private CD[] cdField;

/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("CD")]
public CD[] CD {
get {
return this.cdField;
}
set {
this.cdField = value;
}
}
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class CD {

private TITLE tITLEField;

private ARTIST aRTISTField;

private COUNTRY cOUNTRYField;

private COMPANY cOMPANYField;

private PRICE pRICEField;

private YEAR yEARField;

/// <remarks/>
public TITLE TITLE {
get {
return this.tITLEField;
}
set {
this.tITLEField = value;
}
}

/// <remarks/>

323
The Complete Reference To Professional SOA with Visual Studio 2005

public ARTIST ARTIST {


get {
return this.aRTISTField;
}
set {
this.aRTISTField = value;
}
}

/// <remarks/>
public COUNTRY COUNTRY {
get {
return this.cOUNTRYField;
}
set {
this.cOUNTRYField = value;
}
}

/// <remarks/>
public COMPANY COMPANY {
get {
return this.cOMPANYField;
}
set {
this.cOMPANYField = value;
}
}

/// <remarks/>
public PRICE PRICE {
get {
return this.pRICEField;
}
set {
this.pRICEField = value;
}
}

/// <remarks/>
public YEAR YEAR {
get {
return this.yEARField;
}
set {
this.yEARField = value;
}
}
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]

324
The Complete Reference To Professional SOA with Visual Studio 2005

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class COMPANY {

private string[] textField;

/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public string[] Text {
get {
return this.textField;
}
set {
this.textField = value;
}
}
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class COUNTRY {

private string[] textField;

/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public string[] Text {
get {
return this.textField;
}
set {
this.textField = value;
}
}
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class PRICE {

private string[] textField;

325
The Complete Reference To Professional SOA with Visual Studio 2005

/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public string[] Text {
get {
return this.textField;
}
set {
this.textField = value;
}
}
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class TITLE {

private string[] textField;

/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public string[] Text {
get {
return this.textField;
}
set {
this.textField = value;
}
}
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class YEAR {

private string[] textField;

/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public string[] Text {
get {
return this.textField;
}

326
The Complete Reference To Professional SOA with Visual Studio 2005

set {
this.textField = value;
}
}
}

For VB based generated code see listing 8-39below.

Listing 8-39. cd_catalog.VB

Option Strict Off


Option Explicit On

Imports System.Xml.Serialization

'
'This source code was auto-generated by xsd, Version=2.0.50727.42.
'

'''<remarks/>
<System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42"), _
System.SerializableAttribute(), _
System.Diagnostics.DebuggerStepThroughAttribute(), _
System.ComponentModel.DesignerCategoryAttribute("code"), _
System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=true), _
System.Xml.Serialization.XmlRootAttribute([Namespace]:="", _
IsNullable:=false)> _
Partial Public Class ARTIST

Private textField() As String

'''<remarks/>
<System.Xml.Serialization.XmlTextAttribute()> _
Public Property Text() As String()
Get
Return Me.textField
End Get
Set
Me.textField = value
End Set
End Property
End Class

'''<remarks/>
<System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42"), _
System.SerializableAttribute(), _
System.Diagnostics.DebuggerStepThroughAttribute(), _
System.ComponentModel.DesignerCategoryAttribute("code"), _
System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=true), _
System.Xml.Serialization.XmlRootAttribute([Namespace]:="", _
IsNullable:=false)> _
Partial Public Class CATALOG

327
The Complete Reference To Professional SOA with Visual Studio 2005

Private cdField() As CD

'''<remarks/>
<System.Xml.Serialization.XmlElementAttribute("CD")> _
Public Property CD() As CD()
Get
Return Me.cdField
End Get
Set
Me.cdField = value
End Set
End Property
End Class

'''<remarks/>
<System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42"), _
System.SerializableAttribute(), _
System.Diagnostics.DebuggerStepThroughAttribute(), _
System.ComponentModel.DesignerCategoryAttribute("code"), _
System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=true), _
System.Xml.Serialization.XmlRootAttribute([Namespace]:="", _
IsNullable:=false)> _
Partial Public Class CD

Private tITLEField As TITLE

Private aRTISTField As ARTIST

Private cOUNTRYField As COUNTRY

Private cOMPANYField As COMPANY

Private pRICEField As PRICE

Private yEARField As YEAR

'''<remarks/>
Public Property TITLE() As TITLE
Get
Return Me.tITLEField
End Get
Set
Me.tITLEField = value
End Set
End Property

'''<remarks/>
Public Property ARTIST() As ARTIST
Get
Return Me.aRTISTField
End Get
Set

328
The Complete Reference To Professional SOA with Visual Studio 2005

Me.aRTISTField = value
End Set
End Property

'''<remarks/>
Public Property COUNTRY() As COUNTRY
Get
Return Me.cOUNTRYField
End Get
Set
Me.cOUNTRYField = value
End Set
End Property

'''<remarks/>
Public Property COMPANY() As COMPANY
Get
Return Me.cOMPANYField
End Get
Set
Me.cOMPANYField = value
End Set
End Property

'''<remarks/>
Public Property PRICE() As PRICE
Get
Return Me.pRICEField
End Get
Set
Me.pRICEField = value
End Set
End Property

'''<remarks/>
Public Property YEAR() As YEAR
Get
Return Me.yEARField
End Get
Set
Me.yEARField = value
End Set
End Property
End Class

'''<remarks/>
<System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42"), _
System.SerializableAttribute(), _
System.Diagnostics.DebuggerStepThroughAttribute(), _
System.ComponentModel.DesignerCategoryAttribute("code"), _
System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=true), _
System.Xml.Serialization.XmlRootAttribute([Namespace]:="", _
IsNullable:=false)> _

329
The Complete Reference To Professional SOA with Visual Studio 2005

Partial Public Class COMPANY

Private textField() As String

'''<remarks/>
<System.Xml.Serialization.XmlTextAttribute()> _
Public Property Text() As String()
Get
Return Me.textField
End Get
Set
Me.textField = value
End Set
End Property
End Class

'''<remarks/>
<System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42"), _
System.SerializableAttribute(), _
System.Diagnostics.DebuggerStepThroughAttribute(), _
System.ComponentModel.DesignerCategoryAttribute("code"), _
System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=true), _
System.Xml.Serialization.XmlRootAttribute([Namespace]:="", _
IsNullable:=false)> _
Partial Public Class COUNTRY

Private textField() As String

'''<remarks/>
<System.Xml.Serialization.XmlTextAttribute()> _
Public Property Text() As String()
Get
Return Me.textField
End Get
Set
Me.textField = value
End Set
End Property
End Class

'''<remarks/>
<System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42"), _
System.SerializableAttribute(), _
System.Diagnostics.DebuggerStepThroughAttribute(), _
System.ComponentModel.DesignerCategoryAttribute("code"), _
System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=true), _
System.Xml.Serialization.XmlRootAttribute([Namespace]:="", _
IsNullable:=false)> _
Partial Public Class PRICE

Private textField() As String

'''<remarks/>

330
The Complete Reference To Professional SOA with Visual Studio 2005

<System.Xml.Serialization.XmlTextAttribute()> _
Public Property Text() As String()
Get
Return Me.textField
End Get
Set
Me.textField = value
End Set
End Property
End Class

'''<remarks/>
<System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42"), _
System.SerializableAttribute(), _
System.Diagnostics.DebuggerStepThroughAttribute(), _
System.ComponentModel.DesignerCategoryAttribute("code"), _
System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=true), _
System.Xml.Serialization.XmlRootAttribute([Namespace]:="", _
IsNullable:=false)> _
Partial Public Class TITLE

Private textField() As String

'''<remarks/>
<System.Xml.Serialization.XmlTextAttribute()> _
Public Property Text() As String()
Get
Return Me.textField
End Get
Set
Me.textField = value
End Set
End Property
End Class

'''<remarks/>
<System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42"), _
System.SerializableAttribute(), _
System.Diagnostics.DebuggerStepThroughAttribute(), _
System.ComponentModel.DesignerCategoryAttribute("code"), _
System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=true), _
System.Xml.Serialization.XmlRootAttribute([Namespace]:="", _
IsNullable:=false)> _
Partial Public Class YEAR

Private textField() As String

'''<remarks/>
<System.Xml.Serialization.XmlTextAttribute()> _
Public Property Text() As String()
Get
Return Me.textField
End Get

331
The Complete Reference To Professional SOA with Visual Studio 2005

Set
Me.textField = value
End Set
End Property
End Class

After the class is generated we can include the class into our project. Using these classes, we can develop in
an object oriented fashion to generate any XML document to conform to the original XML schema file. The
generated class cd_catalog.cs for C# and cd_catalog.vb if we’re generating for Visual Basic.

Open Schema with XmlAnyAttribute and


XmlAnyElement
Quite often it is necessary to allow data to be included within an instance of a particular XML datatype even if
we did not anticipate this when we created the schema. By doing so, we can improve the scalability of our
system without the requirement to recreate our schemas. This is important especially when our Web service is
made public on the internet. It allows additional information to be submitted by our consumers without the need
to redefine our schemas. A good example is if an order was placed on an online music store against a particular
CD and shipping details were required to be submitted. However the consumer of the Web service had provided
some additional details to what we had originally specified in our schema. Normally the additional information
will simply be lost. However using XmlAnyElement and XmlAnyAttribute we can still obtain the information.

Listing 8-40: Shipment details with additional Location information

<?xml version="1.0"?>
<Shipment xmlns="http://schema.servergeek.com/2004/7">
<OrderNo>101</OrderNo>
<Location>
<Addr>76 Reberto av</Addr>
<City>Organge Bay</City>
<State>CA</State>
</Location>
</Shipment>

Listing 8-41. Shipping Details

<?xml version="1.0"?>
<Shipment xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
xmlns="http://schema.soawithwebservice.com/2006/9">
<OrderNo>102</OrderNo>
<Location>
<Addr>76 Reberto av </Addr>
<City>Organge Bay </City>
<State>CA</State>
<Zip>OB6527</Zip>
</Location>
</Shipment>

Schemas that allow the inclusion of additional elements and attributes that are not formally defined within the
schema itself are often referred to as open schemas.

332
The Complete Reference To Professional SOA with Visual Studio 2005

We can create an open schema by decorating a public field or property with the XmlAnyAttribute and
XmlAnyElement attributes. The XmlAnyAttribute attribute specifies that the parent element can contain any XML
attribute in addition to the ones formally defined within the schema. The XmlAnyElement attribute specifies that
the parent element can contain any XML element in addition to the ones formally defined within the schema.
The flexibility of open schemas can be very enticing. However, we should consider the consequences before
we create an open schema because the code needed to handle and process the extended data can become a little
complex.
One popular method for allowing extended information to be included within an instance document in a
semi-controlled fashion is to provide an area in the document definition for that information. The following
example defines an element within the CD datatype that is designated for containing extended information about
the CD:

Listing 8-42. Using XmlAnyElement using Visual C#

[XmlRoot(Namespace=”http://www.mswcf.com”)]
public class Shipment
{
string _orderNo = string.Empty;
Location _location = new Location();
public string OrderNo
{
get { return _orderNo; }
set { _orderNo = value; }
}
public Location Location
{
get { return _location; }
set { _location = value; }
}
}

[XmlRoot(Namespace = ”http://www.mswcf.com”)]
public class Location
{
string _addr = string.Empty;
string _city = string.Empty;
string _state = string.Empty;
public string Addr
{
get { return _addr; }
set { _addr = value; }
}
public string City
{
get { return _city; }
set { _city = value; }
}
public string State
{
get { return _state; }
set { _state = value; }
}

333
The Complete Reference To Professional SOA with Visual Studio 2005

XmlNode[] _openElements = null;


[XmlAnyElement()]
public XmlNode[] OpenElements
{
get { return _openElements; }
set { _openElements = value; }
}
}

Listing 8-42. Using XmlAnyElement using Visual Basic .NET

<XmlRoot(Namespace=”http://www.mswcf.com”)> _
Public Class Shipment
Private _orderNo As String = String.Empty
Private _location As Location = New Location

Public Property OrderNo() As String


Get
Return _orderNo
End Get
Set
_orderNo = value
End Set
End Property

Public Property Location() As Location


Get
Return _location
End Get
Set
_location = value
End Set
End Property
End Class

<XmlRoot(Namespace=”http://www.mswcf.com”)> _
Public Class Location
Private _addr As String = String.Empty
Private _city As String = String.Empty
Private _state As String = String.Empty

Public Property Addr() As String


Get
Return _addr
End Get
Set
_addr = value
End Set
End Property

Public Property City() As String


Get
Return _city

334
The Complete Reference To Professional SOA with Visual Studio 2005

End Get
Set
_city = value
End Set
End Property

Public Property State() As String


Get
Return _state
End Get
Set
_state = value
End Set
End Property
Private _openElements As XmlNode() = Nothing

<XmlAnyElement()> _
Public Property OpenElements() As XmlNode()
Get
Return _openElements
End Get
Set
_openElements = value
End Set
End Property
End Class

The public field or property which includes the XmlAnyAttribute attribute can be of type XmlElement or
XmlNode. Because the XmlElement and XmlNode types are part of the XML DOM that ships with .NET, we can
use the methods and properties exposed by these types to navigate through the additional data that accompanied
the purchase order.
The preceding code defines an additional element within the Shipment XML datatype called OpenElement.
This element can contain any attribute as well as any element. The above code generates the following schema
containing the OpenElement element definition:

Listing 8-43. shows the schema that support open schema

<?xml version="1.0" encoding="utf-8" ?>


<xs:schema id="order" targetNamespace="http://schema.SOAWebservice.com/2006/9"
xmlns:bks="http://schema.SOAWebservice.com/2006/9"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
attributeFormDefault="qualified">
<xs:element name="Shipment">
<xs:complexType>
<xs:sequence>
<xs:element name="OrderNo" type="xs:string"/>
<xs:element name="Location">
<xs:complexType>
<xs:sequence>
<xs:element name="Addr" type="xs:string" />
<xs:element name="City" type="xs:string" />
<xs:element name="State" type="xs:string" />

335
The Complete Reference To Professional SOA with Visual Studio 2005

<xs:sequence>
<xs:any namespace="##any" minOccurs="0"
maxOccurs="unbounded"
processContents="skip" />
</xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:sequence>
<xs:any namespace="##any"
minOccurs="0" maxOccurs="unbounded"
processContents="skip" />
</xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

In the schema above, the namespace for the open elements are declared as '##any', which is the default value.
Alternatively, we can supply the specific namespace that is allowed, or another predefined namespace tokens.
These tokens are:

##other - The XML elements must be from any namespace other than the target namespace is allowed.
##local - The XML elements must not be in a namespace.

##targetNamespace - The XML must be in the target namespace.

The processContents attribute in the xs:any element is set to 'skip' in this example, which instructs a schema
validator to ignore the nodes that are part of the open element. A complete list of options follows:

Lax - Enforce schema if a namespace is declared and the validator has access to the schema definition.

Skip - No schema enforcement.


Strict - Always enforce schema for this open element.

Summary
In this chapter we have examined XML serialization. XML serialization is an important aspect of Web services
as all communication between Web services are achieved through data serialization. It is responsible for
serializing instances of .NET types to XML and deserializing XML to instances of .NET types. This includes
support for instances of built-in .NET types, classes, and structures as well as composite types such as arrays,
nested object hierarchies, and objects that support the ICollection and IEnumerable interfaces. It also supports
serializing .NET type definitions into an XML schema.
XML serialization has default behaviors that might not be appropriate in all situations, so the .NET platform
provides a collection of attributes that we can apply to .NET type definitions, variable declarations, and
parameter declarations to control the behavior of .NET serialization.

336
The Complete Reference To Professional SOA with Visual Studio 2005

Chapter 9 Creating and


Consuming Web Service using
Visual Studio 2005
In this chapter we will be examining the XML Web Services programming in Visual Studio 2005 which allows
us to build highly scalable, loosely coupled, distributed applications to enable our Service Oriented Architecture.
To do this we will be using Web protocol standards such as HTTP, XML, and SOAP.

Web Service Summary


Just a quick recap on XML Web Service: A XML Web Service is the building block from which to build
scalable, loosely coupled, platform-independent applications. Web Service use XML to enable disparate
applications to exchange messages using standard protocols such as HTTP, XML, XSD, SOAP, and Web
Services Description Language (WSDL).

Figure 9-1. Communication between a client and an XML Web Service

The exchange between a client and a XML Web Service consists of several stages. A client can be any
application that can facilitate a SOAP request to the XML Web Service this includes, console applications,
Windows forms applications, Web form applications and or even another XML Web Service. The following
steps are performed during these phases (see Figure 9-1):

337
The Complete Reference To Professional SOA with Visual Studio 2005

* The client creates an object of the XML Web Service by creating a proxy class on the computer on which the
client resides. The client calls a method on the proxy object. The request on the client system serializes the
method call and arguments into a SOAP message and sends it to the XML Web Service over the network.

* The XML Web Service on the server after receiving the request deserializes the SOAP message. The
deserialized message is then used to create an instance of the XML Web Service. The instance is used to
invoke the XML Web Service method with the arguments on the XML Web Service. The XML Web Service
executes the method and returns the value to the requesting client.

* The XML Web Service serializes the response return value and any out parameters into a SOAP message and
sends them to the client over the network.

* The client application after receiving the response message deserializes the SOAP message containing the
return value and any out parameters and sends them to the proxy object. The proxy object passes the relevant
return value and any out parameter back into the application.

In order to build XML Web Services that the clients can consume, we can use the ASP.NET Framework,
which is an integral part of the .NET Framework. Visual Studio 2005 also provides tools to build, deploy, and
publish the XML Web Services once development is complete. In the following section we will look at
development with Visual Studio 2005.

Creating XML Web Services


In the previous chapters we had already examined the simplicity involved in creating XML Web Service with
Visual Studio 2005. Developing a XML Web Service is similar to creating a Component Object Model (COM)
component that provides application logic to a client application. We create an XML Web Service to provide
specific functionality to client applications over the Web.
To create an XML Web Service, we first choose a programming language in which we want to create the
service and create a class that inherits from System.Web.Services.WebService. Next, we require an
infrastructure that makes the XML Web Service available for client applications to use over the Internet. Visual
Studio 2005 provides us with tools that help build, deploy, and consume an XML Web Service.
In this section we will be looking at manipulating employee information using the AdventureWorks
database. This sample Web Service will allow modification to employee details. To provide this functionality we
will need to create an XML Web Service that will support the adding and updating of employee details. The
AdventureWorks XML Web Service, however, is not user-interface driven or interactive. The XML Web
Service only provides the application logic.
The Visual Studio 2005 IDE provides us with the environment needed to create projects for distributed
desktop applications, Web applications, and XML Web Services. To create an XML Web Service, perform the
following steps:

338
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 9-2: New Web Site

1. Open the Visual Studio 2005. Start a project to create a new Web Site by pointing to File -> New -> Web Site.
Figure 9-2.

Figure 9-3: New Web Site

2. In the New Web Site dialog box, select Visual C# or Visual Basic as the language. Also select the location of
the Web Service that we would like it to be in. In the Templates pane, select ASP.NET Web Service. In the
Location box, type the name and location of the XML Web Service as
http://localhost/soa/AdventureWorks/Employee, and click OK. Figure 9-3.

339
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 9-4: Select “Browse” button for the Choose Location dialog window

3. .NET offers several forms of storage for Web Service, we could save our Web Service to File System, Local
IIS, FTP Site or Remote Site. In this instance we will be saving to an IIS location. Figure 9-4.

NOTE: If we are creating Web Service on a remote computer. The remote computer must be running .NET Framework version 2.0 and
must have IIS version 5.0 or later installed and running, ASP.NET must be enabled on IIS and FrontPage Server Extensions must be
installed and enabled at the root level where we are creating the new Web site. The user must also have FrontPage administration or
author permissions to create new folders and files on the remoting computer under the root folder where we want the site to be.

When we create the ASP.NET Web Service project, an .asmx file is created. After creating an XML Web
Service project, we write the code to provide functionality to the XML Web Service. This code is stored in a file
associated with the .cs or .vb file and is known as the code-behind file. The code-behind file depends on the
language that we use to create the XML Web Service. For a Visual C# project, the code-behind file is a .cs file.
The default template content of the file is shown in the listing 9-1and listing 9-2below.

Listing 9-1. XML Web Service default code behind using Visual C#

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
public Service () {

//Uncomment the following line if using designed components


//InitializeComponent();
}

[WebMethod]

340
The Complete Reference To Professional SOA with Visual Studio 2005

public string HelloWorld() {


return "Hello World";
}

}
For a Visual Basic .NET project, the default code-behind file is the service.vb file.

Listing 9-2. XML Web Service default code behind using Visual Basic .NET

Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols

<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class Service
Inherits System.Web.Services.WebService

<WebMethod()> _
Public Function HelloWorld() As String
Return "Hello World"
End Function

End Class

The .asmx file acts as the front end of the Web Service. It specifies the language that’s used to implement
the service logic, it also points to the actual file implementation of the code behind content of the Web Service.
The .asmx file is shown below. Listing 9-3 and Listing 9-4.

Listing 9-3. Service.asmx for a Visual C# project

<%@ WebService Language="C#"


CodeBehind="~/App_Code/Service.cs" Class="Service" %>

Listing 9-4. Service.asmx for a Visual Basic project

<%@ WebService Language="vb"


CodeBehind="~/App_Code/Service.vb" Class="Service" %>

Figure 9-5: Solution Explorer

341
The Complete Reference To Professional SOA with Visual Studio 2005

Under the Solution Explorer we can see the structure of the application Figure 9-5. Under App_Code the
code for the webservice will be stored there. The App_Data folder is used by ASP.NET to store databases that
the system maintains. The .asmx is our .NET Web Service.
1. Rename the Service.asmx to Employee.asmx and

2. Then the service.cs file under the App_Code folder as Employee.cs.

Or
Service.vb file under App_Code folder as Employee.vb

3. Double click on the Employee.cs to open the code behind and rename the class from Service to Employee and
also change its constructor to Employee if using Visual C# see Listing 9-5. Otherwise if using Visual Basic
.NET its just the class name see listing 9-6.

Listing 9-5. Renamed Class and Constructor in Visual C# implementation

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Employee : System.Web.Services.WebService
{
public Employee()
{

//Uncomment the following line if using designed components


//InitializeComponent();
}

[WebMethod]
public string HelloWorld() {
return "Hello World";
}

Listing 9-6. Rename Web Service template’s default Service name to Employee

Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols

<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class Employee
Inherits System.Web.Services.WebService

342
The Complete Reference To Professional SOA with Visual Studio 2005

<WebMethod()> _
Public Function HelloWorld() As String
Return "Hello World"
End Function

End Class

Since we have changed the file name as well as the class name we will need to adjust the .asmx accordingly.
So that the correct file and class is pointed to by the Employee.asmx file.
4. Double click on the Employee.asmx file and change the code bind pointer to
CodeBehind="~/App_Code/Employee.cs" Class="Employee".

Or
CodeBehind="~/App_Code/Employee.vb" Class="Employee".

Before we start to create the AdventureWorks employee management XML Web Service we need to ensure
that we have the relevant database table:

NOTE: We can install the sample database when installing Sql Server 2005 by specifying the advanced selection during installation and
enabling the AdventureWorks database for install. Or if Sql Server 2005 Express edition is used the database can be downloaded from the
Microsoft’s download site by using AdventureWorks as the search keyword.

We will be focusing on two tables. Employee under HumanResources and Contact under Person.
The Employee table contains employee information such as their national identification number, work title,
and vacation and sick leave hours listing 9-7.

Listing 9-7: The SQL create script for the Employee table

CREATE TABLE [HumanResources].[Employee](


[EmployeeID] [int] IDENTITY(1,1) NOT NULL,
[NationalIDNumber] [nvarchar](15) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[ContactID] [int] NOT NULL,
[LoginID] [nvarchar](256) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[ManagerID] [int] NULL,
[Title] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[BirthDate] [datetime] NOT NULL,
[MaritalStatus] [nchar](1) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Gender] [nchar](1) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[HireDate] [datetime] NOT NULL,
[SalariedFlag] [dbo].[Flag] NOT NULL CONSTRAINT [DF_Employee_SalariedFlag] DEFAULT ((1)),
[VacationHours] [smallint] NOT NULL CONSTRAINT [DF_Employee_VacationHours] DEFAULT ((0)),
[SickLeaveHours] [smallint] NOT NULL CONSTRAINT [DF_Employee_SickLeaveHours] DEFAULT ((0)),
[CurrentFlag] [dbo].[Flag] NOT NULL CONSTRAINT [DF_Employee_CurrentFlag] DEFAULT ((1)),
[rowguid] [uniqueidentifier] ROWGUIDCOL NOT NULL CONSTRAINT [DF_Employee_rowguid] DEFAULT (newid()),
[ModifiedDate] [datetime] NOT NULL CONSTRAINT [DF_Employee_ModifiedDate] DEFAULT (getdate()),
CONSTRAINT [PK_Employee_EmployeeID] PRIMARY KEY CLUSTERED
(
[EmployeeID] ASC

343
The Complete Reference To Professional SOA with Visual Studio 2005

)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]


) ON [PRIMARY]

The Contact table contains a list of names and related information for each customer, employee, or vendor.
For example, a customer (store) may provide a sales agent name as a primary contact for their company and a
sales manager as a secondary contact listing 9-8.

Listing 9-8. The SQL create script for the Contact table

CREATE TABLE [Person].[Contact](


[ContactID] [int] IDENTITY(1,1)
NOT FOR REPLICATION NOT NULL,
[NameStyle] [dbo].[NameStyle]
NOT NULL CONSTRAINT [DF_Contact_NameStyle] DEFAULT ((0)),
[Title] [nvarchar](8)
COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[FirstName] [dbo].[Name] NOT NULL,
[MiddleName] [dbo].[Name] NULL,
[LastName] [dbo].[Name] NOT NULL,
[Suffix] [nvarchar](10)
COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[EmailAddress] [nvarchar](50)
COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[EmailPromotion] [int] NOT NULL CONSTRAINT
[DF_Contact_EmailPromotion] DEFAULT ((0)),
[Phone] [dbo].[Phone] NULL,
[PasswordHash] [varchar](40)
COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[PasswordSalt] [varchar](10)
COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[AdditionalContactInfo] [xml]
(CONTENT [Person].[AdditionalContactInfoSchemaCollection]) NULL,
[rowguid] [uniqueidentifier]
ROWGUIDCOL NOT NULL CONSTRAINT
[DF_Contact_rowguid] DEFAULT (newid()),
[ModifiedDate] [datetime]
NOT NULL CONSTRAINT [DF_Contact_ModifiedDate]
DEFAULT (getdate()),
CONSTRAINT [PK_Contact_ContactID] PRIMARY KEY CLUSTERED
(
[ContactID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

344
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 9-6: ERD for Employee table and Contact table

After the database is setup, we can provide the relevant functionality to the XML Web Service. To enable
client applications to access and use the XML Web Service, we expose the functionality of the XML Web
Service by creating Web methods. Web methods are independent functional units that perform certain predefined
operations in an XML Web Service. We use the <WebMethod> attribute in Visual Basic .NET listing 9-10 or the
[WebMethod] attribute in Visual C# to declare a Web method listing 9-9, depending on the language we choose
to develop the XML Web Service in.

Listing 9-9. Creating WebMethod using Visual C#

[WebMethod]
public string HelloWorld() {
return "Hello World";
}

Listing 9-10. Creating WebMethod using Visual Basic .NET

<WebMethod()> _
Public Function HelloWorld() As String
Return "Hello World"
End Function

In our employee management code below we have created three functions.

GetEmployees, which retrieves a list of employee details

GetEmployeeByID, which retrieves the employee details by a specific ID

UpdateEmployeeDetailByID, which updates the personal details of a specific employee

Firstly we need to enable our connection to the AdventureWorks database using the the SqlConnection
class. The listing 9-11and listing 9-12 below shows how to use SqlConnection to connect to the AdventureWorks
database. In the connection string the Database login id of Book and Password Book is used. If you will need to
adjust the credential information inorder for the connection to work.

345
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 9-11. Constructor and Finalizer to ensure our database connection is opened and closed using Visual C#

public class Employee : System.Web.Services.WebService


{
SqlConnection sqlcon =
new SqlConnection("Data Source=DEVSERVER01;Initial Catalog=AdventureWorks;Persist Security Info=True;User
ID=Book;Password=Book");

public Employee () {

//Uncomment the following line if using designed components


//InitializeComponent();
sqlcon.Open();
}

~Employee()
{
if (sqlcon.State == ConnectionState.Open)
{
sqlcon.Close();
}
}

Listing 9-12. Constructor and Finalizer to ensure our database connection is opened and closed using Visual Basic .NET

Public Class Employee


Inherits System.Web.Services.WebService
Private sqlcon As SqlConnection = New SqlConnection( _
"Data Source=DEVSERVER01;Initial " & _
"Catalog=AdventureWorks;Persist Security " & _
"Info=True;User ID=Book;Password=Book")

Public Sub New()


sqlcon.Open()
End Sub

Protected Overrides Sub Finalize()


If (sqlcon.State = ConnectionState.Open) Then
sqlcon.Close()
End If
End Sub
End Class

In C# we use ~Classname() to specify the finalizer in VB.NET we can override the Finalize method to
achieve the same result. A finalizer is the last method called before the code exits. It is usually used to clean up
file handles and database connections. Within the finalizer method we also check to see if the sqlconnection is
still open by using the sqlcon. If the connection is still open then we will close it.
Since we are performing database operations using ADO.NET we need to add the System.Data and
System.Data.SqlClient namespace to our code listing 9-13 and listing 9-14.

Listing 9-13. Adding the required namespace to code using Visual C#

using System.Data;

346
The Complete Reference To Professional SOA with Visual Studio 2005

using System.Data.SqlClient;

Listing 9-14. Adding the required namespace to code using Visual Basic .NET

Imports System.Data
Imports System.Data.SqlClient

The below listing shows how to implement the GetEmplyoees Method which is used to retrieve a list of
employee details From the XML Web Service listing 9-15and listing 9-16.

Listing 9-15. Implementing GetEmployees() using Visual C#

[WebMethod]
public DataSet GetEmployees () {
SqlDataAdapter sqlda = new SqlDataAdapter(
@"Select EmployeeID, FirstName, MiddleName, LastName, EmailAddress, Phone,
HumanResources.Employee.Title, BirthDate, MaritalStatus, Gender, HireDate, HumanResources.Employee.ContactID
from HumanResources.Employee
inner join Person.Contact on HumanResources.Employee.ContactID =
Person.Contact.ContactID",
sqlcon);
DataSet dsEmployees = new DataSet();

sqlda.Fill(dsEmployees);

return dsEmployees;
}

Listing 9-16. Implementing GetEmployees() using Visual Basic .NET

<WebMethod()> _
Public Function GetEmployees() As DataSet
Dim sqlda As SqlDataAdapter = _
New SqlDataAdapter("Select EmployeeID, " & _
"FirstName, MiddleName, LastName, EmailAddress," & _
" Phone, HumanResources.Employee.Title, BirthDate, " & _
"MaritalStatus, Gender, HireDate, HumanResources.Employee.ContactID " & _
" from HumanResources.Employee inner join Person.Contact on " & _
"HumanResources.Employee.ContactID = Person.Contact.ContactID", _
sqlcon)
Dim dsEmployees As DataSet = New DataSet
sqlda.Fill(dsEmployees)
Return dsEmployees
End Function

In listing 9-15 and listing 9-16 the GetEmployees code we are required to populate the dataset with all
employees. A SqlDataAdapater is used to fill the dataset. We then return the dataset in the WebMethod. We
don’t need to worry about the serialization aspect. As .NET Framework is nice enough to handle all of it for us.

Listing 9-17. Implementing GetEmployeeByID() using Visual C#

[WebMethod]

347
The Complete Reference To Professional SOA with Visual Studio 2005

public DataSet GetEmployeeByID(int EmployeeID)


{
SqlDataAdapter sqlda = new SqlDataAdapter(
@"Select EmployeeID, FirstName, MiddleName,
LastName, EmailAddress, Phone, HumanResources.Employee.Title,
BirthDate, MaritalStatus, Gender, HireDate, HumanResources.Employee.ContactID
from HumanResources.Employee
inner join Person.Contact on HumanResources.Employee.ContactID =
Person.Contact.ContactID where EmployeeID = @EmployeeID",
sqlcon);
sqlda.SelectCommand.Parameters.Add
("@EmployeeID",SqlDbType.Int,
sizeof(int)).Value = EmployeeID;

DataSet dsEmployees = new DataSet();


sqlda.Fill(dsEmployees);

return dsEmployees;
}

Listing 9-18. Implementing GetEmployeeByID() using Visual Basic .NET

<WebMethod()> _
Public Function GetEmployeeByID(ByVal EmployeeID As Integer) As DataSet
Dim sqlda As SqlDataAdapter = New SqlDataAdapter("Select EmployeeID," & _
" FirstName, MiddleName, LastName, EmailAddress, Phone," & _
" HumanResources.Employee.Title, BirthDate, MaritalStatus, " & _
"Gender, HireDate, HumanResources.Employee.ContactID " & _
"from HumanResources.Employee inner join Person.Contact " & _
"on HumanResources.Employee.ContactID = Person.Contact.ContactID " & _
" where EmployeeID = @EmployeeID", sqlcon)
sqlda.SelectCommand.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID
Dim dsEmployees As DataSet = New DataSet
sqlda.Fill(dsEmployees)
Return dsEmployees
End Function

In listing 9-17 and listing 9-18 above the WebMethod will return the information of a specific employee by
allowing the client to pass in an integer value of the employee ID. Once the WebMethod is called we execute a
sql query to return the client information into a DataSet which is then returned to the consumer of the Web
Service.

Listing 9-19. Implementing UpdateEmployeeDetailByID() using Visual C#

[WebMethod]
public void UpdateEmployeeDetailByID(
int EmployeeID,
string EmployeeFirstName,
string EmployeeMiddleName,
string EmployeeLastName,
string EmailAddress,
string Phone,

348
The Complete Reference To Professional SOA with Visual Studio 2005

string Title,
string BirthDate,
string MaritalStatus,
string Gender,
string HireDate)
{
SqlTransaction transaction = this.sqlcon.BeginTransaction("EmployeeTran");
try
{
// update Person.Contact
SqlCommand sqlcmdEmployee = new SqlCommand(
@"update Person.Contact con set
FirstName = @FirstName,
MiddleName = @MiddleName,
LastName = @LastName
EmailAddress = @EmailAddress,
Phone = @Phone,
inner join HumanResources.Employee emp on
emp.ContactID = con.ContactID
where
EmployeeID = @EmployeeID;

update HumanResources.Employee emp


set Title = @Title,
BirthDate = @BirthDate,
MaritalStatus = @MaritalStatus,
Gender = @Gender,
HireDate = @HireDate where
emp.EmployeeID = @EmployeeID;
",
sqlcon);
sqlcmdEmployee.Transaction = transaction;

sqlcmdEmployee.Parameters.Add
("@FirstName", SqlDbType.VarChar, 50)
.Value = EmployeeFirstName;
sqlcmdEmployee.Parameters.Add
("@MiddleName", SqlDbType.VarChar, 50)
.Value = EmployeeMiddleName;
sqlcmdEmployee.Parameters.Add
("@LastName", SqlDbType.VarChar, 50)
.Value = EmployeeLastName;

sqlcmdEmployee.Parameters.Add
("@Title", SqlDbType.Int,
sizeof(int)).Value = EmployeeID;
sqlcmdEmployee.Parameters.Add
("@BirthDate", SqlDbType.VarChar, 50)
.Value = EmployeeLastName;
sqlcmdEmployee.Parameters.Add
("@MaritalStatus", SqlDbType.VarChar, 50)
.Value = EmployeeLastName;
sqlcmdEmployee.Parameters.Add

349
The Complete Reference To Professional SOA with Visual Studio 2005

("@Gender", SqlDbType.VarChar, 50)


.Value = EmployeeLastName;
sqlcmdEmployee.Parameters.Add
("@HireDate", SqlDbType.VarChar, 50)
.Value = EmployeeLastName;
sqlcmdEmployee.ExecuteNonQuery();

transaction.Commit();
} catch {
transaction.Rollback();
}
}

Listing 9-20. Implementing UpdateEmployeeDetailByID() using Visual Basic .NET

<WebMethod()> _
Public Sub UpdateEmployeeDetailByID(ByVal EmployeeID As Integer, _
ByVal EmployeeFirstName As String, ByVal EmployeeMiddleName As String, _
ByVal EmployeeLastName As String, ByVal EmailAddress As String, _
ByVal Phone As String, ByVal Title As String, _
ByVal BirthDate As String, ByVal MaritalStatus As String, _
ByVal Gender As String, ByVal HireDate As String)
Dim transaction As SqlTransaction = _
Me.sqlcon.BeginTransaction("EmployeeTran")
Try
Dim sqlcmdContactID As SqlCommand = _
New SqlCommand("select contactid from " & _
"HumanResources.Employee where " & _
"HumanResources.Employee.EmployeeID = @EmployeeID", sqlcon)
sqlcmdContactID.Parameters.Add("@EmployeeID", _
SqlDbType.Int).Value = EmployeeID
sqlcmdContactID.Transaction = transaction
Dim contactID As Integer = _
CType(sqlcmdContactID.ExecuteScalar, Integer)
Dim sqlcmdEmployee As SqlCommand = _
New SqlCommand(" update Person.Contact set " & _
"FirstName = @FirstName, MiddleName = @MiddleName, " & _
"LastName = @LastName, EmailAddress = @EmailAddress, " & _
"Phone = @Phone where Person.Contact.ContactID " & _
"= @ContactID; update HumanResources.Employee " & _
"set Title = @Title, BirthDate = @BirthDate, " & _
"MaritalStatus = @MaritalStatus, Gender = @Gender, " & _
"HireDate = @HireDate where " & _
"HumanResources.Employee.EmployeeID = @EmployeeID; ", sqlcon)
sqlcmdEmployee.Transaction = transaction
sqlcmdEmployee.Parameters.Add("@ContactID", _
SqlDbType.Int).Value = contactID
sqlcmdEmployee.Parameters.Add("@EmployeeID", _
SqlDbType.Int).Value = EmployeeID
sqlcmdEmployee.Parameters.Add("@FirstName", _
SqlDbType.VarChar, 50).Value = EmployeeFirstName
sqlcmdEmployee.Parameters.Add("@MiddleName", _

350
The Complete Reference To Professional SOA with Visual Studio 2005

SqlDbType.VarChar, 50).Value = EmployeeMiddleName


sqlcmdEmployee.Parameters.Add("@LastName", _
SqlDbType.VarChar, 50).Value = EmployeeLastName
sqlcmdEmployee.Parameters.Add("@EmailAddress", _
SqlDbType.VarChar, 50).Value = EmailAddress
sqlcmdEmployee.Parameters.Add("@Phone", _
SqlDbType.VarChar, 50).Value = Phone
sqlcmdEmployee.Parameters.Add("@Title", _
SqlDbType.VarChar, 50).Value = Title
sqlcmdEmployee.Parameters.Add("@BirthDate", _
SqlDbType.DateTime).Value = DateTime.Parse(BirthDate)
sqlcmdEmployee.Parameters.Add("@MaritalStatus", _
SqlDbType.VarChar, 50).Value = MaritalStatus
sqlcmdEmployee.Parameters.Add("@Gender", _
SqlDbType.VarChar, 50).Value = Gender
sqlcmdEmployee.Parameters.Add("@HireDate", _
SqlDbType.DateTime).Value = DateTime.Parse(HireDate)
sqlcmdEmployee.ExecuteNonQuery()
transaction.Commit()
Catch ex As Exception
transaction.Rollback()
Throw New Exception(ex.Message)
End Try
End Sub

In listing 9-19 and listing 9-20 we’re providing the functionality to allow the consumer of the Web Service
to update a particular employee’s details. The consumer of the Web Service simply need to pass in an ID of the
employee followed by its details in the form of string parameters. The Web Service will then execute an update
statement on the Sql Server database on the server.
Once the above-mentioned Web methods had been created, we can now build and run our ASP.NET Web
Service application. To build an ASP.NET Web Service application, select Build Solution from the Build menu.
In order to execute the ASP.NET Web Service project, select Start Debugging from the Debug menu.
When launching debugging for the first time we will be prompted whether we wanted to enable debugging.
In this instance we will enable debugging see figure 9-7.

Figure 9-7. Debug diaglog option which will create the Web.config file.

351
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 9-8. Shows the Web Service running

Once the Web Service is started we can see the three WebMethods that we had created earlier,
GetEmployeeByID, GetEmployees, UpdateEmployeeDetailByID see figure 9-8. .NET will also create the test
harness for each of the WebMethod. If we clicked on the links which is represented as the GetEmployeeByID
WebMethod.

352
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 9-9. Test harness for WebMethod

Shows the test harness that was generated around the WebMethod figure 9-9. By entering an EmployeeID
value of 1 we can then invoke this WebMethod to see the result that it produces. The result is shown in figure 9-
10.

Figure 9-10. GetEmployeeByID WebMethod result

Listing 9-21. The result of GetEmployeeByID

<?xml version="1.0" encoding="utf-8"?>


<DataSet xmlns="http://tempuri.org/">
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-
com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Table">
<xs:complexType>
<xs:sequence>
<xs:element name="EmployeeID" type="xs:int" minOccurs="0" />
<xs:element name="FirstName" type="xs:string" minOccurs="0" />
<xs:element name="MiddleName" type="xs:string" minOccurs="0" />
<xs:element name="LastName" type="xs:string" minOccurs="0" />
<xs:element name="EmailAddress" type="xs:string" minOccurs="0" />
<xs:element name="Phone" type="xs:string" minOccurs="0" />
<xs:element name="Title" type="xs:string" minOccurs="0" />

353
The Complete Reference To Professional SOA with Visual Studio 2005

<xs:element name="BirthDate" type="xs:dateTime" minOccurs="0" />


<xs:element name="MaritalStatus" type="xs:string" minOccurs="0" />
<xs:element name="Gender" type="xs:string" minOccurs="0" />
<xs:element name="HireDate" type="xs:dateTime" minOccurs="0" />
<xs:element name="ContactID" type="xs:int" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-
v1">
<NewDataSet xmlns="">
<Table diffgr:id="Table1" msdata:rowOrder="0">
<EmployeeID>1</EmployeeID>
<FirstName>Guy</FirstName>
<MiddleName>R</MiddleName>
<LastName>Gilbert</LastName>
<EmailAddress>[email protected]</EmailAddress>
<Phone>320-555-0195</Phone>
<Title>Production Technician - WC60</Title>
<BirthDate>1972-05-15T00:00:00+10:00</BirthDate>
<MaritalStatus>M</MaritalStatus>
<Gender>M</Gender>
<HireDate>1996-07-31T00:00:00+10:00</HireDate>
<ContactID>1209</ContactID>
</Table>
</NewDataSet>
</diffgr:diffgram>
</DataSet>

From the result in listing 9-21 above we can see the actual values that will be returned by the WebMethod.
In our GetEmployeeByID we returned a dataset from the result returned above we can see that the DataSet is
being returned.

Deploying Web Service


In the last section, we looked at how to create XML Web Services and consume them remotely. After we have
created a XML Web Service, we need to deploy the XML Web Service to a Web server to make it available to
the applications that want to use the XML Web Service. When we deploy an XML Web Service, we publish the
discovery .disco file. The discovery file for an XML Web Service contains information such as the location of
Web Services. Each client that needs to access our XML Web Service uses this file to locate the Web Service.
In the following section, we will examine what we need to perform when deploying and publishing an XML
Web Service. In addition, we will learn about the XML Web Services discovery mechanism and how to
configure discovery information on our XML Web Service.
When we deploy an XML Web Service on a Web server, the service is published on the Web and becomes
accessible to client applications. We can deploy an XML Web Service on a Web server in two ways. We can
either create a Web setup project or we can publish the the XML Web Service files to the Web server. We will

354
The Complete Reference To Professional SOA with Visual Studio 2005

discuss the creation of setup projects in a later chapter. We will now deploy an XML Web Service by publishing
the XML Web Service files to the Web server.

To deploy our XML Web Service on a Web server, perform the following steps:

Click on Build -> Publish Web Site see figure 9-11.

Figure 9-11: Publish Web Site

Figure 9-12. Publish Web Site

Enter the Target Location for the Web Service to be published as http://localhost/soawebservice/deploy/employee
then press the OK button. See figure 9-12 above

After the Web Service has been deployed we can check by browsing to the location
http://localhost/soawebservice/deploy/employee/employee.asmx in our Internet Explorer see figure 9-13 below.

355
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 9-13. Deployed Employee Web Service

We can see the deployed files by browsing to the location in the file explorer see figure 9-14 below.

Figure 9-14. Shows the files created under the deployed Employee Web Service.

When we are publishing to a HTTP location. We could also publish to a UNC share. If we wanted to publish
to a remote Web site using HTTP or FTP, the Target Location box is where we would specify the remote server
URL.
The Allow this precompiled site to be updatable option specifies that all program code is compiled into
assemblies, but that .aspx files (including single-file ASP.NET Web pages) are copied as-is to the target folder
see figure 9-12.

Note: All data in the target folder and its subfolders will be deleted. Make sure that you do not type the name of a folder that contains data

356
The Complete Reference To Professional SOA with Visual Studio 2005

or contains subfolders with data.

Web Service File Types


These are some of the common file types that are used in .NET Web Service.

* AssemblyInfo file, an assembly is the functional unit for sharing and reuse in the common language runtime.
The AssemblyInfo file consists of general information about the assembly in the project. To modify the
assembly information, such as the version number, we can change the attributes in the AssemblyInfo file.
* Web.config file, this file contains configuration information, such as the debug mode and the authentication
mode for a Web project. It also includes information about whether to display custom errors for a Web project.
We can also use the Web.config file to store custom configuration information for our XML Web Service.
* Global.asax and Global.asax.cs or Global.asax.vb files, these files enable us to manage application-level and
session-level events. These files reside in the root directory of an ASP.NET Web application or ASP.NET Web
Service. The Global.asax.cs or Global.asax.vb class file contains the code for handling application events such
as the Application_OnError event. These files when deployed are created as App_global.asax.dll and placed
under the bin directory.

* Service.asmx and the Service.cs or Service.vb files, these two files make up a single XML Web Service. The
Service.asmx file contains the XML Web Service processing directive and serves as the addressable entry point
for the XML Web Service. The Service.cs or Service.vb class file is located under App_Code, dependent file of
WebService.asmx and contains the code-behind class for the XML Web Service.
* WebService.disco, the .disco file is also known as the discovery file. This file is an XML-based file that
contains links or URLs to resources providing discovery information for an XML Web Service.

* The \Bin directory, this directory contains the compiled classes and every referenced assembly for the XML
Web Service.

XML Web Services Discovery Mechanism


The XML Web Service discovery mechanism allows a client application to locate or discover the documents that
describe an XML Web Service. The XML Web Service discovery mechanism returns a service description
document to a client. The service description document is written in Web Services Description Language
(WSDL) and contains information about the capabilities of an XML Web Service, its location, and how to
interact with it. In the XML Web Service discovery process, files, such as service descriptions, XSD schemas, or
discovery documents, which contain the details of an XML Web Service, are downloaded to the client computer.
A discovery document usually defined by the .disco extension defines a document that contains information
and references of resources to the location of the Web Service. This information will help the clients in
discovering the XML Web Service. In the ASP.NET Framework the discovery document is automatically
generated and handled by the .ASMX. We can query a Web Service for its discovery document by adding
“?disco” query at the end of the .asmx address. In the case of accessing the Employee Web Service’s discovery
document we would specify the following address:

http://localhost/soa/AdventureWorks/Employee/Employee.asmx?disco

The generated code is shown in the listing 9-22below.

357
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 9-22. Discovery document

<?xml version="1.0" encoding="utf-8"?>


<discovery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.xmlsoap.org/disco/">
<contractRef ref="http://localhost/soa/AdventureWorks/Employee/Employee.asmx?wsdl"
docRef="http://localhost/soa/AdventureWorks/Employee/Employee.asmx"
xmlns="http://schemas.xmlsoap.org/disco/scl/" />
<soap address="http://localhost/soa/AdventureWorks/Employee/Employee.asmx"
xmlns:q1="http://tempuri.org/" binding="q1:EmployeeSoap"
xmlns="http://schemas.xmlsoap.org/disco/soap/" />
<soap address="http://localhost/soa/AdventureWorks/Employee/Employee.asmx"
xmlns:q2="http://tempuri.org/" binding="q2:EmployeeSoap12"
xmlns="http://schemas.xmlsoap.org/disco/soap/" />
</discovery>

Adding Custom Discovery Information for a Web Service


At design time, the discovery process helps the client application of a Web Service learn about details, such as
the location and capabilities of the Web Service. The discovery mechanism also enables the client to find out
how to interact with the XML Web Service.
A client application can programmatically discover a XML Web Service through a .disco file for the XML
Web Service. By default the XML Web Service will automatically generate the discovery document for us. The
discovery document is automatically generated for an XML Web Service when we access it using a URL with
?DISCO in the query string. For example, if the URL for an XML Web Service is in our case
http://localhost/soa/AdventureWorks/Employee/Employee.asmx, a discovery document is automatically generated
with http://localhost/soa/AdventureWorks/Employee/Employee.asmx?disco as the URL. To configure discovery
information for an XML Web Service, perform the following steps:

1. Create an XML document and insert the <?xml version="1.0" ?> tag in the first line.

2. Add a <discovery> element, such as:

<discovery xmlns="http://schemas.xmlsoap.org/disco/"></discovery>

3. Add references to service descriptions, XSD schemas, and other discovery documents within the <discovery>
element as displayed in the following code:

<?xml version="1.0"?>
<discovery xmlns="http://schemas.xmlsoap.org/disco/">
<discoveryRef ref="/Folder/Default.disco"/>
<contractRef ref=" http://localhost/soa/AdventureWorks/Employee/Employee.asmx?WSDL"
docRef="Service.htm"
xmlns="http://schemas.xmlsoap.org/disco/scl/"/>
<schemaRef ref="Schema.xsd"
xmlns="http://schemas.xmlsoap.org/disco/schema/"/>
</discovery>

4. Then deploy the discovery document to a location on the Web server.

358
The Complete Reference To Professional SOA with Visual Studio 2005

After we have specified the discovery information for our XML Web Service and have published the
discovery file, users can browse the discovery file to locate our XML Web Service.
After a client application discovers a Web Service, the client application can access and use all the exposed
methods of a Web Service. The process of using an exposed method of a Web Service is known as consuming a
Web Service.

Consuming Web Service


To consume the Web Service with Visual Studio 2005 is quite easy. In the following section we will create a
sample windows application that will consume the Web Services that we had earlier and help us maintain the
employee information within the system.
We will now create a windows application that will act as the client to access our Web Services that we had
built earlier. Web Services are very flexible and robust they can be accessed by any application that uses SOAP
to communicate with it. It is also possible to use HTTP POST, and GET to execute a Web Service.

Figure 9-15: Create a new windows application.

To create a new windows project in Visual Studio 2005 select File -> New -> Project. This will bring up a
new project dialog window. In the New Project window select the language that we want to use and select
Windows Application from the Templates. Specify the name of the project as EmployeeClient and select a
location for the project. Then click OK see figure 9-15.

359
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 9-16: Add a reference to the Web Service

Tip: If the Web References node under the project cannot be seen the same result can be achieved by right clicking the project and
selecting Add Web Reference.

We need to add a Web Reference to the Web Service that we had created earlier. It is just a way for the
application to know where to execute the Web Service at. In Visual Studio 2005 by adding a Web Reference to
the Web Service Visual Studio also automatically generate the proxy class for us. To add a reference in Solution
Explorer. Right click on the Windows Project right mouse click and select “Add Web Reference”.

Figure 9-17: Add Web Reference

In Listing 9-17 above we’re adding a reference to the Web Service. By simply entering the location of the
Web Service asmx press the Go button. We should be able to see the Employee Web Service and its

360
The Complete Reference To Professional SOA with Visual Studio 2005

WebMethods. Then we need to give it a reference name. In this case we will call it WSEmployee. Once
complete select Add Reference.

Figure 9-18: Solution explorer

Tip : Click the Show All Files button within the Solution Explorer window to display other files under the WSEmployee node.

In figure 9-18 we can see that the reference to the Web Service was added onto the windows application. By
adding the reference Visual Studio 2005 has also created some files for us. These are the Employee.disco,
Employee.wsdl, Reference.map and Reference.cs.
Employee.disco, this file contains information which is used by Visual Studio for its discovery purposes. The
discovery file helps to provide location of useful resources as well as contain details about the different forms of
bindings that can be used against the XML Web Service. The content of the Employee.disco is shown in the
listing 9-23below.

Listing 9-23. Employee.disco

<?xml version="1.0" encoding="utf-8"?>


<discovery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.xmlsoap.org/disco/">
<contractRef
ref="http://localhost/soa/AdventureWorks/Employee/Employee.asmx?wsdl"
docRef="http://localhost/soa/AdventureWorks/Employee/Employee.asmx"
xmlns="http://schemas.xmlsoap.org/disco/scl/" />
<soap
address="http://localhost/soa/AdventureWorks/Employee/Employee.asmx"
xmlns:q1="http://tempuri.org/" binding="q1:EmployeeSoap"
xmlns="http://schemas.xmlsoap.org/disco/soap/" />
<soap
address="http://localhost/soa/AdventureWorks/Employee/Employee.asmx"
xmlns:q2="http://tempuri.org/" binding="q2:EmployeeSoap12"
xmlns="http://schemas.xmlsoap.org/disco/soap/" />
</discovery>

361
The Complete Reference To Professional SOA with Visual Studio 2005

Employee.wsdl, the wsdl file contains the Web Service Description Language for the Employee Web Service. A
.wsdl file is essentially the interface for the Web Service it describes the methods that are available to be
consumed as well as the parameter and its datatype that’s required for each method. The .wsdl file is itself
described by a XML grammar see listing 9-24.

Listing 9-24. Demonstrates the Employee.wsdl file

<?xml version="1.0" encoding="utf-8"?>


<wsdl:definitions
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:tns="http://tempuri.org/" xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
targetNamespace="http://tempuri.org/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<s:schema elementFormDefault="qualified"
targetNamespace="http://tempuri.org/">
<s:element name="GetEmployees">
<s:complexType />
</s:element>
<s:element name="GetEmployeesResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="GetEmployeesResult">
<s:complexType>
<s:sequence>
<s:element ref="s:schema" />
<s:any />
</s:sequence>
</s:complexType>
</s:element>
</s:sequence>
</s:complexType>
</s:element>
<s:element name="GetEmployeeByID">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1"
name="EmployeeID" type="s:int" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="GetEmployeeByIDResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1"
name="GetEmployeeByIDResult">
<s:complexType>
<s:sequence>

362
The Complete Reference To Professional SOA with Visual Studio 2005

<s:element ref="s:schema" />


<s:any />
</s:sequence>
</s:complexType>
</s:element>
</s:sequence>
</s:complexType>
</s:element>
<s:element name="UpdateEmployeeDetailByID">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="EmployeeID"
type="s:int" />
<s:element minOccurs="0" maxOccurs="1" name="EmployeeFirstName"
type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="EmployeeMiddleName"
type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="EmployeeLastName"
type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="EmailAddress"
type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="Phone"
type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="Title"
type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="BirthDate"
type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="MaritalStatus"
type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="Gender"
type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="HireDate"
type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="UpdateEmployeeDetailByIDResponse">
<s:complexType />
</s:element>
</s:schema>
</wsdl:types>
.
.

Reference.map, this file contains an XML mapping to the WSDL file. If we expand the Reference.Map node we
can see a Reference.cs or a Reference.vb file nested underneath the mapping. This file is known as the proxy.
The proxy is a WSDL to code mapping. The mapping allows us to invoke methods that are exposed by the
WSDL by invoking .NET code see listing 9-25below.

Listing 9-25. Demonstrates the Reference.map file

<?xml version="1.0" encoding="utf-8"?>


<DiscoveryClientResultsFile

363
The Complete Reference To Professional SOA with Visual Studio 2005

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Results>
<DiscoveryClientResult
referenceType="System.Web.Services.Discovery.DiscoveryDocumentReference"
url="http://localhost/soa/AdventureWorks/Employee/Employee.asmx?disco"
filename="Employee.disco" />
<DiscoveryClientResult
referenceType="System.Web.Services.Discovery.ContractReference"
url="http://localhost/soa/AdventureWorks/Employee/Employee.asmx?wsdl"
filename="Employee.wsdl" />
</Results>
</DiscoveryClientResultsFile>

Reference.cs, this is the proxy file which contains the mapped WSDL in .NET code class. It allows a .NET client
to invoke methods on the XML Web Service over the network. It also handles the SOAP encoding and decoding
as messages are sent to and from the XML Web Service see listing 9-26 for reference.cs and listing 9-27 for
reference.vb. The code generated for the proxy is quite lengthy for our purpose only the
UpdateEmployeeDeatilByID() is shown.

Listing 9-26. UpdateEmployeeDetailByID method contained in the Reference.cs when using Visual C#

.
.
[System.Web.Services.Protocols.SoapDocumentMethodAttribute(
"http://tempuri.org/UpdateEmployeeDetailByID",
RequestNamespace="http://tempuri.org/",
ResponseNamespace="http://tempuri.org/",
Use=System.Web.Services.Description.SoapBindingUse.Literal,
ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public void UpdateEmployeeDetailByID(int EmployeeID,
string EmployeeFirstName, string EmployeeMiddleName,
string EmployeeLastName, string EmailAddress, string Phone,
string Title, string BirthDate, string MaritalStatus,
string Gender, string HireDate) {
this.Invoke("UpdateEmployeeDetailByID", new object[] {
EmployeeID,
EmployeeFirstName,
EmployeeMiddleName,
EmployeeLastName,
EmailAddress,
Phone,
Title,
BirthDate,
MaritalStatus,
Gender,
HireDate});
}
.
.

364
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 9-27. UpdateEmployeeDetailByID method contained in the Reference.vb when using Visual Basic .NET

.
.
Public Sub UpdateEmployeeDetailByID(ByVal EmployeeID As Integer, _
ByVal EmployeeFirstName As String, ByVal EmployeeMiddleName As String, _
ByVal EmployeeLastName As String, ByVal EmailAddress As String, _
ByVal Phone As String, ByVal Title As String, ByVal BirthDate As String, _
ByVal MaritalStatus As String, ByVal Gender As String, _
ByVal HireDate As String)
Me.Invoke("UpdateEmployeeDetailByID", New Object() { _
EmployeeID, EmployeeFirstName, EmployeeMiddleName, EmployeeLastName, _
EmailAddress, Phone, Title, BirthDate, MaritalStatus, Gender, HireDate})
End Sub
.
.

The proxy file can be created automatically when we use Visual Studio’s “Add Web Reference” option to a
XML Web Service. We can also generate the proxy file using the command line utility wsdl.exe in the .NET
Framework. We can access the wsdl.exe utility through the Visual Studio 2005 Command Prompt where the
environment variables are setup for us to use within the command window.
To use the wsdl.exe tool we need to pass the location of the WSDL file to the tool. The tool by default will
generate visual C# proxy. The proxy can then be used to invoke the Web Service.
wsdl http://localhost/soa/AdventureWorks/Employee/Employee.asmx?wsdl

We can also specify a particular file name by using the /out: parameter :
wsdl /out:ReferenceProxy.cs http://localhost/soa/AdventureWorks/Employee/Employee.asmx?wsdl

For VB.NET users we can generate VB proxy by using the /language parameter. The following syntax will
create a VB proxy file called myProxyClass.vb.
wsdl /language:VB /out:myProxyClass.vb http://localhost/soa/AdventureWorks/Employee/Employee.asmx?wsdl

Client Application
Once the reference has been added and the proxy class to the Web Service was created. We can now start on our
windows application to access the Web Service we have created earlier. In this instance we will be creating a
windows application. We will need to create the user interface for the application first.

365
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 9-19: Employee Management Client

Figure 9-19 shows the user interface for our windows application we will be creating to call on our Web Service.

1. To create the user interface first, select GroupBox from the Toolbox window. To add a GroupBox on to the
Windows form we could either double click on the GroupBox component or drag and drop the GroupBox
component onto the Windows form.

2. Select the text of the GroupBox right click and select properties

3. Change the Text property of the GroupBox to “Get Employee Details”

4. Next drag and drop a Label control from the Toolbox window onto the GroupBox.

5. Right click on the label select properties and change the Text property to “Employee ID”.

6. Select a TextBox control from the Toolbox window and drag and drop the control onto the “Get Employee
Details” GroupBox.

7. Right Click on the new TextBox and select properties. Change the name property to “textBoxGetEmployeeID”
8. Select a Button control from the Toolbox and drag and drop the control onto the “Get Employee Details”
GroupBox.

9. Right click on the new Button control select properties and change the Text of the button to “Get Employee”
and change the Name property of the control to “buttonGetEmployee”.

10. Select another Button control from the Toolbox and drag and drop the control onto the “Get Employee Details”
GroupBox.
11. Right click on the new Button control select properties and change the Text of the button to “Get All
Employees” and change the Name property of the control to “buttonGetAllEmployees”.

366
The Complete Reference To Professional SOA with Visual Studio 2005

Now we should have a user interface that look like figure 9-20 below.

Figure 9-20. User Interface

1. Now we need to create a second GroupBox. To do this select the GroupBox control from the Toolbox window
and drag and drop the control onto the Windows form. Right click on the group box to select properties.
Change the Text property of the GroupBox to “Update Employee Details”.

2. Select a Label control and drag and drop the control into the “Update Employee Details” GroupBox. Change
the Text property for the Label control to “Employee ID”.

3. Select a TextBox control from the Toolbox window and drag and drop the control onto the “Update Employee
Details” GroupBox next to the new Label.
4. Right Click on the new TextBox and select properties. Change the Name property to “textBoxEmployeeID”

5. Select another Label control and drag and drop the control into the “Update Employee Details” GroupBox.
Change the Text property for the Label control to “First Name”.

6. Select a TextBox control from the Toolbox window and drag and drop the control onto the “Update Employee
Details” GroupBox next to the new Label.
7. Right Click on the new TextBox and select properties. Change the Name property to “textBoxFirstName”

8. Select another Label control and drag and drop the control into the “Update Employee Details” GroupBox.
Change the Text property for the Label control to “Middle Name”.

9. Select a TextBox control from the Toolbox window and drag and drop the control onto the “Update Employee
Details” GroupBox next to the new Label.

10. Right Click on the new TextBox and select properties. Change the Name property to “textBoxMiddleName”
11. Select another Label control and drag and drop the control into the “Update Employee Details” GroupBox.
Change the Text property for the Label control to “Last Name”.

12. Select a TextBox control from the Toolbox window and drag and drop the control onto the “Update Employee
Details” GroupBox next to the new Label.

13. Right Click on the new TextBox and select properties. Change the Name property to “textBoxLastName”

14. Select another Label control and drag and drop the control into the “Update Employee Details” GroupBox.
Change the Text property for the Label control to “Email Address”.

15. Select a TextBox control from the Toolbox window and drag and drop the control onto the “Update Employee
Details” GroupBox next to the new Label.
16. Right Click on the new TextBox and select properties. Change the Name property to “textBoxEmailAddress”

367
The Complete Reference To Professional SOA with Visual Studio 2005

17. Select another Label control and drag and drop the control into the “Update Employee Details” GroupBox.
Change the Text property for the Label control to “Phone”.

18. Select a TextBox control from the Toolbox window and drag and drop the control onto the “Update Employee
Details” GroupBox next to the new Label.
19. Right Click on the new TextBox and select properties. Change the Name property to “textBoxPhone”
20. Select another Label control and drag and drop the control into the “Update Employee Details” GroupBox.
Change the Text property for the Label control to “Title”.

21. Select a TextBox control from the Toolbox window and drag and drop the control onto the “Update Employee
Details” GroupBox next to the new Label.

22. Right Click on the new TextBox and select properties. Change the Name property to “textBoxTitle”

23. Select another Label control and drag and drop the control into the “Update Employee Details” GroupBox.
Change the Text property for the Label control to “Marital Status”.

24. Select a TextBox control from the Toolbox window and drag and drop the control onto the “Update Employee
Details” GroupBox next to the new Label.

25. Right Click on the new TextBox and select properties. Change the Name property to “textBoxMaritalStatus”

26. Select another Label control and drag and drop the control into the “Update Employee Details” GroupBox.
Change the Text property for the Label control to “Gender”.

27. Select a TextBox control from the Toolbox window and drag and drop the control onto the “Update Employee
Details” GroupBox next to the new Label.
28. Right Click on the new TextBox and select properties. Change the Name property to “textBoxGender”

29. Select another Label control and drag and drop the control into the “Update Employee Details” GroupBox.
Change the Text property for the Label control to “Birth Date”.

30. We need to add a DateTimePicker to the window. Select the DateTimePicker control from Toolbox and drag
and drop the control onto the “Update Employee Details” GroupBox.

31. Right Click on the new DateTimePicker and select properties. Change the Name property to
“dateTimePickerBirthDate”

32. In the DateTimePicker control set the CustomFormat “yyyy-MM-dd”. This will give us a datetime format of
year-month-day.

33. Select another Label control and drag and drop the control into the “Update Employee Details” GroupBox.
Change the Text property for the Label control to “Hire Date”.

34. Add another DateTimePicker to the window. Select the DateTimePicker control from Toolbox and drag and
drop the control onto the “Update Employee Details” GroupBox.

35. Right Click on the new DateTimePicker and select properties. Change the Name property to
“dateTimePickerHireDate”

368
The Complete Reference To Professional SOA with Visual Studio 2005

36. In the DateTimePicker control set the CustomFormat “yyyy-MM-dd”. This will give us a datetime format of
year-month-day.

37. Select another Button control from the Toolbox and drag and drop the control onto the “Update Employee
Details” GroupBox.
38. Right click on the new Button control select properties and change the Text of the button to “Update” and
change the Name property of the control to “buttonUpdate”.

39. Right click on the Windows Form and select properties. Change the Text Property for the windows form to
“CS Employee Client” or “VB Employee Client” accordingly.
Now we should have a user interface that look like figure 9-21 below.

Figure 9-21. User interface so far.

To display the result we will be using a DataGridView. A DataGridView is a control that can display result in a
table format so we can see all the information.
To add a DataGridView select the DataGridView control from Toolbox and drag and drop into the windows form.

Select the Name property of the DataGridView and change it to “dataGridViewEmployee”

With the datagrid the windows form should look something similar to figure 9-22 below.

369
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 9-22. The user interface

To access the methods within a Web Service we must first create an object of the Web Service. Since we
had named our Web Service in an earlier figure 9-17 as WSEmployee.

Listing 9-28. Creating the Proxy in Visual C#

WSEmployee.Employee wsEmployee = new WSEmployee.Employee();

Listing 9-29. Creating the Proxy in Visual Basic .NET

Private wsEmployee As WSEmployee.Employee = New WSEmployee.Employee

Behind each button is an event that is fired when the button is pressed. Visual Studio 2005 will
automatically generate the event for us. To create these events simply double click on the button control that
we’re interested in.

Listing 9-30. Implementing Update button event using Visual C#

private void buttonUpdate_Click(object sender, EventArgs e)


{
wsEmployee.UpdateEmployeeDetailByID(
int.Parse(this.textBoxEmployeeID.Text), this.textBoxFirstName.Text,
this.textBoxMiddleName.Text, this.textBoxLastName.Text,
this.textBoxEmailAddress.Text, this.textBoxPhone.Text,
this.textBoxTitle.Text, this.dateTimePickerBirthDate.Text,
this.textBoxMaritalStatus.Text, this.textBoxGender.Text,
this.dateTimePickerHireDate.Text);
}

Listing 9-31. Implementing Update button event using Visual Basic .NET

370
The Complete Reference To Professional SOA with Visual Studio 2005

Private Sub buttonUpdate_Click(ByVal sender As Object, ByVal e As EventArgs)


wsEmployee.UpdateEmployeeDetailByID(Integer.Parse(Me.textBoxEmployeeID.Text), _
Me.textBoxFirstName.Text, Me.textBoxMiddleName.Text, Me.textBoxLastName.Text, _
Me.textBoxEmailAddress.Text, Me.textBoxPhone.Text, Me.textBoxTitle.Text, _
Me.dateTimePickerBirthDate.Text, Me.textBoxMaritalStatus.Text, _
Me.textBoxGender.Text, Me.dateTimePickerHireDate.Text)
End Sub

In listing 9-30 and listing 9-31 above, we’re shown the button event for the Update button which when
clicked will call on the UpdateEmployeeDetailByID WebMethod from our Web Service. We’re then passing the
required parameters to the Web Service. We don’t have to worry about the serialization aspect of the call as
.NET takes care of it for us.
By invoking the Web Service function the proxy takes care of composing the SOAP request it will also
takecare of the SOAP response from the Web Service.
The format of the request being sent by the proxy is shown in the listing 9-32 below. The SOAP response
format is shown in listing 9-33 below. The SOAP request and response is not something that we need to concern
with as it is automatically handled by the Web Service proxy it is added here for additional information so that
we have an idea what is sent and what is receieved upon each request and response.

Listing 9-32. SOAP 1.1 request

POST /soawebservice/deploy/employee/employee.asmx HTTP/1.1


Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/UpdateEmployeeDetailByID"

<?xml version="1.0" encoding="utf-8"?>


<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<UpdateEmployeeDetailByID xmlns="http://tempuri.org/">
<EmployeeID>int</EmployeeID>
<EmployeeFirstName>string</EmployeeFirstName>
<EmployeeMiddleName>string</EmployeeMiddleName>
<EmployeeLastName>string</EmployeeLastName>
<EmailAddress>string</EmailAddress>
<Phone>string</Phone>
<Title>string</Title>
<BirthDate>string</BirthDate>
<MaritalStatus>string</MaritalStatus>
<Gender>string</Gender>
<HireDate>string</HireDate>
</UpdateEmployeeDetailByID>
</soap:Body>
</soap:Envelope>

Listing 9-33. SOAP 1.1 response

371
The Complete Reference To Professional SOA with Visual Studio 2005

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>


<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<UpdateEmployeeDetailByIDResponse xmlns="http://tempuri.org/" />
</soap:Body>
</soap:Envelope>

In listing 9-34 and listing 9-35 below we’re shown the button event for GetAllEmployees which when
clicked invokes the GetEmployees() WebMethod. This WebMethod returns a DataSet which contains our data
table. We then use this to populate the DataGridView with it.

Listing 9-34. Implementing GetAllEmployees Event using Visual C#

private void buttonGetAllEmployees_Click(object sender, EventArgs e)


{
DataSet dsEmployees = wsEmployee.GetEmployees();
this.dataGridViewEmployee.DataSource = dsEmployees.Tables[0];
}

Listing 9-35. Implementing GetAllEmployees Event using Visual Basic .NET

Private Sub buttonGetAllEmployees_Click(ByVal sender As Object, _


ByVal e As EventArgs)
Dim dsEmployees As DataSet = wsEmployee.GetEmployees
Me.dataGridViewEmployee.DataSource = dsEmployees.Tables(0)
End Sub

The format of the request being sent by the proxy is shown in the listing 9-36 below. The SOAP response
format is shown in listing 9-37 below. Again the SOAP request and response is not something that we need to
concern with as it is automatically handled by the Web Service proxy it is added here for additional information
so that we have an idea what is sent and what is receieved upon each request and response.

Listing 9-36. SOAP 1.1 request

POST /soawebservice/deploy/employee/employee.asmx HTTP/1.1


Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/GetEmployees"

<?xml version="1.0" encoding="utf-8"?>


<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetEmployees xmlns="http://tempuri.org/" />
</soap:Body>
</soap:Envelope>

372
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 9-37. SOAP 1.1 response

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>


<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetEmployeesResponse xmlns="http://tempuri.org/">
<GetEmployeesResult>
<xsd:schema>schema</xsd:schema>xml</GetEmployeesResult>
</GetEmployeesResponse>
</soap:Body>
</soap:Envelope>

In listing 9-38 and listing 9-39 below we’re shown the button event for GetEmployee button click. When
this button is clicked the GetEmployeeByID() WebMethod of the Web Service is invoked. This in turn returns a
dataset with the values of the specified employee.

Listing 9-38. Implementing GetEmployee using Visual C#

private void buttonGetEmployee_Click(object sender, EventArgs e)


{
DataSet dsEmployee = wsEmployee.GetEmployeeByID(
int.Parse(this.textBoxEmployeeID.Text));
this.dataGridViewEmployee.DataSource = dsEmployee.Tables[0];

this.textBoxEmployeeID.Text = dsEmployee.Tables[0].Rows[0]
["EmployeeID"].ToString();
this.textBoxFirstName.Text = dsEmployee.Tables[0].Rows[0]
["FirstName"].ToString();
this.textBoxMiddleName.Text = dsEmployee.Tables[0].Rows[0]
["MiddleName"].ToString();
this.textBoxLastName.Text = dsEmployee.Tables[0].Rows[0]
["LastName"].ToString();
this.textBoxEmailAddress.Text = dsEmployee.Tables[0].Rows[0]
["EmailAddress"].ToString();
this.textBoxPhone.Text = dsEmployee.Tables[0].Rows[0]
["Phone"].ToString();
this.textBoxTitle.Text = dsEmployee.Tables[0].Rows[0]
["Title"].ToString();
this.dateTimePickerBirthDate.Text = dsEmployee.Tables[0].Rows[0]
["BirthDate"].ToString();
this.textBoxMaritalStatus.Text = dsEmployee.Tables[0].Rows[0]
["MaritalStatus"].ToString();
this.textBoxGender.Text = dsEmployee.Tables[0].Rows[0]
["Gender"].ToString();
this.dateTimePickerHireDate.Text = dsEmployee.Tables[0].Rows[0]
["HireDate"].ToString();

373
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 9-39. Implementing GetEmployee using Visual Basic .NET

Private Sub buttonGetEmployee_Click(ByVal sender As Object, _


ByVal e As EventArgs)
Dim dsEmployee As DataSet = wsEmployee.GetEmployeeByID( _
Integer.Parse(Me.textBoxEmployeeID.Text))
Me.dataGridViewEmployee.DataSource = dsEmployee.Tables(0)
Me.textBoxEmployeeID.Text = dsEmployee.Tables(0) _
.Rows(0)("EmployeeID").ToString()
Me.textBoxFirstName.Text = dsEmployee.Tables(0) _
.Rows(0)("FirstName").ToString
Me.textBoxMiddleName.Text = dsEmployee.Tables(0) _
.Rows(0)("MiddleName").ToString
Me.textBoxLastName.Text = dsEmployee.Tables(0) _
.Rows(0)("LastName").ToString
Me.textBoxEmailAddress.Text = dsEmployee.Tables(0) _
.Rows(0)("EmailAddress").ToString
Me.textBoxPhone.Text = dsEmployee.Tables(0) _
.Rows(0)("Phone").ToString
Me.textBoxTitle.Text = dsEmployee.Tables(0) _
.Rows(0)("Title").ToString
Me.dateTimePickerBirthDate.Text = dsEmployee.Tables(0) _
.Rows(0)("BirthDate").ToString
Me.textBoxMaritalStatus.Text = dsEmployee.Tables(0) _
.Rows(0)("MaritalStatus").ToString
Me.textBoxGender.Text = dsEmployee.Tables(0) _
.Rows(0)("Gender").ToString
Me.dateTimePickerHireDate.Text = dsEmployee.Tables(0) _
.Rows(0)("HireDate").ToString
End Sub

The format of the request being sent by the proxy to invoke the GetEmployeeByID() WebMethod is shown
in the listing 9-40 below. The SOAP response format is shown in listing 9-41 below.

Listing 9-40. SOAP 1.1 request

POST /soawebservice/deploy/employee/employee.asmx HTTP/1.1


Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/GetEmployeeByID"

<?xml version="1.0" encoding="utf-8"?>


<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetEmployeeByID xmlns="http://tempuri.org/">
<EmployeeID>int</EmployeeID>
</GetEmployeeByID>
</soap:Body>

374
The Complete Reference To Professional SOA with Visual Studio 2005

</soap:Envelope>

Listing 9-41. SOAP 1.1 response

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>


<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetEmployeeByIDResponse xmlns="http://tempuri.org/">
<GetEmployeeByIDResult>
<xsd:schema>schema</xsd:schema>xml</GetEmployeeByIDResult>
</GetEmployeeByIDResponse>
</soap:Body>
</soap:Envelope>

The result of the execution can be seen in figure 9-23 and figure 9-24 below.

Figure 9-23. Result of executing Get Employee to retrieve employee information.

375
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 9-24. Result from executing Get All Employees.

Summary
XML Web Service allows us to build scalable, loosely coupled, platform-independent applications. XML Web
Services enable disparate applications to exchange messages using standard protocols such as HTTP, XML,
XSD, SOAP, and WSDL.
In this chapter we have created an XML Web Service that provide specific functionality to the client
applications over the Web. The Visual Studio 2005 IDE provides us with the environment that are needed to
create projects for distributed desktop applications, Web applications, and XML Web Services.
In this chapter we have also looked at deploying the XML Web Service to a Web server to make it available
to the applications that want to use the XML Web Service. We can deploy an XML Web Service to a Web server
by simply using the Publish Web Site function that’s available within Visual Studio 2005 which will allow us to
deploy to a HTTP location. We could also publish to a UNC share or a remote Web site using HTTP or FTP.
The XML Web Service discovery mechanism enables a client application to locate or discover the
documents that describe an XML Web Service. The XML Web Service discovery mechanism returns a service
description document to a client. The service description document is written in WSDL and contains information
about the capabilities of the XML Web Service, its location, and how to interact with it.
After we create an XML Web Service and publish it, any application having permission to access it can
access our XML Web Service and consume its services. The application that consumes a Web Service is known
as the Web Service client or Web Service consumer. A Web Service client can be a windows application, a web
based application or a mobile application. This is because Web Services are interoperable through open
standards.

376
The Complete Reference To Professional SOA with Visual Studio 2005

Chapter 10 Testing and


Debugging an XML Web
Service
Using XML Web services to implement SOA is widely accepted in IT architectures today. Developers who
implement XML Web service need to ensure their functionality is operational at all times through active and
aggressive testing. Comprehensive functional, performance, interoperability, and vulnerability testing form the
pillars of SOA testing. Only through vigorous and comprehensive testing can an enterprise ensure that their SOA
is robust, scalable, interoperable and secure.
Today, Web services have helped to blur the boundaries between network devices, security products,
applications and other IT assets within an enterprise. Almost every IT asset can advertise its interface through a
Web Services Definition Language (WSDL). This allows a distributed consuming application to easily consume
the Web service using SOAP/XML messaging. Web services interface for the first time helped to provide
unprecedented flexibility in application integration. Such flexibility makes it the responsibility of IT staff from
all domains such as developers, network engineers, security & compliance officers, and application quality
assurance (QA) testers to ensure that their Web services work as advertised.
In this chapter we will be looking into how to test and analyze Web services with Visual Studio as well as
looking at some of the internal features of Visual Studio Team System for Developers’ test functionality. We
will also be learning about testing and why a testing phase should be implemented as part of the software
development life cycle. In addition, we will learn about various types of testing.

Overview of the Testing Process


When we develop an application, in addition to meeting the requirements of a customer, we must ensure that the
application is defect-free. Therefore, we need to perform various levels of testing on the application. Testing
accomplishes a number of tasks, such as checking whether the desired functionality is implemented and working.
However, the most important aspect that testing measures is to ensure the quality of the application that we are
developing.
For a long time, creating error-free applications has been a high-priority for many organizations. In fact,
organizations implement the testing phase as part of their application development life cycle. The following
factors contribute to the importance of testing:

* Testing reduces the cost of developing an application. The cost of rectifying an error after an application has
been created is much more than the cost of implementing a thorough testing process as part of the development
life cycle.

* Testing ensures that our application performs as specified. In most cases, if testing is not implemented, we
cannot actually predict the output of a certain operation.

* Testing reduces the total cost of ownership. If a software application functions exactly as described in the
documentation, users require fewer hours of training and less support from product experts.

377
The Complete Reference To Professional SOA with Visual Studio 2005

* Testing develops customer loyalty and word-of-mouth market share. We are more likely to build a strong
customer base with high-quality, bug-free software, which only thorough testing can provide.

To ensure that our application is free of defects and bugs, we can subject our applications to the following
types of testing see Table 10-1:

Table 10-1: Testing Types

Testing Type Description

Requirements testing This is where we perform testing to verify whether our application meets the
requirements as specified in the software specification.

Usability testing We perform usability testing to test the usability and ease of use of our application.
During usability testing, we perform checks to ensure that all the information that
users require is provided by the application. In addition, we also perform tests to
ensure that the user interface is easily navigable.

Unit testing During unit testing, we take the smallest unit of an application usually a method
within a module and test it to ensure that it functions as expected. This ensures the
quality of each function before they’re integrated onto the server.
During integration testing, we combine the functions that had already been
Integration testing
tested through our unit testing phase into a component and test the interface
that combines the two units. We then combine them into components, test
the components, and integrate them into modules. The various modules are
then tested and integrated into an application.

Regression testing We perform regression testing to ensure that any change made to code that has
already been tested does not break the code. We can perform regression testing by
executing the existing tests on the modified code or by creating new tests for the
modified code, if necessary.

Organizing the Testing Effort


The earlier we incorporate testing into an application's development process, the better our chances are for
producing a defect-free application. We need to organize our testing effort carefully so that it is efficient and
effective.
It is advisable to develop an application in modules. The modular format enables us to plan for testing the
modules separately. This ensures that when the individual modules are arranged in the final application, the
entire application is error-free.
The testing process involves testing module interaction and not module execution. Planning is crucial to a
successful testing effort because it sets expectations about the outcome of the application's development life
cycle. We should also consider the cost, schedule, and performance of the application in test plans. This
increases the probability of a successful, effective, and efficient testing process.

Requirements-Based Testing
The first phase of the software development life cycle involves gathering and analyzing requirements. The
requirements phase provides the application's necessary features. Requirements also provide the basis for all

378
The Complete Reference To Professional SOA with Visual Studio 2005

types of testing. Based on the descriptions in the requirement specification, testing identifies defects that create,
cause, or allow unpredictable behavior in the software. Therefore, the test team should also be involved in the
specification-writing process.
We should design our test cases while writing the requirements specifications. A test case consists of sample
data and its corresponding output, which is calculated manually. To design test cases, we need to analyze each
specification and determine how well the requirement supports the development of test cases. Developing a test
case ensures that we will critically analyze the requirement specifications.

Developing a Test Plan


A test plan outlines the entire testing process and includes the individual test cases. A test case includes sample
data that is included in the application. The sample data is passed to the application, and the output is verified.
To develop a reliable test plan, we must systematically explore the program to ensure that we cover all the
modules thoroughly. A formal test plan establishes a testing process that does not depend upon accidental,
random testing.

Approaches to Develop Test Plans


There are two common approaches to testing: the waterfall approach and the evolutionary approach.

The Waterfall Approach


The waterfall approach to application development and testing consists of various phases, which cover
requirements analysis, design and specifications requirements, coding, final testing, and release. Before we begin
working on a phase, the work in the preceding phase must have been completed. To the testing team, this means
waiting for a final specification and then following the pattern set by the development team. A significant
disadvantage of this approach is that it eliminates the opportunity for testing to identify problems early in the
process; therefore, this approach is best suited for small projects of limited complexity.

The Evolutionary/Agile Approach


In the evolutionary approach, we develop a modular piece or unit of an application, test it, fix it, and then add
another small piece that adds functionality. We then test the two units as an integrated component, increasing the
complexity as we proceed. Some of the advantages to this approach are:

* Low-cost opportunities to reappraise requirements and refine the design, as we understand the application
better.

* Consistently deliver a working, useful product. If we add functionality in priority order, we can stop
development at any time.
* Rather than developing one lengthy test plan, we can start with small, modular pieces of the final test plan. In
the interim period, we can use the smaller pieces of the plan to locate bugs.
* We can add new sections to the test plan, explore new areas, and use each part of the plan.

The Four Pillars of Successful Testing


We can use traditional software development testing methods to test and validate our XML Web services when
developing towards SOA. There are four main areas in testing which are vital for the successful implementation of

379
The Complete Reference To Professional SOA with Visual Studio 2005

SOA. These are: functional and regression testing, performance, interoperability, and vulnerability assessment see
figure 10-1.
There are four pillars of successful testing, as shown in Figure 10-1.

Figure 10-1: The four pillars of successful testing

Pillar I: Functional & Regression Testing


Functional and regression testing is the first line of defense against human error. It is thus the first pillar and one
that we must focus on first. As developers or system integrators we need to quickly setup regression test cases
that will allow us to test the changes that had just been implemented. Gaining the habit of setting up simple test
cases is paramount to lowering potential issues later on. Later in this chapter we will learn to setup simple test
case management to help us automate testing using Visual Studio this will help to lower the time required to
execute test cases and provide a more reliable means of validating functionalities.

Pillar II: Performance


The second pillar of successful testing is performance testing. Performance testing is often neglected by
application developers and system integrators. Systems are often only tested with functional and regression
testing. It is only after the system has been deployed into production performance bottlenecks become evident.
Bottlenecks can be quite serious and they can easily bring enterprise systems to a crunching halt. Developers
should always test Web services changes for scalability and robustness and ensure performance characteristics.
Testers should determine response times, latency and throughput profiles for the targeted Web service. In
addition testers should stress test the implementation by specifying duration for measuring endurance and
robustness. We can also determine the scalability of a Web service by sending varying SOAP messages.

Pillar III: Interoperability


The third pillar is ensuring interoperability of our changes with the rest of the application architecture. We can
validate interoperability by testing the application for both design-time and runtime characteristics for the
selected Web service. Developers can run a series of comprehensive Web Service Interoperability (WSI) profile
tests and report interoperability issues with the Web service WSDL. Ensuring interoperability is important
especially in architectures where more than one technology is used for example a Java or C++ application may
require consuming the Web service. These tests validates the selected Web service for interoperability by
sending specialized requests to the Web services to determine whether the Web services complies to the WSI
Profile specification.

380
The Complete Reference To Professional SOA with Visual Studio 2005

Pillar IV: Vulnerability Assessment


The last pillar is perhaps one of the most important and crucial to testing of them all and that is vulnerability
assessment. If not assessed properly an organization can easily lose client financial information leading to
depriving the organization of reputation and eventually business. Vulnerability assessment is very important in
an open architecture such as the case of SOA. We need to vigorously test the Web services that we expose to
ensure that there are no possible means available of performing actions that it was not designed to perform. In
the past I have seen people breaking into databases through very simple SQL statements. This was only made
possible by the developer who had carelessly given himself system administrator status. They had forgotten to
reduce the privileges upon deploying the changes to production. As a result the entire operation was
compromised. Resulting in considerable financial losses and not to mention damaging reputations.
Thus security engineers always need to ensure that Web services vulnerabilities such as buffer overflows,
deeply nested nodes, recursive payloads, schema poisoning, and malware traveling over SOAP messages do not
affect their critical Web services. They can do this by rapidly scanning Web services and assessing areas of
exposure, determining severity levels, providing vulnerability diagnosis, and then publishing remediation
techniques. Web services vulnerability assessment is a crucial pre-production and post-production step for every
service oriented application.

Debugging
When we compile and execute the source code for a Visual Studio 2005 application, a .NET Framework
compatible compiler compiles the source code to Microsoft Intermediate Language (MSIL) code. Then, the
MSIL code is interpretated by the Common Language Runtime (CLR) and uses the Just In Time (JIT) to run the
native code on a computer. When we debug a Visual Studio 2005 application, the debugger first maps the native
code to MSIL, and then maps the MSIL code to source code by using a programmer database (PDB) file.
Visual Studio 2005 provides debugging tools, such as DbgClr and CorDbg, to help developers locate and
remove errors and bugs. The Microsoft CLR debugger (DbgCLR.exe) provides debugging services with a
graphical interface to help application developers find and fix bugs in programs that target the common language
runtime. Alternatively, CorDbg is a command-line debugging tool. Next we’ll look at how to debug Visual
Studio 2005 applications by using these tools.

Cordbg.exe
The .NET framework SDK provides CorDbg.exe which can be used to debug our .NET applications from the
command prompt. To use CorDbg we first need to build the application so that it includes the appropriate /debug
switch. CorDbg uses the run-time Debug API to debug applications. Here's how to use the debugger:

cordbg [ProgramName[Program arguments]][optional arguments]


command [command arguments]

Common Command Description

b[reak] [[file:] line number] | [[ Using the break command we can set or displays
class::] function [:offset]] breakpoints. If no arguments are specified, the tool
will display a list of current breakpoints

cont [count] cont command continues the execution of the


program. It can be used after execution has stopped
due to breakpoints

381
The Complete Reference To Professional SOA with Visual Studio 2005

del[ete] [breakpoint id, ...] Delete command can be used to remove breakpoints.
We can specify a specific breakpoint id to remove.
We can find the relevant breakpoint id by using the
break or stop command.

h[elp] [command ...] the help command words as help it can displays
descriptions for a specified command. If no command
is specfied then CorDbg.exe displays a list of
debugger commands. The ? command can be used the
same way as the help command.

k[ill] We can stop the current process by using the kill


command.

l[ist] option list command can be used to displays a list of loaded


modules, classes, or global functions.
We can specify several options:

mod Lists the loaded modules in the process.

cl Lists the loaded classes in the process.

fu Lists global functions for each module in the process.

n[ext] [count] The next command can be used to step to the next
line of source code. It will also step over function
calls.

o[ut] [count] The out command can be used to steps the program
out of the current function. If no argument is
specified the command will only perform a set out
once for its current position. If we specify a count
parameter the out command will be performed for the
specified number of times.

p[rint] [variable name] The print command can be used to display a local
variable and its value. If no variable is specified all
local variables are displayed.

ref[reshsource] [source file] The refreshsource command can be used to reload the
source code for a given file. The source must be part
of the currently executing program.

r[un] [executable [args]] The run command is use to execute a program for
debugging we can also pass in parameters by
specying them as arguments.

set variable value set command can be used to set the value of a
particular variable.

382
The Complete Reference To Professional SOA with Visual Studio 2005

sh[ow] [count] The show command is used to display the source


code. If no argument is specified then it will display
five lines before and five lines after the current
position in the source code. We can specify in the
argument the number of source code lines to display
before and after.

s[tep] [count] The step command is used to step to the next source
line. It can also be used to step into a function call.

w[here] [count] The where command can be used to display a stack


trace for the current thread. A count can be specified
to display the specified number of stacks.

In the following example we will attempt to debug the following code in listing 10-1 and listing 10-2using
CorDbg:

Listing 10-1. Sample code for debugging using Visual C#

using System;
using System.Collections.Generic;
using System.Text;

namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 2; i++)
{
Console.WriteLine("Count: " + i);
}
}
}
}

Listing 10-2. Sample code for debugging using Visual Basic .NET

Module Module1

Sub Main()
Dim i As Integer = 0
While i < 2
Console.WriteLine("Count: " + i.ToString())
i += 1
End While
End Sub

383
The Complete Reference To Professional SOA with Visual Studio 2005

End Module
When we debug an application using CorDbg, the application is debugged in a new CorDbg session. To start
a CorDbg session, we need to type cordbg inside the Visual Studio 2005 Command Prompt, followed by the
required command to control the debugging session.
We can start debugging the program by using the cordbg helloworld.exe command. The command run
helloworld.exe is invoked automatically within the cordbg environment. We can ignore the warning about
mscorlib.dll, the cordbg utility simply informs us that we can not debug the core library that contains .NET
Framework class library types. We are now in the cordbg command prompt see figure 10-2 below and listing 10-
3 for output.

Figure 10-2. Launching cordbg

Listing 10-3. starting cordbg

D:\Projects\CH10\SourceCode\HelloWorld\
HelloWorld\bin\Debug>cordbg helloworld.exe
Microsoft (R) Common Language Runtime Test Debugger
Shell Version 2.0.50727.42 (
RTM.050727-4200)
Copyright (C) Microsoft Corporation. All rights reserved.

(cordbg) run helloworld.exe


Process 5376/0x1500 created.
Warning: couldn't load symbols for
C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__
b77a5c561934e089\mscorlib.dll
[thread 0x1504] Thread created.

010: {
(cordbg)

We can use the show command to list five lines before and five lines after the current line of code. By
entering show we get the following response from cordbg see listing 10-4below.

Listing 10-4. using show command

(cordbg) show

384
The Complete Reference To Professional SOA with Visual Studio 2005

005: namespace HelloWorld


006: {
007: class Program
008: {
009: static void Main(string[] args)
010:* {
011: for (int i = 0; i < 2; i++)
012: {
013: Console.WriteLine("Count: " + i);
014: }
015: }
(cordbg)

In the listing 10-4 above, we can see that cordbg has listed the line number next to the code. The line
numbers will serve as a reference point from which will allow us to set brake points. We can see that at line 10
there is an astrix * next to the line. This indicates where we are currently in the debugging process.
We can set break points by using the ‘b’ command. For the purpose of this example we want to set our point
on the line with the following code Console.WriteLine("Count: " + i); this is on line 13 determined from the listing
10-4 above.
To break on line 13 use the command b 13. See listing 10-5 below.

Listing 10-5. Adding break point

(cordbg) b 13
Breakpoint #1 has bound to D:\Projects\Book\SourceCode\Ch10\HelloWorld\HelloWorl
d\bin\Debug\helloworld.exe.
#1 D:\Projects\Book\SourceCode\Ch10\HelloWorld\HelloWorld\Program.cs:13
Main+0x6(il) [active]
(cordbg)

After we have set the break point we can ask the debugger to continue executing until the break point this
can be achieved using the go command. See listing 10-6.

Listing 10-6. Executing the go command

(cordbg) go
break at #1 D:\Projects\Book\SourceCode\Ch10\HelloWorld\HelloWorld\Program.c
s:13 Main+0x6(il) [active]

013: Console.WriteLine("Count: " + i);


(cordbg)

The deubugger is now currently on line 13 we can see this by executing the show command again. See
listing 10-7 below.

Listing 10-7. show command

(cordbg) show
008: {
009: static void Main(string[] args)
010: {
011: for (int i = 0; i < 2; i++)
012: {

385
The Complete Reference To Professional SOA with Visual Studio 2005

013:* Console.WriteLine("Count: " + i);


014: }
015: }
016: }
017: }
(cordbg)

In the listing 10-7 above we can now see the astrix * is next to line 13. Now we want to find out the value of
i to do this we can use the print command by specifying print i. This will return the value of 0. Now if we wanted
to continue the execution to see if the value of i changes. We can execute the go command again. Because the
break point is still set on line 13 and the for condition in Visual C#, while condition in Visual Basic .NET has not
yet been satisfied the execution will still remain on line 13. By executing the print i command again we can see
that the value of i has changed. See listing 10-8 below.

Listing 10-8. using the print command

(cordbg) print i
i=0
(cordbg) go
Count: 0
break at #1 D:\Projects\Book\SourceCode\Ch10\HelloWorld\HelloWorld\Program.c
s:13 Main+0x6(il) [active]

013: Console.WriteLine("Count: " + i);


(cordbg) print i
i=1
(cordbg)

We have successfully debugged in the above example the value of i. To exit cordbg debug environment
simply the exit command.

Debugging Using Visual Studio 2005


To start debugging an application, choose Start from the Debug menu of Visual Studio 2005, as shown in Figure
10-3. When we choose Start Debugging, the application starts and continues to execute until it reaches a
breakpoint. When the application reaches a breakpoint, execution of the code is paused and the application enters
break mode. In break mode, we can examine values by moving the cursor over an object. In addition, we can
modify variables' values by using either the watch window or the command window.

386
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 10-3: Start Debugging

The Watch Window


We can use the Watch window (see figure 10-4) to evaluate variables and expressions and maintain the results.
To open the Watch window when an application is in break mode, from the Debug menu, point to Windows and
choose Watch (Visual Studio 2005 allows up to four watch windows). We can also use the Watch window to
edit the value of a variable or register. However, we cannot edit the values of constant variables.

Figure 10-4: Watch window

To add a variable to the watch window simply break at the location where you’re interested. Right mouse
click over the variable and select Add Watch. You can also add the variable by simply drag and dropping it into
the watch window. Alternative you could simply type the variable into the name fieled of the watch window.

The Call Stack Window


We can use the Call Stack window, to view the function or procedure calls that are currently on the stack. To
open the Call Stack window when an application is in break mode, from the Debug menu, point to Windows and
choose Call Stack.

Figure 10-5: Call stack window

387
The Complete Reference To Professional SOA with Visual Studio 2005

The Call Stack window displays the name of each function and the language in which it is written. In
addition to the function name, the Call Stack window displays optional information, such as module name;
parameter name, parameter type, parameter value, line number and byte offset. To select the desired information
to display, right-click in the Call Stack window and choose the appropriate information type.

The Locals Window


The Locals window displays variables that are local to the current context. To open the Locals window when the
application is in break mode, point to Windows on the Debug menu and choose Locals.
We can also change the values of variables in the Locals window. To change the value of a variable, double-
click the value that we want to change and type the new value.

Figure 10-6: Locals

The Autos Window

Visual Studio also comes with the Auto window which can help us with the debugging process. The window will
appear during debugging. We can use the Autos window, to view the variables used in the current statement and
in the previous statement. However, when we are debugging a Visual Basic 2005 application, the Autos window
displays variables in the current statement and in the three next and previous statements.

Figure 10-7: The Autos window

The Breakpoint Window


In Visual Studio 2005 we can set breakpoints within the application. These are the locations in code where the
debugger pauses the execution of a program. When our program and debugger reach a breakpoint, they are said
to be in a break mode.
We can set, enable, disable, edit, or delete breakpoints in the source code window or through the
Breakpoints window (shown in Figure 10-8). To set a breakpoint in the source code window, we identify the

388
The Complete Reference To Professional SOA with Visual Studio 2005

statement where we would like to set the breakpoint and click on the grey margin on the left. To open the
Breakpoints window, from the Debug menu, point to Windows and choose Breakpoints.

Figure 10-8: Breakpoints

In Visual Studio we can specify breakpoints within the application in several ways:

* File breakpoint - causes a program to break when execution reaches a specified location within a file.
* Condition - an optional property that determines whether the program breaks when a breakpoint is reached.
The condition can be any valid expression recognized by the debugger. The debugger evaluates the condition
and breaks execution only if the condition is satisfied.
* Hit Count - Hit count, as shown in Figure 10-9, determines whether our program breaks when the breakpoint is
reached. This allows us to specify a condition. If the condition is met then the debugger will break. In this
instance the debugger will be stopped at the nth time the break point is reached. We can also specify for
multiple times of or breaking when the hit count is greater than or equal to.

Figure 10-9: Breakpoint hit Counter

* Filter - we can restrict the breakpoint to only being set in certain processes and threads. We can enter the
expression such as ProcessID=45 which will influence the breakpoint to only be set when the ProcessID=45
(see Figure 10-10). We can also combine conditions using & (AND), || (OR), ! (NOT), and parentheses.

389
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 10-10: Breakpoint Filter

* When Hit - when a breakpoint is hit, this option allows you to specify a task that will run, for example a Visual
Studio macro or a message display. When the breakpoint is hit, the message is written to the Output window
(see Figure 10-11). This means we don’t have to add or remove any code.

Figure 10-11: When breakpoint is hit the result is written to the output window.

Testing With Visual Studio 2005


Microsoft Visual Studio 2005 Team System is the first version of Visual Studio to include a suite of tools for
testing. These tools are specifically designed for developers and testers. The tools support testing throughout the
entire software development and maintenance life cycles. In the past, testers have typically relied on third-party
products such as Nunit, NAnt to create and execute test cases. In this section we will be looking at the
functionalities provided by Visual Studio 2005 Team Edition for Software Developers.

Unit Testing
To build clean, well-structured code, we developers need some mechanism to ensure that the code runs
effectively. One solution is for the developer to write pieces of code and then run the application to see whether
it works the way it should. The developer then moves on to the next piece of code, never coming back to test that
functionality until it’s close to the release date. Unit tests are a way to automate that method of testing so that the
tests can be run repeatedly as the product is developed.

390
The Complete Reference To Professional SOA with Visual Studio 2005

In order to create unit tests, we need to design a series of test cases that test whether the business logic is
functioning correctly and whether inputs produce the expected outputs. To be complete, many unit tests might
test the same piece of code to ensure that all the branches and internal code flow are tested. We’ll see how Visual
Studio solves this problem when we talk about code coverage later. Because unit tests test basic functionality at
the method level, they are considered to be a developer’s responsibility and not the responsibility of the testing
staff.
In the example below we will be creating a calculator Web service we will then attempt to test this
calculator service with our unit tests.
To start with create a new Web service called TestService, as shown in Figure 10-12.

Figure 10-12: New Web service called TestService

Enter the code below. First, Listing 10-9 shows the C#:

Listing 10-9: C# for the Calculator Web service

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
public Service () {

//Uncomment the following line if using designed components


//InitializeComponent();
}

[WebMethod]
public int AddInt(int x, int y) {
return x + y;
}

[WebMethod]

391
The Complete Reference To Professional SOA with Visual Studio 2005

public int SubtractInt(int x, int y)


{
return x - y;
}

[WebMethod]
public int MultiplyInt(int x, int y)
{
return x * y;
}

[WebMethod]
public double DivideInt(int x, int y)
{
return x / y;
}

[WebMethod]
public int DivideExceptionInt(int x, int y)
{
return x / y;
}
}

Or, if you prefer Visual Basic 2005, see Listing 10-10:

Listing 10-10: Visual Basic for the Calculator Web service

Imports System
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols

<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
Public Class Service
Inherits System.Web.Services.WebService

Public Sub New()


End Sub

<WebMethod()> _
Public Function AddInt(ByVal x As Integer, ByVal y As Integer) As Integer
Return x + y
End Function

<WebMethod()> _
Public Function SubtractInt(ByVal x As Integer, ByVal y As Integer) As Integer
Return x - y
End Function

<WebMethod()> _
Public Function MultiplyInt(ByVal x As Integer, ByVal y As Integer) As Integer
Return x * y

392
The Complete Reference To Professional SOA with Visual Studio 2005

End Function

<WebMethod()> _
Public Function DivideInt(ByVal x As Integer, ByVal y As Integer) As Double
Return x / y
End Function

<WebMethod()> _
Public Function DivideExceptionInt(ByVal x As Integer, ByVal y As Integer) As Integer
Return x / y
End Function

End Class

Once we have completed our code we need to build the Web service application to verify that there are no
outstanding syntax errors. Once the build is successful using Visual Studio we can generate our test project and
our test methods. Simply right mouse click on the screen then select “Create Unit Tests” (see figure 10-13).

Figure 10-13: Create Unit Tests

A dialog window will appear (see Figure 10-14). In this window we can select the methods that we’d like to
Visual Studio to generate test cases for.

393
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 10-14: Create Unit Tests

Pressing the Settings button brings a dialog screen from which we can specify our settings to generate our
new test project (see Figure 10-15). In our example we will leave the settings as they are.

Figure 10-15: Test Generation Settings

In the Output project selection checked that you have selected your default language either “Create a new Visual
Basic test project…” or “Create a new Visual C# test project”.
Make sure you have selected all the methods then click OK. Enter VBCalcUnitTest as the new project name
then select Create, as shown in Figure 10-16.

394
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 10-16: New Test Project

The Test Generation Progress dialog box appears showing the test classes' generation progress (see Figure 10-
17)

Figure 10-17: Test generation

Visual Studio will generate the new test cases for the previously selected methods. We can see an example
of the generated test case in listing 10-11 and listing 10-12.

Listing 10-11: Auto generated TestMethod() in C#

[TestMethod()]
public void AddIntTest()
{
Service target = new Service(); // TODO: Use [AspNetDevelopmentServer]
//and TryUrlRedirection() to auto launch and bind web service.

int x = 0; // TODO: Initialize to an appropriate value

int y = 0; // TODO: Initialize to an appropriate value

int expected = 0;
int actual;

actual = target.AddInt(x, y);

Assert.AreEqual(expected, actual, "UnitTest.localhost.Service.AddInt did not return the expected value.");


Assert.Inconclusive("Verify the correctness of this test method.");
}

Listing 10-12: Auto generated TestMethod() in Visual Basic 2005

<TestMethod()> _
Public Sub AddIntTest()
Dim target As Service = New Service 'TODO: Use [AspNetDevelopmentServer]

395
The Complete Reference To Professional SOA with Visual Studio 2005

'and TryUrlRedirection() to auto launch and bind web service.

Dim x As Integer 'TODO: Initialize to an appropriate value

Dim y As Integer 'TODO: Initialize to an appropriate value

Dim expected As Integer


Dim actual As Integer

actual = target.AddInt(x, y)

Assert.AreEqual(expected, actual, _
"VBCalcUnitTest.localhost.Service.AddInt did not return the expected value.")
Assert.Inconclusive("Verify the correctness of this test method.")
End Sub

Figure 10-18. Test project in solution explorer

The exact generated code will vary depending on the method type and signature that the test targets for
testing. The wizard will create code using reflection to test private member functions.
The generated test classes in the test project will contain test methods that is decorated with the
TestMethodAttribute. In addition, the classes that contains these test methods are decorated with the
TestClassAttribute. Both of these attributes can be found under the
Microsoft.VisualStudio.QualityTools.UnitTesting.Framework namespace. The Team Test uses reflection to search a
test assembly and find all of the test classes decorated with TestClassAttribute. It then finds the corresponding
TestMethodAttribute within the test classes to determine what to execute. The test method themselves must not
take any parameters it is validated by the execution engine but not by the compiler.
When the tests is run, the Assert.Inconclusive() can be used to indicate that a correct implementation could be
missing. The Assert class provides a number of members which allow us to test a particular condition or
particular state of an object see Table 10-3.

396
The Complete Reference To Professional SOA with Visual Studio 2005

Table 10-3: Common Assert members

Name Description

AreEqual Checks to see whether the specified two values are equal if the values are not
equal then the test fails.

AreNotEqual Checks to make sure that the specified two values are not equal. The test fails
if the value are equal.

AreNotSame Checks to make sure the two inputs refer to different objects and fail if they are
of the same object.

AreSame Checks to ensure that the two inputs refer to the same object. The test fails if
they refer to two different objects.

Fail Fails the assertion.

Inconclusive This means that the result can not be concluded. The test result can not be
proven true or false.

IsFalse Test to see if the condition is false. If the result is true then the assertion fails.

IsInstanceOfType Test to see if the specified object is an instance of a specified type. If it is not
of that type the test fails.

IsNotInstanceOfType Test to ensure that the specified object is not of an instance of the wrong type.

IsNotNull Tests to ensure that the specified object is not null. The test fails if the value is
null.

IsNull Tests to ensure that the specified object is of a null value or Nothing in Visual
Basic. The test fails if it is not null.

IsTrue Tests to ensure that the specified condition is true and the test fails if test
condition is false.
We will now customize the test methods to unit test our calculator methods.

Listing 10-13. ServiceTest, the C# unit test class used to test the Web service

// The following code was generated by Microsoft Visual Studio 2005.


// The test owner should check each test for validity.
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Text;
using System.Collections.Generic;
using CSCalcUnitTest.localhost;

397
The Complete Reference To Professional SOA with Visual Studio 2005

namespace CSUnitTest
{
/// <summary>
///This is a test class for CSUnitTest.localhost.Service and is intended
///to contain all CSUnitTest.localhost.Service Unit Tests
///</summary>
[TestClass()]
public class ServiceTest
{
private TestContext testContextInstance;

/// <summary>
///Gets or sets the test context which provides
///information about and functionality for the current test run.
///</summary>
public TestContext TestContext
{
get
{
return testContextInstance;
}
set
{
testContextInstance = value;
}
}
#region Additional test attributes
//
//You can use the following additional attributes as you write your tests:
//
//Use ClassInitialize to run code before running the first test in the class
//
//[ClassInitialize()]
//public static void MyClassInitialize(TestContext testContext)
//{
//}
//
//Use ClassCleanup to run code after all tests in a class have run
//
//[ClassCleanup()]
//public static void MyClassCleanup()
//{
//}
//
//Use TestInitialize to run code before running each test
//
//[TestInitialize()]
//public void MyTestInitialize()
//{
//}
//
//Use TestCleanup to run code after each test has run
//

398
The Complete Reference To Professional SOA with Visual Studio 2005

//[TestCleanup()]
//public void MyTestCleanup()
//{
//}
//
#endregion

/// <summary>
///A test for AddInt (int, int)
///</summary>
[TestMethod()]
public void AddIntTest()
{
Service target = new Service();
Random rand = new Random();
int x = rand.Next(100);
int y = rand.Next(100);

int expected = x + y;
int actual;

actual = target.AddInt(x, y);

Assert.AreEqual(expected, actual,
"CSUnitTest.localhost.Service.AddInt did not return the expected value.");
}

/// <summary>
///A test for DivideInt (int, int)
///</summary>
[TestMethod()]
public void DivideIntTest()
{
Service target = new Service();
Random rand = new Random();
int x = rand.Next(100);
int y = rand.Next(100);

double expected = (double)x/y;


double actual;

actual = target.DivideInt(x, y);

Assert.AreEqual(expected, actual,
"CSUnitTest.localhost.Service.DivideInt did not return the expected value.");
}

/// <summary>
///A test for MultiplyInt (int, int)
///</summary>
[TestMethod()]
public void MultiplyIntTest()

399
The Complete Reference To Professional SOA with Visual Studio 2005

{
Service target = new Service();
Random rand = new Random();
int x = rand.Next(100);
int y = rand.Next(100);

int expected = x*y;


int actual;

actual = target.MultiplyInt(x, y);

Assert.AreEqual(expected, actual,
"CSUnitTest.localhost.Service.MultiplyInt did not return the expected value.");
}

/// <summary>
///A test for SubtractInt (int, int)
///</summary>
[TestMethod()]
public void SubtractIntTest()
{
Service target = new Service();
Random rand = new Random();
int x = rand.Next(100);
int y = rand.Next(100);

int expected = x-y;


int actual;

actual = target.SubtractInt(x, y);

Assert.AreEqual(expected, actual,
"CSUnitTest.localhost.Service.SubtractInt did not return the expected value.");
}

}
}

Listing 10-14. ServiceTest, the Visual Basic 2005 unit test class used to test the Web service

'The following code was generated by Microsoft Visual Studio 2005.


'The test owner should check each test for validity.
Imports Microsoft.VisualStudio.TestTools.UnitTesting
Imports System
Imports System.Text
Imports System.Collections.Generic
Imports VBCalcUnitTest.localhost

'''<summary>
'''This is a test class for VBCalcUnitTest.localhost.Service and is intended
'''to contain all VBCalcUnitTest.localhost.Service Unit Tests
'''</summary>

400
The Complete Reference To Professional SOA with Visual Studio 2005

<TestClass()> _
Public Class ServiceTest

Private testContextInstance As TestContext

'''<summary>
'''Gets or sets the test context which provides
'''information about and functionality for the current test run.
'''</summary>
Public Property TestContext() As TestContext
Get
Return testContextInstance
End Get
Set(ByVal value As TestContext)
testContextInstance = Value
End Set
End Property

#Region "Additional test attributes"


'
'You can use the following additional attributes as you write your tests:
'
'Use ClassInitialize to run code before running the first test in the class
'
'<ClassInitialize()> _
'Public Shared Sub MyClassInitialize(ByVal testContext As TestContext)
'End Sub
'
'Use ClassCleanup to run code after all tests in a class have run
'
'<ClassCleanup()> _
'Public Shared Sub MyClassCleanup()
'End Sub
'
'Use TestInitialize to run code before running each test
'
'<TestInitialize()> _
'Public Sub MyTestInitialize()
'End Sub
'
'Use TestCleanup to run code after each test has run
'
'<TestCleanup()> _
'Public Sub MyTestCleanup()
'End Sub
'
#End Region

'''<summary>
'''A test for AddInt(ByVal Integer, ByVal Integer)
'''</summary>

401
The Complete Reference To Professional SOA with Visual Studio 2005

<TestMethod()> _
Public Sub AddIntTest()
Dim target As Service = New Service
Dim rand As Random = New Random
Dim x As Integer = rand.Next(100)
Dim y As Integer = rand.Next(100)
Dim expected As Integer = x + y
Dim actual As Integer
actual = target.AddInt(x, y)
Assert.AreEqual(expected, actual, _
"CSUnitTest.localhost.Service.AddInt did not return the expected value.")

End Sub

'''<summary>
'''A test for DivideInt(ByVal Integer, ByVal Integer)
'''</summary>
<TestMethod()> _
Public Sub DivideIntTest()
Dim target As Service = New Service
Dim rand As Random = New Random
Dim x As Integer = rand.Next(100)
Dim y As Integer = rand.Next(100)
Dim expected As Double = CType(x, Double) / y
Dim actual As Double
actual = target.DivideInt(x, y)
Assert.AreEqual(expected, actual, _
"CSUnitTest.localhost.Service.DivideInt did not return the expected value.")
End Sub

'''<summary>
'''A test for MultiplyInt(ByVal Integer, ByVal Integer)
'''</summary>
<TestMethod()> _
Public Sub MultiplyIntTest()
Dim target As Service = New Service
Dim rand As Random = New Random
Dim x As Integer = rand.Next(100)
Dim y As Integer = rand.Next(100)
Dim expected As Integer = x * y
Dim actual As Integer
actual = target.MultiplyInt(x, y)
Assert.AreEqual(expected, actual, _
"CSUnitTest.localhost.Service.MultiplyInt did not return the expected value.")
End Sub

'''<summary>
'''A test for SubtractInt(ByVal Integer, ByVal Integer)
'''</summary>
<TestMethod()> _
Public Sub SubtractIntTest()
Dim target As Service = New Service
Dim rand As Random = New Random

402
The Complete Reference To Professional SOA with Visual Studio 2005

Dim x As Integer = rand.Next(100)


Dim y As Integer = rand.Next(100)
Dim expected As Integer = x - y
Dim actual As Integer
actual = target.SubtractInt(x, y)
Assert.AreEqual(expected, actual, _
"CSUnitTest.localhost.Service.SubtractInt did not return the expected value.")
End Sub
End Class

Running Tests
We can run our auto-generated test service by Test ~TRA Start Selected Test Project with Debugger or Shift +
Alt + X (see Figure 10-19).

Figure 10-19: Start Selected Test Project

Figure 10-20 shows the Test Results windows. Columns can be added or removed by right-clicking on the
column headers and selecting the Add/Remove Columns... menu item. In addition, we can right-click on
individual tests and select the Open Test menu item to jump into the test code.

Figure 10-20: Test Result window after executing all tests

We can also use a unit test to check for exception conditions. The ExpectedExceptionAttribute listens for an
exception during the execution of a test. If an exception occurs, the test passes. We can specify either the type of
exception or both the type of the exception and the message the exception generates. This is useful if we needed
to check that we’re throwing custom exceptions upon certain conditions.
In the example we will be generating an exception by dividing 0 listing 10-15 and listing 10-16.

Listing 10-15: Generating test exceptions with C#

[TestMethod()]

403
The Complete Reference To Professional SOA with Visual Studio 2005

public void DivideExceptionIntTest()


{
Service target = new Service();
int x = 0;
int y = 0;
target.DivideExceptionInt(x, y);
}

Listing 10-16: Generating test exceptions with Visual Basic 2005

<TestMethod()> _
Public Sub DivideExceptionIntTest()
Dim target As Service = New Service
Dim x As Integer = 0
Dim y As Integer = 0
target.DivideExceptionInt(x, y)
End Sub

We can see that an exception had been thrown in Figure 10-21.

Figure 10-21: Shows the generated exception

We will now add the ExpectedExceptionAttribute, which will return successful when the exception is
encountered. See listing 10-17 and listing 10-18.

Listing 10-17. Adding ExpectedExceptionAttribute in C#

[TestMethod()]
[ExpectedException(typeof(SoapException))]
public void DivideExceptionIntTest()
{
Service target = new Service();
int x = 0;
int y = 0;
target.DivideExceptionInt(x, y);
}

Listing 10-18: Adding ExpectedExceptionAttribute in VB

<TestMethod()> _
<ExpectedException(GetType(System.Web.Services.Protocols.SoapException))> _
Public Sub DivideExceptionIntTest()
Dim target As Service = New Service
Dim x As Integer = 0
Dim y As Integer = 0

404
The Complete Reference To Professional SOA with Visual Studio 2005

target.DivideExceptionInt(x, y)
End Sub

Figure 10-22 shows the Test Results window now we have added an ExpectedExceptionAttribute.

Figure 10-22: Result of using ExpectedExceptionAttribute.

Code Coverage
One key metric for unit testing is determining how much of the code is tested when the unit tests run. The metric
is known as the code coverage and Team Test includes a code coverage tool for detailing both the percentage of
code that is executed along with highlighting within the code to show which lines are executed and which lines
are not.
To enable code coverage in VSTS go to Test ~TRA Edit Test Run Configuration ~TRA Local Test Run, as
shown in Figure 10-24.

Figure 10-23: Select a Test Run Configuration

Under the Code Coverage option, select the artifacts to instrument, as shown in Figure 10-24. Then select
Apply.

405
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 10-24: Enable Code Coverage

Start the test by selecting Test -> Start Selected Test Project Without Debugger. This results in highlighted
code when run, as shown in Figure 10-25.

Figure 10-25: Highlighted Code Coverage

Initializing and Cleaning Up Tests


In general, a test class contains not only the individual test methods, but also various methods for initializing and
cleaning up tests as well. The test setup and cleanup methods are decorated with TestInitializeAttribute and
TestCleanupAttribute respectively. Within each of these methods we can place any additional code that needs to
be run before or after every test.

406
The Complete Reference To Professional SOA with Visual Studio 2005

During debugging it is possible that the TestCleanupAttribute decorated method will not run simply because
the debugger was stopped before the cleanup code executed. For this reason, it is often a good practice to check
for cleanup during test setup and execute the cleanup prior to the setup as necessary. Other test attributes
available for initialization and cleanup are AssemblyInitializeAttribute/AssemblyCleanupAttribute and
ClassInitializeAttribute/ClassCleanupAttribute. The assembly-related attributes run once for an entire assembly
while the class related attributes run once each for the loading of a particular test class.

Static Analysis
Creating quality code often involves analyzing code for known defects, which can be achieved through the use
of static analysis. In Visual Studio 2005 Team System, the static analysis tool is an evolution of FxCop. The
static code analyzer runs against compiled code, looking for a large number of known defects and poor
programming practices. In addition, it can be used to enforce corporate naming conventions.
The rules used by the static analyzer are fully extensible, and it is possible to add a new rule relatively
quickly. It’s also possible to enable and disable rules that will be run against the code. For instance, we might
choose not to run the rules that enforce naming conventions but be very interested in the results of the tests that
check for known security issues. Finally, we can choose whether a violation of a rule generates a warning or a
compile-time error.
For coding conventions that absolutely must not be violated, using an error is the best practice and is one of
the easiest to implement. Setting a violation of code from being checked in unless it has compiled without error,
results in an easy to implement yet very powerful technique for guaranteeing a certain level of code quality.
We can enable code analysis in Visual Studio by right click on a project selecting properties. Then selecting
the Code Analysis tab see figure 10-26. To enable code analysis we will need to select the check box “Enable
Code Analysis”.

Figure 10-26: Configuring static analysis for the code

Once we have enabled the project set up for code analysis, all we need to do is recompile our application.
This will cause the static code analyzer to run. The results can then be seen by examining the Errors window (see
figure 10-27). If a particular line of code caused the error, double-clicking the error in the Error window will
open the appropriate code window and bring us to the problem area within the code.

407
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 10-27: Result from static analysis test in Visual Studio 2005

The results can also be saved to CodeAnalysisLog.xml. Opening this file will show all the issues the compiler
had uncovered.

Figure 10-28: CodeAnalysisLog.xml

Profiling
Code profiling is the process where we analyze the code and how quickly it executes. It enables developers to
see where the bottleneck exists within the application quickly. After the application has been completed and the
code unit tested we should always profile the code. There’re two types of methods to profile an application in
Visual Studio: sampling and instrumentation.

408
The Complete Reference To Professional SOA with Visual Studio 2005

Sampling
Using the sampling method, the profiler will periodically determine which function is being executed. The
profiler keeps track of the number of times that it has executed the function by incrementing a counter. It
interrupts the application in short intervals to build up a statistical view of he application. It’s a reliable way to
determine where an application spends the majority of its time. Once the application is stopped, a report is
generated that provides the details.

Instrumentation
The instrumentation method is more aggressive than the sampling method. In this method, the profiler inserts
enter and exit probes into specific functions of an application. These functions are now monitored when the
application runs. The probes capture the deterministic performance metrics for the functions. This means that we
can get information about how long a method takes to execute. This method also provides a relatively complete
numeric look at how often various methods are called. Once the application is stopped, a report can be generated
based on the data gathered by the instrumentation profiler.

Implementing Sampling
To configure the performance we can check session properties under the Tools ~TRA Options ~TRA
Environment ~TRA Performance Tools page in Visual Studio, shown in Figure 10-29. This is the section where
we can specify all settings related to all performance sessions.

Figure 10-29: Configuring performance session.

The first option shown in Figure 10-29 is a radio button to show time as CPU clock ticks or milliseconds.
The next option lets us select how many functions are shown in summary view. Summary view is the first view
that we see when analyzing a performance run and it lists the top X functions in terms of total number of calls,
total number of calls to a function and all child functions, and total time taken by a function. The last option
allows us to serialize symbols, which saves symbols in with our .VSP files. The .VSP files can be copied and
read on different systems without chasing down symbols files. These .VSP files are the files that are created with
each run of the profiler.
In the example below we will create a sampling session on a Web service client we had created in Chapter
9. Select the Tools ~TRA Performance Tools ~TRA Performance Wizard option, as shown in Figure 10-30.

409
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 10-30: Performance Wizard

In Figure 10-31 we will select Profile an executable (.EXE) because the application that we wanted to
profile has already been compiled. We will be asked for the path to the file, the working directory, and any
command-line arguments, more of which later.
If we select a project in the current solution we will proceed straight to the performance session type page
shown in Figure 10-33. For a .DLL, we have the same options as for an .EXE, but we also have to specify the
path to an .EXE file that utilizes the selected .DLL. And for ASP.NET we are asked for the local URL of the
ASP.NET application that we want to profile.

Figure 10-31: Performance Wizard

We will now browse to the location of the executable that we had created in Chapter 9 of the employee Web
service client (the CSEmployeeClient project in Chapter 9), as shown in Figure 10-32.

410
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 10-32: Browse to a location of Exe application to performance test

The next screen asks us to pick either sampling or instrumentation profiling to profile our application. Select
sampling, as shown in Figure 10-33. We will cover instrumentation a little later.

Figure 10-33: Select profiling method

In Figure 10-34 select Finish to complete the process.

411
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 10-34: Performance Wizard

In the sampling mode under Performance Explorer the Targets folder contains the item that we’re interested
in collecting profiling data from (see Figure 10-35). If an icon has a green arrow then it indicates that this is the
startup binary that will be automatically launched at the start of our profiling session. We can change this simply
by right mouse clicking on the selected binary and specifying to launch the binary or not. We can also add more
binaries to the performance session, simply by right clicking on the Targets folder and select Add Target Binary
this allows us to add other binaries from other projects in the solution or even from an ASP.NET web
application.
In the sampling mode, data is collected from all binaries that are running. But in instrumentation mode, we
can specify to collect data from the specific binaries that we choose to instrument. We can select the binaries that
we want to instrument by right mouse clicking them in the performance explorer then selecting instrument.
These binaries are marked with 1s and 0s on their icon to indicate that they will be instrumented when the
performance session is launched. We using instrumentation, we should limit the number of instrumented binaries
to keep them from being overwhelmed with data.
Now, right mouse click on the Performance explorer and select Launch to launch our windows application,
as shown in Figure 10-35.

Figure 10-35: Launch the application to profile

You will see the application...

412
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 10-36: Running the application

Once we close the Windows application the analysis of the results collected begins, as shown in Figure 10-
37.

Figure 10-37: Analyzing the report

The end result is a report into which we can drill to view the result from the execution of each method (see
Figure 10-38).

413
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 10-38: Sampling performance report

The summary view for sampling lists the top three (this number can be adjusted in the Tools ~TRA Options
~TRA Performance page) functions in terms of inclusive samples and exclusive samples. In the performance
report there’s a result set for inclusive and one for exclusive. An inclusive sample indicates which functions
during execution is spending the most amount of time. An exclusive sample indicates which functions during
execution is being called frequently though its execution could be quite fast. Thus in performance tuning the first
areas to focus on is the exclusive samples because the function is being executed quite often. By examining the
exclusive list we see that the mscorwks.dll (see Figure 10-39), a rather large DLL that is where most of the
loading is happening. This DLL according to the report is where almost thirty-five percent of the sample has
taken place. While looking at the inclusive report we can see that 99 samples were taken from the Main function
or its sub functions. This indicates that we’re getting very few samples in areas outside of the performance
scenario that we wanted to profile.

Figure 10-39: Instrumentation performance report

In instrumentation mode the performance report summary contains three different sections (see figure 10-
39). These are “most called functions,” “functions with most individual work” and “functions taking longest.”
The “most called functions” lists the functions that had been called the highest number of times. The report
also lists the number of times that they have been called.
The “Functions with most individual work” section lists the functions in which most amount of time had
been spent. The report shows the amount of time spent by each of these methods and their percentage against the
total execution time.

414
The Complete Reference To Professional SOA with Visual Studio 2005

Lastly the “functions taking longest” section shows the functions that took the longest to execute this
includes time spent in sub-functions this is similar to the inclusive mode for sampling.
By using instrumentation every function entry and exit is captured. This provides a very detailed report
which is not only limited to the samples. Figure 10-40 shows the instrumentation summary view for our demo
application.

Figure 10-40: Result from the profiling

Generally determining which method to use for profiling is based on our needs. Sampling is often used as a
first look at an application. The sampling method is also far less intrusive than the instrumentation method, and
thus allows the application to run at a normal pace. It doesn’t, however, provide a complete analysis of the
application. For example, even though we can see how the code appears within a method, we cannot determine
how long that particular method took to execute.
Instrumentation profiling provides for very specific performance metrics. However, it performs this in an
intrusive manner. This makes the application seem like it is struggling, but it does provide a much fuller profile
of the application and more reliable and specific information than the sampling method.

Summary
Visual Studio 2005 Team System has integrated a lot of tools for developers. It provides a vast range of tool sets
over previous versions of Visual Studio especially those tools help developers to develop efficiently and quickly.
After using Visual Studio Team System it is difficult to go back to any other development environments.
In this chapter we had looked at testing and how to accomplish a number of tasks, such as:

* Unit testing - Unit testing helps developers to build clean and well-structured code. It also helps to support the
mechanism to ensure that the code written runs effectively.
* Code coverage - Code coverage helps a developer to determine how much of the code is tested when the unit
tests run. Team Test includes a code coverage tool for detailing both the percentage of code that is executed
along with highlighting within the code to show which lines are executed and which lines are not.

* Static analysis - Creating quality code often involves analyzing code for known defects, which can be achieved
through the use of static analysis. The static code analyzer runs against compiled code, looking for a large
number of known defects and poor programming practices.

415
The Complete Reference To Professional SOA with Visual Studio 2005

* Profiling - Profiling the code ensures the performance of the code. After the application has been completed
and the code unit tested we should always profile the code. Code profiling is the process where we analyze the
code and how it quickly it executes. It enables developers to see where the bottleneck exists within the
application quickly. There’re two types of methods to profile an application in Visual Studio 2005: sampling
and instrumentation.

In addition to Visual Studio Team System Developer’s implementation to application testing. Visual Studio
Team System Tester’s also helps with the implementation to integration and regression testing.

416
The Complete Reference To Professional SOA with Visual Studio 2005

Chapter 11 Deployment
The .NET Framework provides features and tools that enable us to easily package and distribute a variety of
applications to a number of users. In this chapter, we will learn how to create setup projects to automatically
install and configure our Web service.
Once we have ensured that our application is free from bugs, we need to distribute our Web service
applications to end users by possibly deploying the application on various computers. In this chapter we will be
looking at various deployment features of the .NET Framework.

.NET Deployment
Ensuring successful deployment of an application is extremely important in the software development lifecycle,
especially when the majority of the deployment today is done at the client’s site. Any sort of failure during the
deployment process can easily become quite embarrassing. The .NET Framework is packed full of features and
tools that we can use to deploy applications successfully. These features and tools enable us to deploy different
types of applications to a large number of users. In addition, we can install new versions of applications on target
computers without adversely affecting the older versions of our applications. The .NET Framework provides
various packaging and distribution options that make it easy to deploy applications. The features of .NET
deployment include
No-impact deployment: In the past an incompatible version of DLL can be installed over an existing DLL. This
was a serious issue as it caused applications to stop working and was referred to as the “DLL Hell” problem. No-
impact deployment offered by the .NET Framework resolves this problem and DLL is deployed in isolation.
Controlled code sharing: Because components are private by default, multiple applications cannot share
components. We need to explicitly make the components available for sharing by assigning a strong name to an
assembly containing the components and installing the assembly in the global assembly cache.
XCOPY deployment and reproduction: .NET applications and components are self describing and self
contained so there is no need for registry entries or other form of dependencies. This allows application to be
simply copied from source to the destination directory on the target computer. Because of its simplicity it is often
referred to as XCOPY deployment. XCOPY is a MS DOS copy command.
Integration with the Windows Installer: Windows Installer offers rich capabilities and allows application users
to easily manage the deployed applications. Windows installer supports advertisement, publishing, repair and
install-on-demand when deploying applications. By deploying with Visual Studio we are able to build
deployment projects utilizing Windows Installer.
Private components by default: By default, the components are deployed to the application directory. These
components are visible only to the containing application. Because components are private by default, they have
no impact on other applications.
Side-by-side versioning: The .NET Framework supports the deployment of multiple versions of a component or
an application. We can specify the version of components that our application must use, and the Common
Language Runtime will enforce the versioning policy.
On the fly updates: One of the problems in the past with application update is that every application has to be
manually updated. With .NET applications administrators can use runtime hosts, such as ASP.NET, to update
program DLLs, even on remote computers. This feature enables us to update an application without stopping it.

417
The Complete Reference To Professional SOA with Visual Studio 2005

ClickOnce Deployment: ClickOnce deployment is a new feature in .NET Framework 2.0. The deployment
process is as the name suggests is very simple. It allows the deployment of Windows based client applications to
desktops by placing the application files on a Web server or file server that is accessible to the client.
Enterprise deployment: Using the software installation feature of Active Directory,an administrator can
automatically distribute and install .NET applications on the entire network.
Downloading and caching: .NET Applications and components can take advantage of the downloading and
caching feature which allows incremental downloads of applications to reduce the impact of the deployment
process on the client system. The components can also be isolated for use by the application for zero-impact
deployment.

Maintaining Assembly Versions


.NET applications are made up of discrete units of assemblies. These assemblies enable us to implement version
control, reusability, and security permissions. In addition, assemblies also provide the common language runtime
with the information it requires concerning type implementations. Therefore, assemblies are the fundamental
units for deploying Visual Studio 2005 applications. The following sections explain how versioning is
implemented for assemblies.
The details of each assembly version information is stored within the assembly’s manifest. The assembly
manifest contains specific information about the assembly’s version and the version of assemblies that are
dependent. The assemblies keep version information through two ways. The assembly contains a Globally
Unique Identifier (GUID) as an identification number and an informational version.

Figure 11-1: Assembly Information

An assembly’s information includes the version number, name and culture information about the assembly (see
figure 11-1). The common language runtime considers assemblies that contain different version numbers to be
different assemblies. The version number is a four part number consists of major version, minor version, build
number and revision. The format of the version number is:
<major version>.<minor version>.<build number>.<revision>

418
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 11-2: Specifying automatic assembly version

For example, in version 1.5.1153.0, the number 1 represents the major version, 5 represents the minor version,
1153 represents the build number, and 0 represents the revision number. The version number is stored in the
assembly manifest along with other identity information, including the assembly name and public key, and
information regarding the relationships and identities of other assemblies referenced in the application. When we
build an assembly, the development tool stores dependency information for each referenced assembly in the
assembly manifest.

Figure 11-3: AssemblyInfo.CS contains information regarding the assembly

There are three ways of specifying the assembly version. One way is using the Visual Studio IDE, right mouse
click on our CSEmployeeClient project in the solution explorer, and the properties. We can directly specify the
version of the assembly as shown in Figure 11-1. Select the Application tab then select Assembly Information. A
dialog window will appear. We can specify the version of the assembly by typing the values into the assembly
version section.
The second way is to let Visual Studio automatically increment the version number for us upon each
publication of the project Figure 11-2. Select Publish in the properties section of the project then select the
checkbox for “Automatically increment revision with each publish”.

419
The Complete Reference To Professional SOA with Visual Studio 2005

The third way to specify the assembly version is to modify the AssemblyInfo.cs or AssemblyInfo.vb file. It
can be found when we enable “Show All Files” in solution explorer. Then open the Properties folder under the
project under C# and open the My Project folder under Visual Basic 2005. See Figure 11-3.

The following code shows the attribute that we use to specify the version of an assembly see listing 11-1 and
listing 11-2.

Listing 11-1: Assembly.CS Using C#

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following


// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("CSEmployeeClient")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("devorg")]
[assembly: AssemblyProduct("CSEmployeeClient")]
[assembly: AssemblyCopyright("Copyright © devorg 2006")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("3e7a116c-4e4c-4760-9134-746e74849513")]

// Version information for an assembly consists of the following four values:


//
// Major Version
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Listing 11-2: Assembly.VB using Visual Basic 2005

Imports System
Imports System.Reflection
Imports System.Runtime.InteropServices

' General Information about an assembly is controlled through the following


' set of attributes. Change these attribute values to modify the information
' associated with an assembly.

420
The Complete Reference To Professional SOA with Visual Studio 2005

' Review the values of the assembly attributes

<Assembly: AssemblyTitle("VBEmployeeClient ")>


<Assembly: AssemblyDescription("")>
<Assembly: AssemblyCompany("DevOrg")>
<Assembly: AssemblyProduct("VBEmployeeClient ")>
<Assembly: AssemblyCopyright("Copyright © DevOrg 2006")>
<Assembly: AssemblyTrademark("")>

<Assembly: ComVisible(False)>

'The following GUID is for the ID of the typelib if this project is exposed to COM
<Assembly: Guid("a6cb62f3-c72b-4a4a-9ea5-386265bf1d03")>

' Version information for an assembly consists of the following four values:
'
' Major Version
' Minor Version
' Build Number
' Revision
'
' You can specify all the values or you can default the Build and Revision Numbers
' by using the '*' as shown below:
' <Assembly: AssemblyVersion("1.0.*")>

<Assembly: AssemblyVersion("1.0.0.0")>
<Assembly: AssemblyFileVersion("1.0.0.0")>

The AssemblyVersionAttribute attribute takes a string argument that represents the version number. We could
represent our AssemblyVersion as 1.3.* for example. Where only the major and minor versions are specified and
a wildcard is used for build and revision numbers. The language compiler automatically generates the build and
the revision numbers.
Assembly versioning enables us to implement side-by-side execution of assemblies. Side-by-side execution
enables us to run multiple versions of the same assembly simultaneously. The common language runtime
provides the infrastructure that allows multiple versions of the same assembly to run on the same computer. We
can also run multiple versions of the same assembly within the same process.
Side-by-side execution provides flexibility and allows CLR to manage side-by-side execution by reading an
assembly’s manifest information. This allows existing applications to continue to work with earlier versions of
the assembly. While new applications can simultaneously take advantage of newer versions of the same
assembly on the same machine.

Packaging and Distribution Options


The .NET Framework provides us with various options to package and distribute the applications that we create
in Visual Studio 2005. Whether it’s the Web service or the Windows Form or Web Form application that we
create to access the Web service. .NET packaging and distribution options allow us to deploy and publish our
application in various scenarios. In the following example we will learn to publish a Web service that we had
created in Chapter 9 (you can also find it under the Chapter 10 source code).

421
The Complete Reference To Professional SOA with Visual Studio 2005

Publishing Web service


Before we start make sure the Web service project is loaded in Visual Studio. We can open an existing Web
service project by File->Open->Web site then browsing to the location of the Web service before selecting
Open.
Once the Web service project has been loaded we can publish the Web service by selecting Build->Publish
Web Site (see figure 11-4).

Figure 11-4: Publish Web Site

At this stage a location dialog window will appear. Visual Studio provides us with several options we can
publish to a local IIS server (figure 11-5), a location on the file system (figure 11-6), a remote FTP site (figure
11-7) or a Remote web location (FrontPage Server Extensions is required) (figure 11-8).

Tip: Click the (…) button on the Publish Web Site dialog window to see the Publish Web Site window below.

Figure 11-5: Select a IIS location Figure 11-6: Select a File System location

422
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 11-7: Select a FTP location Figure 11-8: Select a remote location

In this example we will be publishing to a local IIS server. Select a location to publish (figure 11-5) then select
open. The Publish Web Site dialog window will appear. We can select a location to deploy here.
There are three checks boxes available. The “Allow this precompiled site to be updatable” option allows the
content of the .aspx pages to remain as it is. This allows us to update the HTML code after deploying to a Web
location. This is typically used by ASP.NET Web form application.
The second option is “Use fixed naming and single page assemblies”. This option specifies that we will not
be compiling in batch mode during precompiling as a result we can generate assemblies with fixed names.
The last option is “Enable strong naming on precompiled assemblies”. This option specifies that the
generated assemblies are to be strongly named using a key file. Strong naming a assembly ensures that they will
not be tampered with. If we select this option we can specify a key file or a key container.

After choosing the required options, click OK to continue the deployment process.

Figure 11-9: Enter a location to publish the Web Service

Selecting OK will publish our Web Service to the desired location.

423
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 11-10: Deployed employee service

It is usually a good idea to test the service after the Web service has been deployed. Simply click on one of
the Web method and .NET will generate a test harness as long as the parameters used are primitive .NET types.
In our case we can easily enter a number into the EmployeeID field to test the Web method (see figure 11-11).

Figure 11-11: Testing the deployed service

The WSDL document for the deployed Web service can be located by appending the ?wsdl after the .asmx
extension (see Figure 11-12).

424
The Complete Reference To Professional SOA with Visual Studio 2005

http://localhost/soawebservice/deploy/employee/employee.asmx?wsdl

Figure 11-12: WSDL for the Employee Web service

The discover document for the deployed Web service can be located by appending a ?disco after the .asmx
extension (see Figure 11-13).
http://localhost/soawebservice/deploy/employee/employee.asmx?disco

Figure 11-13: Discovery document for the Employee Web service

425
The Complete Reference To Professional SOA with Visual Studio 2005

Publishing Client Application using ClickOnce Deployment


ClickOnce is a new deployment technology in .NET Framework 2.0. ClickOnce allows us to deploy and run
application from a Web page making it very convenient in today’s distributed architecture. As the name suggests
provides a one click solution to deployment with minimal user interaction.
A ClickOnce application can be published through medias such as Web page, a network file sharing or from
disk medias such as CD-ROM or Flash drives. A ClickOnce application can be installed locally onto a client’s
computer from a Web page. These applications typically are Windows Form application or Console application
and they will continue to run locally even when the computer is offline. The ClickOnce application can also be
ran in an online-only mode without permanently installing anything on the end user’s computer.
In configuring an application for ClickOnce deployment a developer can easily specify the update behaviors
of the application. Applications deployed through ClickOnce can automatically check for newer versions as they
become available and automatically install the required files. A network administrator can also control update
strategies such as ensuring that automatic update for an application is fixed and binding. Both the end user and
administrator have the ability to roll back updates of a deployed application to a previous version.
Applications deployed through ClickOnce deployment are isolated. These applications are self contained
and each application is installed to and ran from a secure per user, per application cache. This ensures that the
application will not break any existing applications. Security wise each application runs within the Internet and
Intranet security boundary. Application can also request to elevate their security permissions.
ClickOnce deployment resolves three inherent issues in application deployment. These are:

* Application update. In the past whenever an application is updated the user must reinstall the entire
application. The key with ClickOnce deployment is that applications can be automatically configured so that
they can check for updates as they become available. Only portions of the application that have changed are
downloaded and installed.

* Low impact. In the past applications deployed through Windows Installer often relied on shared components.
Which could potentially result in version conflicts. ClickOnce deployment offers a self-contained per user, per
application cache which means your application can not interfere with other applications.
* Security. In the past installing applications through Windows Installer required administrative permissions and
allows only limited user installation. In ClickOnce deployment non-administrative users are granted rights and
Code Access Security permission necessary for the application.

In the past, these issues often caused developers to decide to create Web applications rather than Windows-based
applications, sacrificing the rich user interface and responsiveness of Windows Forms for ease of installation.
With applications deployed using ClickOnce, we can now achieve the best of both technologies.

ClickOnce and Windows Installer Comparison Table

The following table compares the features of ClickOnce deployment with Windows Installer deployment:

Table 11-1: Comparison between ClickOnce deployment and traditional Windows Installer

Feature ClickOnce Windows Installer

Automatic update Yes Yes


Post-installation rollback Yes No

426
The Complete Reference To Professional SOA with Visual Studio 2005

Update from Web Yes No


Does not affect shared components or Yes No
other applications
Security permissions granted Grants only permissions necessary for the Grants Full Trust by default
application (more safe) (less safe)
Security permissions required Internet or Intranet Zone (Full Trust for CD- Administrator
ROM installation)
Application and deployment manifest Yes No
signing
Installation-time user interface Single prompt Multipart Wizard
Installation of assemblies on demand Yes No
Installation of shared files No Yes
Installation of drivers No Yes (with custom actions)
Installation to Global Assembly Cache No Yes
Installation for multiple users No Yes
Add application to Start menu Yes Yes
Add application to Startup group No Yes
Add application to Favorites menu No Yes
Register file types No Yes
Install time registry access Limited Yes
Binary file patching No Yes
Application installation location ClickOnce application cache Program Files folder

Using ClickOnce Deployment


In the following section we will walk through the steps required in creating a ClickOnce deployment application.
Using ClickOnce deployment is quite straight forward. Simply open the project that we wanted to deploy in our
case we can open the EmployeeClient we had built in Chapter 9 which was used to access an employee web
service.

Figure 11-14: Publishing using ClickOnce

Publishing to File System


Select Build Menu -> Publish <Project Name> (see figure 11-14).

427
The Complete Reference To Professional SOA with Visual Studio 2005

We should Build the solution first to make sure that everything is in working order first. Click the menu option
to publish our solution. (see figure 11-15).

Figure 11-15: Publish the application to a location

One decision that we need to consider is where we’d like our user to install our ClickOnce application from. We
can deploy application to either, File System, Local IIS, FTP Site or Remote Site (see figure 11-16). To specify
another location simply click on the browse button. Select next when complete. ClickOnce has great support for
different locations. In this case, we will select the File System click "Next" to accept the location.

Figure 11-16: Specifying a location.

428
The Complete Reference To Professional SOA with Visual Studio 2005

ClickOnce deployments allows us to deploy applications to a Web site, a Network location or onto a CD-
ROM. In this example we will be deploying to disk, select From a CD-ROM or DVD-ROM. Enter your
preferred location to deploy to. (You will need to have IIS installed for this to work). (see figure 11-16)

Figure 11-17: Specify how user will install the application

Click Next to continue. We will be asked if we want our application to automatically check for updates. We
can specify the location from which the application periodically checks (see figure 11-18).

Figure 11-18: Specify whether the application will check for updates.

Click Next and Finish will automatically deploy the application to file system. We can see the setup files
created in figure 11-19.

429
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 11-19: Created ClickOnce Files.

Publishing To a Web Location

Figure 11-20: Publishing to a web location

Since we are publishing the ClickOnce deployment application to a Web location we will be prompted
whether this application will be available online or offline (see Figure 11-20). The default online or offline
deployment mode will automatically create a start button menu shortcut and an uninstall option in windows. It
will also link our project to a web page location. In this example we will select “yes, this application is available
online or offline” mode. Select Next followed by Finish to publish the application to an online location.

430
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 11-21: ClickOnce deployment web page

ClickOnce automatically starts the default browser with the generated page once we have completed the
ClickOnce publish process (see Figure 11-21). Clicking the Install button will call the setup.exe automatically to
start the setup process (see Figure 11-22). Or we can execute the Setup.exe ourselves get the same result. Both
setup.exe and publish.htm are in the root of the directory for the web page. Unless we have a security certificate,
we will get a security warning screen that we will need to confirm the installation (see Figure 11-23).

Figure 11-22: Launch notification

431
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 11-23: Security warning if we’re not using security certificates.

How ClickOnce Deployment Works


At the heart of ClickOnce deployment architecture are two XML manifest files. These are the application
manifest and the deployment manifest files.
The application manifest is used to describe the application. These include assembly information,
application dependencies, required permissions, and the location where updates will be available. A developer
can create an application manifest by using the Publish Wizard tool in Visual Studio 2005 or using the .NET
Framework tool Mage.exe the .NET manifest generation tool.
The second manifest file is the deployment manifest file that describes how the application should be
deployed. It contains information about the location of the application manifest and the version of the application
that the client need to run. Developers can create the deployment manifest using the manifest generation tool
(Mage.exe) in the .NET Framework SDK (see Figure 11-24).

Figure 11-24: Mage can be used to modify the manifest

After the deployment manifest is created it is copied to the deployment location. This can be a Web server, a
network file share, or media such as a CD ROM. Application manifest and the application files can also be
copied to the same deployment location or a different location that is specified within the deployment manifest.
When we’re performing the deployment through the Visual Studio 2005 Publishing Wizard the operation is
performed automatically.
After deploying the ClickOnce application to the specified location, the end users can install the application
by clicking on a install icon from the Web page (see Figure 11-21) or from a deployed folder. In most cases, the
end user is presented with a simple dialog box asking the user to confirm installation Figure 11-23, after which
installation proceed and the application is launched without further intervention. In cases where application
requires additional security permissions, the user will be prompted to grant permission before the installation is
allowed to continue.
Once the application has been installed an icon will be added to the user’s Start menu and to the
Add/Remove Programs group in Control Panel. Unlike previous deployment technologies no additional files will
be added under Program Files Folder or records added into the registry or desktop. ClickOnce is a completely
isolated deployment and execution environment.

432
The Complete Reference To Professional SOA with Visual Studio 2005

Using Web Deployment Projects with Visual Studio


2005
While deployment using Copy Web Site and Publish Web Site features are quite simple to use and provide an
efficient means of deploying applications. There are times when we need to do more. There are several reasons:

* Requirement for more control over assemblies and output,

* Creating custom pre-processing and post-processing actions for the build,


* Capability to add, exclude and transform files and directories during build.
* The ability to alter database connection string, application settings or even URL references that is stored in the
Web.config depending on the build mode that we choose. These modes maybe for development, testing,
staging and release based. Each mode may contain a different set of values.

We can achieve this through the use of Web Deployment Projects add-in with Visual Studio 2005. The Web
Deployment Projects add-in package itself does not change the behavior of any features in Visual Studio 2005. It
simply provides additional functionality specific to Web site deployment.
The Web Deployment project is integrated into the Visual Studio 2005 build configuration manager. It
supports build modes such as Debug and Release used for compilation and deployment. The Web deployment
project can be extended to allow us to create pre-build and post-build actions.
The Web Deployment project does not change the way Visual Studio 2005 build projects. It takes an
existing Web site project and generates a precompiled Web project as output. The build process does not change
the source files in the Web site project in anyway. It is this precompiled Web project that we can use in our
Visual Studio 2005 setup project to deploy Web based applications. We will be looking at how to create
deployable Setup Projects using the precompiled web site later in this chapter.
In this section we will be looking into the Web Deployment Projects for Visual Studio 2005.

Installing Web Deployment Projects


In order to use Web deployment projects we need to install WebDeploymentSetup.msi
(WebDeploymentSetup.msi can be downloaded from Microsoft Web site using WebDeploymentSetup.msi as the
keyword for search). Installing Web Deployment projects installs both a Visual Studio 2005 add-in package and
the new ASP.NET merge utility (aspnet_merge.exe).
By default, the installation process installs files into the locations listed in the following table.

Table 11-2: Output for Web Deployment Project

Location Files

C:\Program Files\MSBuild\Microsoft\WebDeployment\v8.0 aspnet_merge.exe


Microsoft.WebDeployment.targets
Microsoft.WebDeployment.Tasks.dll

C:\Program Files\Microsoft Visual Studio MsWebDeployProj.dll


8\Common7\Packages
WebDeploy.wdproj

433
The Complete Reference To Professional SOA with Visual Studio 2005

C:\Program Files\Microsoft Visual Studio MsWebDeployProjUi.dll


8\Common7\Packages\1033

Build Menu Command

Figure 11-25: New option

Installing Web Deployment Projects adds the Add Web Deployment Project command to the Build menu (see
Figure 11-25) and to the shortcut menu for the selected Web project in Solution Explorer. The new command is
supported only for local IIS Web sites and for file system Web sites. Web Deployment Projects do not support
remote FrontPage or FTP Web sites.

1. From the Build menu select Add Web Deployment Project (see Figure 11-25).

Figure 11-26: Deployment Project Name

2. Specify a name and location for the project then select OK. By default, the project name is the same as
the Web site with _deploy appended to the name. The default location is in the same folder as the
solution. The project file in our case will be named Employee_deploy.webdeployproj, and the project
folder path will be C:\Projects\Book\SourceCode\Ch11\Employee_deploy.

434
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 11-27: Web deployment project

3. A new project is added to the solution and automatically associated with the Web site. The new Web
Deployment project is now part of the build process. The new Web Deployment project does not
contain any files or child nodes in the solution hierarchy. Instead, it is an MSBuild project file that
enables us to customize the build rules for the associated Web site.
4. Right click on the Employee deploy project within the Solution Explorer. Select Property Pages.

Web Deployment Project Property Pages


We can create custom configurations for the Web Deployment project by using the Property pages diaglog box. The
dialog box is available by right-clicking the project in Solution Explorer and then selecting Property Pages. There are
four property pages dialog boxes for Web Deployment. These are:

* Compilation
* Output Assemblies

* Signing

* Deployment

435
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 11-28: Compilation

The advantage of using Web Deployment Project is that we can specify unique values for each of the build
configurations. We can use the predefined build configuration of Debug and Release in Visual Studio 2005 or
we can define new configuration for example for staging, and production. The changes we make within each of
the four property pages will be specified only for that selected build configuration. This provides the developer
with more flexibility when configuring to deploy application.
The Compilation page (see figure 11-28) is used to provide information on how the Web project should be
compiled and where to put the precompiled output. The page properties are shown in Table 11-3

Table 11-3: Compilation property

Setting Description

Output folder This is folder which will contain the precompiled image of the Web project.

Generate debug information Select this option to generate debug information when compiling. This setting
will also update the <compilation debug="true"/> element in the configuration
file of the precompile Web project.

Use IIS Metabase path for During compilation, if there are sub-Web sites this will result in build errors.
source input By enablying to use IIS Metabase path which will cause the compiler to skip
sub-Web sites defined in the IIS metabase. To compile the sub-Web sites, we
must add a separate Web Deployment project for each of the sub-Web sites.

Allow this precompiled site to This option is used for ASP.NET Web form. It allows HTML component of
be updatable the aspx and ascx pages to be updated after compiling so that only the code-
behind files are compiled.
The Output Assembly page is used to customize precompiled Web project assemblies. The Output
Assembly properties are shown in Table 11-4

Figure 11-29: Output Assemblies

436
The Complete Reference To Professional SOA with Visual Studio 2005

Setting Description

Merge all outputs to a single This option merges all output assemblies from the compiler into a single
assembly assembly. This is similar to using the aspnet_merge.exe –o assemblyname
option.

Treat as library component This option will remove the App_code.compiled file. This allows a project’s
App_Code.dll assembly to be added to another Web site without conflict. It
is useful for building a library of .ascx controls. This is equivalent to using
aspnet_merge.exe –r command.

Merge each individual folder This option will create a separation output assembly for each folder. This
output to its own assembly allows us to update a Web Project at the folder level rather than the entire
application.

Merge all pages and controls to a This option merges all output assemblies for all pages and user controls in a
single assembly Web project into a single assembly. We can use the assembly to update UI
components separately.

Create a separate assembly for This option creates separate assemblies for each page and user control.
each page and control output

Version Output Assemblies Selecting Version Output Assembly will enable the Asembly Version and
File Version. We can set the Assembly Version and File Version in the
Assembly Version
following format. The format is 0.0.0.0.
File Version
The version information specified will override the setting information
defined within AssemblyInfo.vb or AssemblyInfo.cs file.

Table 11-4: The table above describes the properties of the Output Assemblies page.

Properties of the signing page are only enabled if we select Enable strong naming see figure 11-30 the
property of the page is shown in Table 11-5. Singing an assembly ensures that the assembly is free from
tempering.

437
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 11-30: Signing property page.

Table 11-5: The table shows the properties within the Signing section.

Setting Description

Key file location After enabling strong naming we can specify a keyfile used for
signing the assembly. We can generate the key file using the
sn.exe utility included with the .NET Framework SDK.
Delay signing Delay signing allow us to compile assemblies with delay signing.
This allows the assemblies to be signed after the build process.
Mark assemblies with This allows types in the strongly named assembly to be called by
AllowPartiallyTrustedCallersAttribute partially trusted code only when the assembly is marked with
(APTCA). AllowPartiallyTrustedCallersAttribute. This removes the
automatic demand for Full trust permission.

The deployment page figure 11-31 is used to customize various deployment configuration. This allows us to
adjust certain configuration in Web.config for deployment setup. We can also automatically create an IIS virtual
directory. Properties for the deployment page is show in table 11-6.

Figure 11-31: Deployment property screen

Table 11-6: The following table describes the properties that we can set in the Deployment page.

Setting Description

Enable Web.config file section By enabling the Web.config file section replacement we can replace any
replacement section in the root Web.config file with the matching content in a separate
external .config file. We can use this option to provide configuration
settings for the deployed environment.

438
The Complete Reference To Professional SOA with Visual Studio 2005

Enforce matching section This option requires that the specified section in the Web.config file
replacements matches the number of elements in the external .config file. A build error
occurs if the two do not match.
Use external configuration source file This option is useful for changing database connecting strings or
references for different build configurations.
This option replaces elements using configSource reference with .config
file. configSource attribute can be in the format of:
<appSettings configSource="appSettings.config" />
If this option is not selected the entire section is replaced with the .config
file.
Create an IIS virtual directory for the This option when selected will automatically create an IIS virtual directory
output folder that will point to the output folder for the specified build configuration. To
avoid conflict we should adopt the naming convention for example such as
MyWeb_Staging and MyWeb_Release.
Replace the existing virtual directory This option allows us to replace an existing virtual directory. For example
if a virtual directory already exists we can override it to point to a different
output location.
Remove the App_Data folder from This option removes the App_Data from the precompiled image of the
the output location Web project. This is useful if we’re not requiring a SQL Server Express,
Access or MSDE in the App_Data folder.

Managing Custom Build Configurations


We can define several build configurations using Visual Studio. These build processes are necessary for
producing Debug, Staging and Release builds for Web application. We can customize each configuration. The
three main build configuration commonly used for Web applications are:

* Debug build configuration. Debug build is commonly used by developers during design time to test and
check the Web Application. In a typical team development enivornment when multiple developers are working
on the same project. To avoid impacting development and overwriting each other’s code each developer can set
their own custom settings for their development environment. These may be local resources such as a local
SQL Server database, or a local IIS Web reference which points to http://localhost/....
* Staging build configuration. The staging environment is often a replica of the production or release
environment. We can adjust our configurations to connect to the staging environment. This may mean rather
than connecting to a local database during the debug build we may be connecting to a shared database
containing test data. While Web services and Web Form applications may also be distributed onto different
servers in the staging environment.

* Release build configuration. The Web project is deployed onto a production release environment after it has
been thoroughly tested on the staging environment. The release build means we would no longer require the
debug information that may have been required on the staging build. We can adjust the Debug mode within the
Web.config file by setting it to false.

439
The Complete Reference To Professional SOA with Visual Studio 2005

The benefit of using the Web Deployment projects is that it allows us to add and customize so many
differerent variables for each of the specific builds. We can tailor our environment variables into each of the
build configuration. This helps to lower the risk of deployment errors from misconfigured environment settings.
The property values that we specify within Web deployment project apply only to the specific build
configuration. We can easily change a build configuration for a specific build by changing the required property.
For global properties we can also select All Configurations, which we can apply to change settings globablly
across all configurations.
To change or create a new configuration, in the project Property Page dialog window select Configuration
Manager. The Configuration Manager dialog window will appear (see figure 11-32). By selecting Active
solution configuration drop down list and selecting <New…> we can define a build option for deployment. The
Configuration Manager dialog box allow us to create new configurations and to specify which projects to build
as part of that configuration.

Figure 11-32: Select a New build configuration

In the following example we will create a setting for staging. By selecting <New…> under Active Solution
Configuration. A dialog window will appear (see figure 11-33). We will be prompted to set the name of the
configuration. We can also simplify the configuration process by letting the configuration manager to copy
existing settings defined for Release. Once complete select OK.

440
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 11-33: Create a new staging build

After defining the settings for staging we can see that the new configuration is now active in the
Configuration Manager. In the case of multiple projects we can also specify which project to build for the
specific build configuration (see figure 11-34).

Figure 11-34: Staging build configuration.

Tip: We should also remember to disable building the Web Deployment project in the Debug configuration. Building a Web Deployment
project unnecessarily increases the time it takes to build a solution or start a debug session. We should enable building the Web
Deployment project only in solution configurations intended for deployment builds.

When we sepecify the build configurations we should keep in mind that build configuration for Web projects
should be optimized for developers productivity. When we create our solution configurations, we should build

441
The Complete Reference To Professional SOA with Visual Studio 2005

either the Web site project or the Web Deployment project, but not both. See table 11-7 for suggestion towards
different build solution configurations.

Table 11-7: Build configuration

Solution configuration

Build strategy Debug Staging Release

Build Web site project True False False

Build Web Deployment project False True True

To specify the solution configuration to use when we build, select the configuration name from the Solution
Configurations list on the toolbar:

Figure 11-35: Build options in the project.

When we have our build configurations established, we can initiate a build for any configuration. There are two
ways to build a Web Deployment project from within Visual Studio 2005 or from the command line using
MSBuild.
The files generated for this build are in the MyWeb_deploy\Release folder. Note the single output assembly
MyCompany.MyWeb.dll.

Location Files

C:\Projects\Book\SourceCode\Ch11\Employee_deploy\Re Employee.asmx
lease
PrecompiledApp.config
web.config
C:\Projects\Book\SourceCode\Ch11\Employee_deploy\Re App_Code.compiled
lease\bin
Employee_deploy.dll

Table 11-8: Web deployment project output

Web Setup Projects


In this section we will learn to deploy Web projects by creating a MSI setup file. Visual Studio provides four
types of projects types for deployment. These are: Setup project, Web Setup Project, Cab project and Merge
Module. In Visual Studio 2005 there is now a Setup wizard which we can use to help us create a deployment
project. We can see the templates and the wizard in the New Project dialog box under the Setup and Deployment
Projects node.

442
The Complete Reference To Professional SOA with Visual Studio 2005

The following are guidelines for choosing the right type of deployment project for our project (see Table 11-9).

Table 11-9: Setup project types

Project Type Purpose

Merge Module Project Merge Module Projects are used to package files or components that will be shared
between multiple applications. The project will careate a a merge module (.msm) file
that includes all resource files, registry entires and setup logic for the component.

Setup Project We can use Setup project to create installers for Windows based applications.

Web Setup Project The Web Setup Project can help with the deployment of Web projects whether its
WebForm or Web services. We can specify where the files should be installed on the
target machine, set special conditions or requirements for installation and set custom
actions to be performed on the target machine.

Cab Project We can use Cab Project to create a cabinet file (.cab). A cabinet file can contain a
number of files but does not contain any installation logic. It is used to package
components into a single file can be distributed for installation.

Creating a Web Setup Project for XML Web Service


In this section we will be looking at creating a deployment project for a XML Web service we had constructed
for Employee in Chapter 9.
We will attempt to deploy the Employee web service project by using a Web Setup project. To create a Web
Setup project, use the following procedure continuing from the previous example of Employee Web Deployment
Project:
1. From the File menu, point to Add, and click New Project. The Add New Project dialog box appears.

2. In the Add New Project dialog box, select “Setup and Deployment Projects” under the Project Types pane
(Figure 11-36).

443
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 11-36: Web Setup Project

Note: The screenshot may vary depending on the edition of Visual Studio

3. In the Templates pane, select Web Setup Project.

4. In the Name box, type WSEmployeeSetup and click OK. Select “Add to Solution” from the Solution dropdown
list. This will add the Web setup project to the Web service project (Figure 11-37).

Figure 11-37: WSEmployeeSetup Project

5. Once the Setup web project has been added to the existing Employee Web service project. Right click on the
setup project in the solution explorer. Select Add-> Project Output from the context menu (Figure 11-38).

444
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 11-38: Add Project Output

6. In the Add Project Output Group dialog box, ensure that the Employee_deploy project is selected in the Project
dropdown list. From the list, select the “Precompiled Web Outputs” option and then click OK. Figure 11-39
shows the Add Project Output Group dialog box.

Figure 11-39: Add Project Output

445
The Complete Reference To Professional SOA with Visual Studio 2005

7. As shown in Figure 11-40 the precompiled web deployment output from Employee_deploy is now attached to
the WSEmployeeSetup project.

Figure 11-40: Precompiled Web Outputs

8. We can specify Prerequisites for the project by right mouse click on the WSEmployeeSetup project and
selecting Properties (Figure 11-41). When the dialog window appears select the Prerequisites button. This
option allows us to check that the prerequistes required for the application are specified.

Figure 11-41: Prerequisites for the application.

9. By building the setup project the two setup files will be created automatically. One of the file will be an EXE
setup file while the other is a MSI file (Figure 11-42).

446
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 11-42: Setup output

Summary
The Visual Studio provides various features and tools that we can use to deploy applications. These features and
tools allow us to deploy different types of applications to a large number of users. These features include no-
impact installation, private components, side-by-side execution, enterprise deployment, controlled code sharing,
on-the-fly updates, downloading and caching, and XCopy deployment.
In this chapter we have also looked at ClickOnce deployment. ClickOnce is a new application deployment
technology that makes deploying a Windows Forms based application as easy as deploying a web application.
With “ClickOnce” running a Windows Forms application is as simple as clicking a link in a web page. For
administrators, deploying or updating an application is simply a matter of updating files on a server; no need to
individually touch every client.
We have also looked at deploying a Web service using Web Deployment Project to precompile the
assemblies. Web Deployment Project is an add-in for Visual Studio 2005. It allows us to precompile our Web
service application while it is flexible enough to allow for customization for different build cenarios.
Using Visual Studio’s Web Setup project we can then create and deploy the precompiled assemblies. Visual
Studio provides Web Setup project as a way to build and deploy applications into MSI files. Visual Studio comes
with templates for four types of deployment projects: Merge Module Project, Setup Project, Web Setup Project,
and Cab Project.

* Merge Module Project - Packages components that might be shared by multiple applications.
* Setup Project - Builds an installer for a Windows-based application.

* Web Setup Project - Builds an installer for a Web application.


* Cab Project - Creates a cabinet file for downloading to a legacy Web browser.

447
The Complete Reference To Professional SOA with Visual Studio 2005

Chapter 12 Advanced Web


Service Programming
In previous chapters we have created simple XML Web services. In this chapter we will be looking at more
advanced techniques and Web service implementations.
We will be looking into modifying the properties of the WebMethod attribute that is used to define a method
within a Web service. In addition we will also look at how to implement asynchronous XML Web services calls.
And how we can use SOAP extensions to access and modify the SOAP messages that the XML Web services
send to and receive from client applications.

WebMethod Properties
There are six properties commonly used by the WebMethod. These properties control the way the WebMethod
behave over the web. These are:

* BufferResponse – The BufferResponse property allows us to buffer responses for a WebMethod to improve the
performance of an application by reducing communication between the worker processes and the IIS process.

* CacheDuration - The CacheDuration property of the WebMethod attribute enables us to cache the results for a
Web method for a specified period.
* Description - The Description property allows us to specify a description for a Web method. The description
that we specify using the Description property appears on the Service Description
* EnableSession – The Web service itself is stateless though with .NET we can configure a Web method to
maintain the state of objects across sessions. The EnableSession property of the WebMethod attribute allows us
to enable the session state for a Web method.

* MessageName - The MessageName property can be used to it is used to uniquely identify overloaded Web
methods. The MessageName property allows us to use an alias to uniquely identify Web methods in an XML
Web service.
* TransactionOption - We can use a WebMethod to support transactions and enable a Web Method to participate
as the root object of a transaction.

In the following section we will look at how these properties can be used to customize and control the behavior
of the methods exposed within the Web service.

Buffering Response for a Web Method


We can buffer responses for a Web method to improve the performance of an application by reducing
communication between the worker process and the IIS process. To buffer responses for a Web method, we can
use the BufferResponse property of the WebMethod attribute. The ASP.NET can buffer all responses before
responding to the client this is activuated by setting the BufferResponse property to True. The result is that the
response is serialized into a memory buffer until either the response is completely serialized or the buffer is full.
Once the response is buffered, it is returned to the consuming XML Web service client over the network.

448
The Complete Reference To Professional SOA with Visual Studio 2005

If we set the BufferResponse property to False, ASP.NET buffers the responses in chunks of 16 KB each.
The response to the XML Web service method is sent back to the client as it is serialized. The default value of
the BufferResponse property is True. The following Microsoft Visual Basic .NET and Microsoft Visual C# code
samples show how to use the BufferResponse property (see listing 12-1 and listing 12-2).

Listing 12-1. Demonstrates a program using Buffered and Unbuffered properties in Web service. Using C#

using System;
using System.IO;
using System.Collections;
using System.Xml.Serialization;
using System.Web.Services;
using System.Web.Services.Protocols;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service {

[WebMethod(BufferResponse=true)]
public TextFile GetFileBuffered(string filename) {
return new TextFile(filename);
}

[WebMethod(BufferResponse=false)]
public TextFile GetFileUnbuffered(string filename)
{
return new TextFile(filename);
}

public class TextFile {


public string filename;
private TextFileReaderWriter readerWriter;

public TextFile() {
}

public TextFile(string filename) {


this.filename = filename;
}

[XmlArrayItem("line")]
public TextFileReaderWriter contents {
get {
readerWriter = new TextFileReaderWriter(filename);
return readerWriter;
}
}

public void Close() {


if (readerWriter != null) readerWriter.Close();

449
The Complete Reference To Professional SOA with Visual Studio 2005

}
}

public class TextFileReaderWriter : IEnumerable {

public string Filename;


private StreamWriter writer;

public TextFileReaderWriter() {
}

public TextFileReaderWriter(string filename) {


Filename = filename;
}

public TextFileEnumerator GetEnumerator() {


StreamReader reader = new StreamReader(Filename);
return new TextFileEnumerator(reader);
}

IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}

public void Add(string line) {


if (writer == null)
writer = new StreamWriter(Filename);
writer.WriteLine(line);
}

public void Close() {


if (writer != null) writer.Close();
}

public class TextFileEnumerator : IEnumerator {


private string currentLine;
private StreamReader reader;

public TextFileEnumerator(StreamReader reader) {


this.reader = reader;
}

public bool MoveNext() {


currentLine = reader.ReadLine();
if (currentLine == null) {
reader.Close();
return false;
}
else
return true;
}

450
The Complete Reference To Professional SOA with Visual Studio 2005

public void Reset() {


reader.BaseStream.Position = 0;
}

public string Current {


get {
return currentLine;
}
}

object IEnumerator.Current {
get {
return Current;
}
}
}

Listing 12-2. Demonstrates a program using Buffered and Unbuffered properties in Web service. Using Visual Basic 2005

Imports System
Imports System.IO
Imports System.Collections
Imports System.Xml.Serialization
Imports System.Web.Services
Imports System.Web.Services.Protocols

Public Class Service

<WebMethod(BufferResponse:=True)> _
Public Function GetFileBuffered(ByVal filename As String) As TextFile
Return New TextFile(filename)
End Function

<WebMethod(BufferResponse:=False)> _
Public Function GetFileUnbuffered(ByVal filename As String) As TextFile
Return New TextFile(filename)
End Function

End Class

Public Class TextFile


Public filename As String
Private readerWriter As TextFileReaderWriter

Public Sub New()


End Sub

Public Sub New(ByVal filename As String)


Me.filename = filename
End Sub

<XmlArrayItem("line")> _

451
The Complete Reference To Professional SOA with Visual Studio 2005

Public ReadOnly Property contents() As TextFileReaderWriter


Get
readerWriter = New TextFileReaderWriter(filename)
Return readerWriter
End Get
End Property

Public Sub Close()


If Not (readerWriter Is Nothing) Then
readerWriter.Close()
End If
End Sub
End Class

Public Class TextFileReaderWriter


Implements IEnumerable

Public Filename As String


Private writer As StreamWriter

Public Sub New()


End Sub

Public Sub New(ByVal myfilename As String)


Filename = myfilename
End Sub

Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator


Dim reader As StreamReader = New StreamReader(Filename)
Return New TextFileEnumerator(reader)
End Function

Public Sub Add(ByVal line As String)


If (writer Is Nothing) Then
writer = New StreamWriter(Filename)
End If
writer.WriteLine(line)
End Sub

Public Sub Add(ByVal obj As Object)

End Sub

Public Sub Close()


If Not (writer Is Nothing) Then writer.Close()
End Sub

End Class

Public Class TextFileEnumerator


Implements IEnumerator
Private currentLine As String

452
The Complete Reference To Professional SOA with Visual Studio 2005

Private reader As StreamReader

Public Sub New(ByVal reader As StreamReader)


Me.reader = reader
End Sub

Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext


currentLine = reader.ReadLine()
If (currentLine Is Nothing) Then
reader.Close()
Return False
Else
Return True
End If
End Function

Public Sub Reset() Implements IEnumerator.Reset


reader.BaseStream.Position = 0
End Sub

ReadOnly Property Current() As Object Implements IEnumerator.Current


Get
Return CurrentLine
End Get
End Property
End Class

In the example above listing 12-1 and listing 12-2 we have two exposed WebMethod. These are:
GetFileBuffered() and GetFileUnbuffered().
The GetFileBuffered() WebMethod has the property of BufferResponse defined set to true. When invoked the
GetFileBuffered() WebMethod will retrieve the contents of the requested file and buffer its response before
sending it to the client.
While the GetFileUnbuffered() has the BufferResponse set to false. When invoked the GetFileUnbuffered()
WebMethod will retrieve the contents of the requested file, the response of the WebMethod will not be buffered in
this instance.

Caching the Results for a Web Method


The CacheDuration property of the WebMethod attribute enables us to cache the results for a Web method. When
caching is enabled requests and responses are held in memory on the server. ASP .NET Framework caches
results for each unique parameter set for a specified duration. This duration is defined as the value of the
CacheDuration property (see listing 12-3 and listing 12-4). The default value of the CacheDuration property is
zero.

Tip: If we expect requests or responses to be very large and expect requests to vary widely. Then this may result in extensive amount of
data being cached which may not necessarily result in performance improvement.

Listing 12-3: The following code demonstrates the CacheDuration properties C#

using System.Web.Services;

453
The Complete Reference To Professional SOA with Visual Studio 2005

using System;
using System.Web;

public class Service : WebService


{

[WebMethod(CacheDuration = 60)]
public int ServiceUsage()
{
// If the XML Web service has not been accessed, initialize it to 1.
if (Application["MyServiceUsage"] == null)
{
Application["MyServiceUsage"] = 1;
}
else
{
// Increment the usage count.
Application["MyServiceUsage"] = ((int)Application["MyServiceUsage"]) + 1;
}

// Return the usage count.


return (int)Application["MyServiceUsage"];
}
}

Listing 12-4: The above codes demonstrates the CacheDuration properties Visual Basic 2005

Imports System.Web.Services
Imports System
Imports System.Web

Public Class Service


Inherits WebService

<WebMethod(CacheDuration:=60)> _
Public Function ServiceUsage() As Integer

' If the XML Web service has not been accessed, initialize it to 1.
If Application("MyServiceUsage") Is Nothing Then
Application("MyServiceUsage") = 1
Else
' Increment the usage count.
Application("MyServiceUsage") = CInt(Application("MyServiceUsage")) + 1
End If

' Return the usage count.


Return CInt(Application("MyServiceUsage"))
End Function
End Class

The above code listing 12-3 and listing 12-4 sets the CacheDuration property of the ServiceUsage Web
method to 60 seconds. When the CacheDuration is set ASP.NET will cache the request response based on the

454
The Complete Reference To Professional SOA with Visual Studio 2005

parameters. In this case the response of how frequently the application has been invoked is cached for a period of
60 seconds.
There are two issues that can affect output caching in an ASP.NET 2.0 Web service application.
In ASP.NET 2.0 the HTTP method of the test page has changed from GET to POST. However, POSTs are
not normally cached. If we change the test page in an ASP.NET 2.0 Web service application to use GET,
caching will work properly. As a such we cannot test the Web method directly from the test page. There is a
windows form project called TestCacheClient with the source code which allow us to test caching using SOAP
see Listing 12-5 and Listing 12-6. From the test application we can see that the result to the user request is
cached for 60 seconds.
In addition, HTTP indicates that a user agent (the browser or calling application) should be able to override
server caching by setting the "Cache-Control" to "no-cache". ASP.NET applications, therefore, ignore cached
results when they find a "no-cache" header.
The example below demonstrates the main logic within TestCacheClient. The application calls the web service
and invokes the ServiceUsage WebMethod using SOAP (see Listing 12-5 and Listing 12-6).

Listing 12-5. Invoking ServiceUsage WebMethod using C#

CacheWS.Counter cws = new CSTestCacheClient.CacheWS.Counter();


this.lblDisplay.Text = cws.ServiceUsage().ToString();

Listing 12-6. Invoking ServiceUsage WebMethod using Visual Basic 2005

Dim cws As CacheWS.Counter = New CSTestCacheClient.CacheWS.Counter


Me.lblDisplay.Text = cws.ServiceUsage.ToString()

Specifying a Description for a Web Method


The Description property allows us to specify a description for a Web method. The description that we specify
using the Description property appears on the Service Description and the Service help page. The Description
property takes a string as an input value. The following code displays how to use the Description property.
In the example below listing 12-7 and listing 12-8, the WebMethod is decorated with the description of
“Obtains the Server Computer Name”. It is used to describe the XML Web service method in the Service
Description and Service help page for the XML Web service.

Listing 12-7. Implementing Description property using C#

using System;
using System.Web.Services;

public class Desc : WebService


{
[WebMethod(Description = "Obtains the Server Computer Name")]
public string GetMachineName()
{
return Server.MachineName;
}
}

Listing 12-8. Implementing Description property using Visual Basic 2005

Imports System
Imports System.Web.Services

455
The Complete Reference To Professional SOA with Visual Studio 2005

Public Class Desc


Inherits WebService

<WebMethod(Description:="Obtains the Server Computer Name")> _


Public Function GetMachineName() As String
Return Server.MachineName
End Function
End Class

By adding a description property to the WebMethod we can see that the test Page generated by ASMX (see
figure 12-1 below) now contains the description displayed under the WebMethod.

Figure 12-1. Shows description attached to a WebMethod

The description property is also represented within the WSDL document as:
<wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">Obtains the Server Computer Name</wsdl:documentation>

Enabling Session State in Web Method


The Web service itself is stateless. This means that it does not keep information regarding the consuming
application. By using ASP.NET we can configure the Web service method to maintain the object states across
sessions by using the session state collection directly from HTTPContext.Current.Session namespace. We can
achieve this by setting the EnableSession property to True.
The session is maintained by an HTTP cookie which is returned by the XML Web service. Each XML Web
service consume is uniquely identified by the HTTP cookie returned. In order for the XML Web service to
maintain the session state each client must persist the cookie. Web service consumers can receive the HTTP
cookie by creating a new instance of the CookieContainer and assigning the object to the Web service proxy
class before calling the WebMethod.
If we need to maintain session state beyond when the proxy class instance goes out of scope, the client must
persist the HTTP cookie between calls to the XML Web service. For instance, a Web Forms client can persist the
HTTP cookie by saving the CookieContainer in its own session state.

456
The Complete Reference To Professional SOA with Visual Studio 2005

In listing 12-9 and listing 12-10 , we have decorated WebMethod with EnableSession property set to true.
This allows our WebMethod to access the underlying state management provided by ASP.NET.

Tip: The default value of the EnableSession property is False.

Listing 12-9. Implementing EnableSession using C#

using System.Web.Services;

public class Service : WebService


{
[WebMethod(Description = "Per session Hit Counter", EnableSession = true)]
public int SessionHitCounter()
{
if (Session["HitCounter"] == null)
{
Session["HitCounter"] = 1;
}
else
{
Session["HitCounter"] = ((int)Session["HitCounter"]) + 1;
}
return ((int)Session["HitCounter"]);
}
}

Listing 12-10. Implementing EnableSession using Visual Basic 2005

Imports System.Web.Services

Public Class Service


Inherits WebService

<WebMethod(Description:="Per session Hit Counter", _


EnableSession:=True)> _
Public Function SessionHitCounter() As Integer

If Session("HitCounter") Is Nothing Then


Session("HitCounter") = 1
Else
Session("HitCounter") = CInt(Session("HitCounter")) + 1
End If
Return CInt(Session("HitCounter"))
End Function
End Class

To consume a WebMethod using session we need to specify a session container to enable the application to keep
track of the Web service session. Using CookieContainer allows us to persist data within the same session. See
listing 12-11 and listing 12-12.

457
The Complete Reference To Professional SOA with Visual Studio 2005

Note: If we do not wish to persist data for the web service call we do not to implement support for cookie on the client application.

Listing 12-11. Implementing CookieContainer using C#

using System;
using System.Collections.Generic;
using System.Text;

namespace CSTestSessionClient1
{
class Program
{
static void Main(string[] args)
{
System.Net.CookieContainer cookieJar =
new System.Net.CookieContainer();

WSSession.Service wss =
new WSSession.Service();
wss.CookieContainer = cookieJar;
Console.WriteLine(wss.SessionHitCounter().ToString());
Console.WriteLine(wss.SessionHitCounter().ToString());
Console.WriteLine(wss.SessionHitCounter().ToString());
Console.ReadLine();
}
}
}

isting 12-12. Implementing CookieContainer using Visual Basic 2005

Module Module1

Sub Main()
Dim cookieJar As System.Net.CookieContainer = _
New System.Net.CookieContainer

Dim wss As WSSession.Service = New WSSession.Service()


wss.CookieContainer = cookieJar
Console.WriteLine(wss.SessionHitCounter.ToString())
Console.WriteLine(wss.SessionHitCounter.ToString())
Console.WriteLine(wss.SessionHitCounter.ToString())
Console.ReadLine()
End Sub

End Module

458
The Complete Reference To Professional SOA with Visual Studio 2005

Identifying Overloaded Web Methods Using an Alias


The MessageName property can be used to it is used to uniquely identify overloaded Web methods. The
MessageName property allows us to use an alias to uniquely identify Web methods in an XML Web service.
When we specify a value for the MessageName property, the SOAP messages use this value as the method name
instead of the actual method name. The following code sample displays how to use the MessageName property.
By default, MessageName is set to the name of the XML Web service method. Therefore, if an XML Web
service contains two or more XML Web service methods with the same name, we can uniquely identify the
individual XML Web service methods by setting the MessageName to a name unique within the XML Web
service, without changing the name of the actual method name in code.

Tip: if a WebMethod of the same name but different set of parameters need to be added to a Web service we should
give the new WebMethod a different MessageName and leave the original WebMethod to ensure compatibility with
existing consuming clients.

Listing 12-13. Implementing MessageName using C#

using System;
using System.Web.Services;

public class Calculator : WebService


{
// The MessageName property defaults to Add for this XML Web service method.
[WebMethod]
public int Multiply(int i, int j)
{
return i * j;
}
[WebMethod(MessageName = "Multiply2")]
public int Multiply(int i, int j, int k)
{
return i * j * k;
}
}

Listing 12-14. Implementing MessageName using Visual Basic 2005

Imports System
Imports System.Web.Services

Public Class Calculator


Inherits WebService

' The MessageName property defaults to Add for this XML Web service method.
<WebMethod()> _
Public Function Multiply(ByVal i As Integer, ByVal j As Integer) As Integer
Return i * j
End Function

459
The Complete Reference To Professional SOA with Visual Studio 2005

<WebMethod(MessageName:="Multiply2")> _
Public Function Multiply(ByVal i As Integer, ByVal j As Integer, ByVal k As Integer) As Integer
Return i * j * k
End Function
End Class

In the example above listing 12-13 and listing 12-14 we have a WebMethod which is overloaded with
another WebMethod. In Web service it is not possible to have two WebMethods of the same name. This results
in a conflict. One way around this is through the use of MessageName to specify an alias name. This helps to
distinguish between the two WebMethods. See Figure 12-2.

Figure 12-2: Overloaded WebMethod using MessageName

Web Method Transaction


We can use a Web method to support transactions and enable a Web method to participate as the root object of a
transaction, this is due to the stateless nature of the HTTP protocol. As such we can invoke COM objects that
participate in the same transaction as the XML Web service method.
Using the TransactionOption property we can specify whether we want the Web method to participate in a
transaction or not. The TransactionOption property can be set to the following states: Disabled, NotSupported,
Supported, Required, and RequiresNew. To support transactions and enable a Web method to participate as the
root object of a transaction, we can set TransactionOption to Required or RequiresNew. On the other hand, to
disable transaction support for a Web method, we can set TransactionOption to Disabled, NotSupported, or
Supported.

Table 12-1. TransactionOption states.

Item Description

Disabled By setting the TransactionOption state to Disabled the WebMethod will be executed without

460
The Complete Reference To Professional SOA with Visual Studio 2005

support for transaction. Any transaction in the current context will be ignored.
[WebMethod(TransactionOption= TransactionOption.Disabled)]
NotSupported The NotSupported state indicates that the WebMethod will not run within the scope of a
transaction. The WebMethod will be executed in a context with no governing transaction.
[WebMethod(TransactionOption= TransactionOption.NotSupported)]
Supported The Supported state indicates that the WebMethod will share a transaction if it exists.
[WebMethod(TransactionOption= TransactionOption.Supported)]
Required The Required state indicates that the WebMethod requires a transaction. A new transaction
will be created for the WebMethod if no transaction exists otherwise if transaction exist it
will be shared.
[WebMethod(TransactionOption= TransactionOption.Required)]
RequiresNew The RequiresNew state indicates that the WebMethod requires a new transaction regardless
of the state of the current context. When a request is received the WebMethod is created
within a new transaction.
[WebMethod(TransactionOption= TransactionOption.RequiresNew)]

XML Web service transactions can only participate in Transactions as the root of a new transaction. XML
Web service methods that call other XMLWeb service methods participate in different transactions. This is
because transactions do not flow across XML Web service methods.
When using transactions with ASP.NET XML Web service we can declare the Web method’s transactional
behavior by setting the TransactionOption property of the WebMethod Attribute. If an exception is thrown while
the WebMethod is executing the transaction is automatically aborted otherwise if no exception occurs the
transaction is automatically committed.
To enable Web methods to support transactions, we need to add reference to the System.EnterpriseServices
namespace. This namespace contains the methods and properties that expose the distributed transaction model in
COM+ services. The ContextUtil class of the System.EnterpriseServices namespace allows us to control a
transaction using the SetAbort or SetComplete method.
The following example listing 12-15 and listing 12-16 demonstrates using TransactionOption.

Listing 12-15. implementing TransactionOption using C#.

using System;
using System.Web.Services;
using System.EnterpriseServices;

public class Bank : WebService


{
[WebMethod(TransactionOption = TransactionOption.RequiresNew)]
public void BankTransfer(long Amount,
long AcctNumberTo, long AcctNumberFrom)
{
//bank logic here
ContextUtil.SetComplete();
//if invalid we can set ContextUtil.SetAbort();
}
}

461
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 12-16. implementing TransactionOption using Visual Basic 2005

Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.EnterpriseServices

<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class Bank
Inherits System.Web.Services.WebService

<WebMethod(TransactionOption:=TransactionOption.RequiresNew)> _
Public Sub BankTransfer(ByVal Amount As Long, _
ByVal AcctNumberTo As Long, ByVal AcctNumberFrom As Long)
'bank logic here
ContextUtil.SetComplete()
'if invalid we can set ContextUtil.SetAbort()
End Sub

End Class

Asynchronous Web service


Asynchronous implementation is used to allow applications to execute a method without waiting for it complete.
This is very useful in a distributed architecture, because the inherent nature of the Internet, the response time
between request and response can vary greatly. As such we do not want our program to wait for the method to
return.
In general, asynchronous implementation could result in significant improvement if we’re creating a
Windows application. In this case, an asynchronous call allows the user interface to remain responsive. Or if we
have other work to do that have a high degree of latency. By performing the web service call asynchronously, we
can carry out our work while waiting for the response. A special case is when we need to call several
independent web services. In this situation, we can call them all asynchronously, which can dramatically reduce
the time of total call.
However asynchronous implementation is not a silver bullet solution. For example asynchronous
implementations will not speed up the time taken to receive a response. Thus, in most cases we will have no
reason to call the web service asynchronously in web applications. If we were performing a series of tasks that
do not have to be performed in order then we can use asynchronous implementation to allow these tasks to
execute at the same time instead of waiting on each to complete (see figure 12-3).
We can also use asynchronous implementation when we don’t want to wait for a WebMethod to return. For
example if a WebMethod is going to take considerable amount of time to execute normally the client application
will become locked because it is waiting for the WebMethod to return. By using asynchronous implementation
to invoke the WebMethod the executed WebMethod will return immediately and thus allowing the application to
continue execution. Once the WebMethod has completed execution the result will be returned to the client.

462
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 12-3. Difference between Synchronous and Asymchronous implementation.

In figure 12-3 a synchronous method call can create a delay in program flow, an asynchronous approach may be
better in certain situations, such as when a program needs to send out requests to multiple Web services. In
Asynchronous those requests are sent in parallel. However in synchronous the execution wait for the previous
function to return before executing the next. Asynchronous implementation is particularly suitable in a
distributed architecture where delay for request and response can vary.

Asynchronous Delegates
In .NET we’re shielded from the complexities involved in Asynchronous Operation. All of the work is handled
by the Proxy class that is generated for our Web service. We can implement asynchronous programming by
using delegates. Delegates are typesafe function pointers that form the basis for .NET events. We can create a
delegate that references a specific method, and then call that method through the delegate. All delegates provide
BeginInvoke() and EndInvoke() methods that allows us to trigger methods on one of the threads in the CLR thread
pool.
We need to define the delegate first. We can specify the delegate at the namespace level or in the class itself.
For example, here’s a delegate that can point to any method (see listing 12-17 and listing 12-18):

Listing 12-17. Implementing delegate using C#

public delegate string VerySlowWebMethodAsyncDelegate();

Listing 12-18. Implementing delegate using Visual Basic 2005

Public Delegate Function VerySlowWebMethodAsyncDelegate() As String

We will use this delegate to wrap around a Web service method that is called VerySlowWSFunction(). Every
time we define a delegate such as VerySlowWebMethodAsyncDelegate a custom delegate class is generated and
added to our assembly. The reason is because the code for each delegate is different, depending on the signature
of the method we define.
Through out the examples in this section we will be using the WebMethod VerySlowWSFunction() (see
listing 12-19 and listing 12-20).

463
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 12-19. Implementing VerySlowWSFunction() using C#.

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Threading;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
public Service () {
}

[WebMethod(Description = "Very slow WebMethod")]


public string VerySlowWSFunction()
{
Thread.Sleep(5000);
return "WebMethod execution complete";
}

Listing 12-20. Implementing VerySlowWSFunction() using Visual Basic 2005

Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.Threading

<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class Service
Inherits System.Web.Services.WebService

<WebMethod(Description:="Very slow WebMethod")> _


Public Function VerySlowWSFunction() As String
Thread.Sleep(5000)
Return "execution complete"
End Function

End Class

Let us have a look at using delegate to wrap around a web service method listed above see listing 12-21 and
listing 12-22.

Listing 12-21. Using delegate to call a WebMethod in C#

464
The Complete Reference To Professional SOA with Visual Studio 2005

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace CSTestAsyncClientBegin
{
public delegate string VerySlowWebMethodAsyncDelegate();

public partial class Form1 : Form


{
public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)


{
WSAsync.Service wsa =
new CSTestAsyncClientBegin.WSAsync.Service();
VerySlowWebMethodAsyncDelegate veryslowWebMethod =
new VerySlowWebMethodAsyncDelegate(wsa.VerySlowWSFunction);

this.labelResult.Text = veryslowWebMethod() + " " +


DateTime.Now.ToShortTimeString();
}
}
}

Listing 12-22. Using delegate to call a WebMethod in Visual Basic 2005

Public Delegate Function VerySlowWebMethodAsyncDelegate() As String

Public Class Form1

Private Sub button1_Click(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles button1.Click
Dim wsa As WSAsync.Service = New WSAsync.Service
Dim veryslowWebMethod As VerySlowWebMethodAsyncDelegate = _
New VerySlowWebMethodAsyncDelegate(AddressOf wsa.VerySlowWSFunction)
Me.labelResult.Text = veryslowWebMethod() + " " + _
DateTime.Now.ToShortTimeString
End Sub
End Class

465
The Complete Reference To Professional SOA with Visual Studio 2005

In listing 12-21 and listing 12-22 we have created a delegate named VerySlowWebMethodAsyncDelegate, this
delegate takes no parameters and has a return type of string. This is to match the parameter and return type of our
WebMethod. We then create an object of the delegate by passing in the WebMethod that we’re interested in.
This will allow the delegate to wrap around the WebMethod. See listing 12-23 and listing 12-24 below.

Listing 12-23. Allowing delegate to wrap around a function in C#

VerySlowWebMethodAsyncDelegate veryslowWebMethod =
new VerySlowWebMethodAsyncDelegate(wsa.VerySlowWSFunction);

Listing 12-24. Allowing delegate to wrap around a function in Visual Basic 2005

Dim veryslowWebMethod As VerySlowWebMethodAsyncDelegate = _


New VerySlowWebMethodAsyncDelegate(AddressOf wsa.VerySlowWSFunction)

When we call a method through the delegate, we are actually relying on the Invoke() method of the delegate
class. The Invoke() method executes the linked method synchronously. However, the delegate class also includes
methods for asynchronous invocation these are BeginInvoke() and EndInvoke(). When we use BeginInvoke(), the
call returns immediately, but it doesn’t provide the return value. Instead, the method is simply queued to start on
another thread. When calling BeginInvoke(), we supply all the parameters of the original method, plus two
additional parameters for an optional callback and state object. If we don’t need these details we can simply pass
a null reference in C# or Nothing in VB.NET.
Lets have a look at the implementing BeginInvoke() and EndInvoke() from delegates (see listing 12-25 and
listing 12-26).

Listing 12-25. Using BeginInvoke() and EndInvoke() in C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace CSTestAsyncClient
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void buttonSynchronous_Click(object sender, EventArgs e)


{
DateTime starttime = DateTime.Now;

WSAsync.Service wsAsyncService =
new CSTestAsyncClient.WSAsync.Service();
String result = wsAsyncService.VerySlowWSFunction();
ComplexTimeconsumingLogic();

466
The Complete Reference To Professional SOA with Visual Studio 2005

this.labelSynchTimeTaken.Text =
((TimeSpan)DateTime.Now.Subtract(starttime)).TotalSeconds.ToString();
MessageBox.Show(result);
}

public delegate string VerySlowWebMethodAsyncDelegate();


private void buttonAsynchronous_Click(object sender, EventArgs e)
{
DateTime starttime = DateTime.Now;

WSAsync.Service wsAsyncService = new CSTestAsyncClient.WSAsync.Service();


VerySlowWebMethodAsyncDelegate vsd =
new VerySlowWebMethodAsyncDelegate(wsAsyncService.VerySlowWSFunction);

IAsyncResult handle = vsd.BeginInvoke(null, null);

// perform some very length calculation in the main application


ComplexTimeconsumingLogic();

String result = "";


try
{
result = vsd.EndInvoke(handle);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

this.labelAsyncTimetaken.Text =
((TimeSpan)DateTime.Now.Subtract(starttime)).TotalSeconds.ToString();
MessageBox.Show(result);
}

private void ComplexTimeconsumingLogic()


{
Thread.Sleep(5000);
}
}
}

Listing 12-26. Using BeginInvoke() and EndInvoke() in Visual Basic 2005

Imports System.Threading

Public Class Form1

Private Sub buttonSynchronous_Click(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles buttonSynchronous.Click
Dim starttime As DateTime = DateTime.Now
Dim wsAsyncService As WSAsync.Service = _
New VBTestAsyncClient.WSAsync.Service

467
The Complete Reference To Professional SOA with Visual Studio 2005

Dim result As String = wsAsyncService.VerySlowWSFunction


ComplexTimeconsumingLogic()
Me.labelSynchTimeTaken.Text = _
CType(DateTime.Now.Subtract(starttime), TimeSpan).TotalSeconds.ToString
MessageBox.Show(result)
End Sub

Public Delegate Function VerySlowWebMethodAsyncDelegate() As String

Private Sub buttonAsynchronous_Click(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles buttonAsynchronous.Click
Dim starttime As DateTime = DateTime.Now
Dim wsAsyncService As WSAsync.Service = _
New VBTestAsyncClient.WSAsync.Service
' perform some very length calculation in the main application
Dim vsd As VerySlowWebMethodAsyncDelegate = _
New VerySlowWebMethodAsyncDelegate(AddressOf wsAsyncService.VerySlowWSFunction)
Dim handle As IAsyncResult = _
vsd.BeginInvoke(Nothing, Nothing)
ComplexTimeconsumingLogic()
Dim result As String = ""
Try
result = vsd.EndInvoke(handle)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
Me.labelAsyncTimetaken.Text = _
CType(DateTime.Now.Subtract(starttime), TimeSpan).TotalSeconds.ToString
MessageBox.Show(result)
End Sub

Private Sub ComplexTimeconsumingLogic()


Thread.Sleep(5000)
End Sub
End Class

In listing 12-27 and listing 12-28 we first created a delegate to wrap around our very slow WebMethod VerySlowWSFunction. See listing
12-27 and listing 12-28 below.

Listing 12-27. Declaring the delegate using C#

public delegate string VerySlowWebMethodAsyncDelegate();

Listing 12-28. Declaring the delegate using Visual Basic 2005

Public Delegate Function VerySlowWebMethodAsyncDelegate() As String


We then create a wrapper around the VerySlowWSFunction WebMethod. See listing 12-29 and listing 12-30
below.

Listing 12-29. Wrapping the delegate around the VerySlowWSFunction WebMethod in C#

VerySlowWebMethodAsyncDelegate vsd = new VerySlowWebMethodAsyncDelegate(wsAsyncService.VerySlowWSFunction);

468
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 12-30. Wrapping the delegate around the VerySlowWSFunction WebMethod in Visual Basic 2005

Dim vsd As VerySlowWebMethodAsyncDelegate = _


New VerySlowWebMethodAsyncDelegate(AddressOf wsAsyncService.VerySlowWSFunction)

Once we have wrapped our VerySlowWSFunction we can begin to call the BeginInvoke() and EndInvoke().
BeginInvoke() doesn’t provide the return value of the underlying method. Instead, it returns an IAsyncResult
object, which we can examine to determine when the asynchronous operation is complete. To pick up the results
later, we submit the IAsyncResult object to the matching EndInvoke() method of the delegate. EndInvoke() waits
for the operation to complete if it hasn’t already finished and then provides the real return value. If any
unhandled errors occurred in the method that we executed asynchronously, they’ll bubble up to when we call
EndInvoke(). See listing 12-31 and listing 12-32 below.

Listing 12-31. Using BeginInvoke() and EndInvoke() using C#

IAsyncResult handle = vsd.BeginInvoke(null, null);


// perform some very length calculation in the main application
ComplexTimeconsumingLogic();
String result = vsd.EndInvoke(handle);

Listing 12-32. Using BeginInvoke() and EndInvoke() using Visual Basic 2005

Dim handle As IAsyncResult = vsd.BeginInvoke(Nothing, Nothing)


ComplexTimeconsumingLogic()
Dim result As String = vsd.EndInvoke(handle)

Notice that the exception handler wraps the EndInvoke() method but not the BeginInvoke() method. That is
because if any errors occur while processing the request (whether because of a network problem or a server-side
exception), our code won’t receive it until you call the EndInvoke() method. See listing 12-33and listing 12-
34below.

Listing 12-33. Catching errors for EndInvoke() using C#

String result = "";


try
{
result = vsd.EndInvoke(handle);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

Listing 12-34. Catching errors for EndInvoke() using Visual Basic 2005

Dim result As String = ""


Try
result = vsd.EndInvoke(handle)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
In listing 12-33 and listing 12-34 above we have also included the same functionality using synchronous
implementation. See listing 12-35 and listing 12-36 below.

469
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 12-35. shows the synchronous implemenation C#

private void buttonSynchronous_Click(object sender, EventArgs e)


{
DateTime starttime = DateTime.Now;

WSAsync.Service wsAsyncService =
new CSTestAsyncClient.WSAsync.Service();
String result = wsAsyncService.VerySlowWSFunction();
ComplexTimeconsumingLogic();

this.labelSynchTimeTaken.Text =
((TimeSpan)DateTime.Now.Subtract(starttime)).TotalSeconds.ToString();
MessageBox.Show(result);
}

Listing 12-36. shows the synchronous implemenation Visual Basic 2005

Private Sub buttonSynchronous_Click(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles buttonSynchronous.Click
Dim starttime As DateTime = DateTime.Now
Dim wsAsyncService As WSAsync.Service = _
New VBTestAsyncClient.WSAsync.Service
Dim result As String = wsAsyncService.VerySlowWSFunction
ComplexTimeconsumingLogic()
Me.labelSynchTimeTaken.Text = _
CType(DateTime.Now.Subtract(starttime), TimeSpan).TotalSeconds.ToString
MessageBox.Show(result)
End Sub
In our TestAsyncClient application if we execute both synchronous implementation compared with the
asynchronous implementation. We can see that the asynchronous implementation has dramatic improvement in
performance. This is because the application does not have to wait for the WebMethod to return before start
executing the next big piece of logic. Thus we have parallel execution that allows for a dramatic performance
boost. To gain some of the benefits of multithreading with this technique, we could call several methods
asynchronously with BeginInvoke(). We could then call EndInvoke() on all of them before continuing.

Figure 12-4: Execution time difference between synchronous and asynchronous

Concurrent Asynchronous Calls


The IAsyncState object gives us a few other options that are useful when calling multiple web methods at once.
The key is the IAsyncState.WaitHandle object, which returns a System.Threading.WaitHandle object. Using this

470
The Complete Reference To Professional SOA with Visual Studio 2005

object, we can call WaitAll() to wait until all our asynchronous operations are complete. See listing 12-37 and
listing 12-38.
The following example uses this technique to call the our VerySlowWSFunction() method four times at once.

Listing 12-37. Implement concurrent async processing using C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace CSTestConcurrentAsyncClient
{
class Program
{
public delegate string VerySlowWebMethodAsyncDelegate();
static void Main(string[] args)
{
DateTime starttime = DateTime.Now;

CSTestConcurrenctAsyncClient.WSAsync.Service wsAsyncService = new CSTestConcurrentAsyncClient.WSAsync.Service();


VerySlowWebMethodAsyncDelegate vsd =
new VerySlowWebMethodAsyncDelegate(wsAsyncService.VerySlowWSFunction);

IAsyncResult handle = vsd.BeginInvoke(null, null);


IAsyncResult handle1 = vsd.BeginInvoke(null, null);
IAsyncResult handle2 = vsd.BeginInvoke(null, null);
IAsyncResult handle3 = vsd.BeginInvoke(null, null);

WaitHandle[] waitHandles = {
handle.AsyncWaitHandle,
handle1.AsyncWaitHandle,
handle2.AsyncWaitHandle,
handle3.AsyncWaitHandle};
// perform some very length calculation in the main application
ComplexTimeconsumingLogic();

String result = "", result1 = "", result2 = "", result3 = "";


try
{
WaitHandle.WaitAll(waitHandles);
result = vsd.EndInvoke(handle);
result1 = vsd.EndInvoke(handle1);
result2 = vsd.EndInvoke(handle2);
result3 = vsd.EndInvoke(handle3);
Console.WriteLine("Time taken: " +((TimeSpan)DateTime.Now.Subtract(starttime)).TotalSeconds.ToString());
Console.WriteLine("Execution compelte!");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine("Error" + ex.Message);
}

471
The Complete Reference To Professional SOA with Visual Studio 2005

private static void ComplexTimeconsumingLogic()


{
Thread.Sleep(5000);
}
}
}

Listing 12-38. Implement concurrent async processing using Visual Basic 2005

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Threading
Namespace CSTestConcurrentAsyncClient

Class Program

Public Delegate Function VerySlowWebMethodAsyncDelegate() As String


<MTAThreadAttribute()> _
Shared Sub Main(ByVal args As String())
Dim starttime As DateTime = DateTime.Now
Dim wsAsyncService As VBTestConcurrentAsyncClient.WSAsync.Service = New
VBTestConcurrentAsyncClient.WSAsync.Service
Dim vsd As VerySlowWebMethodAsyncDelegate = New VerySlowWebMethodAsyncDelegate(AddressOf
wsAsyncService.VerySlowWSFunction)
Dim handle As IAsyncResult = vsd.BeginInvoke(Nothing, Nothing)
Dim handle1 As IAsyncResult = vsd.BeginInvoke(Nothing, Nothing)
Dim handle2 As IAsyncResult = vsd.BeginInvoke(Nothing, Nothing)
Dim handle3 As IAsyncResult = vsd.BeginInvoke(Nothing, Nothing)
Dim waitHandles As WaitHandle() = {handle.AsyncWaitHandle, handle1.AsyncWaitHandle,
handle2.AsyncWaitHandle, handle3.AsyncWaitHandle}
ComplexTimeconsumingLogic()
Dim result As String = ""
Dim result1 As String = ""
Dim result2 As String = ""
Dim result3 As String = ""
Try
WaitHandle.WaitAll(waitHandles)
result = vsd.EndInvoke(handle)
result1 = vsd.EndInvoke(handle1)
result2 = vsd.EndInvoke(handle2)
result3 = vsd.EndInvoke(handle3)
Console.WriteLine("Time taken: " + CType(DateTime.Now.Subtract(starttime), TimeSpan).TotalSeconds.ToString)
Console.WriteLine("Execution compelte!")
Console.ReadLine()
Catch ex As Exception
Console.WriteLine("Error" + ex.Message)
Console.ReadLine()
End Try
End Sub

472
The Complete Reference To Professional SOA with Visual Studio 2005

Private Shared Sub ComplexTimeconsumingLogic()


Thread.Sleep(5000)
End Sub
End Class
End Namespace

Instead of using a wait handle, we could also launch the three asynchronous calls by calling BeginInvoke()
three times and then call the three EndInvoke() methods immediately after that. In this case, our code would wait
if required. However, using a wait handle clarifies our code.

Improving Responsiveness in Windows Client


One of the key benefit asynchronous implementation provides is in improving the responsiveness in Windows
Client. In a Windows client, the threading code that we use is a little different. This is because we want to allow
the application to continue unhindered while the operation is taking place. This will allow the UI to continue to
interact with the user until the call is complete. This implementation allows us to refresh the display with
updated information without locking the UI. Support for this asynchronous implementation pattern is built into
the proxy class.
The proxy class actually includes two methods the synchronous version that we’ve seen so far and an
asynchronous version that adds the suffix Async to the method (see figure 12-5).

Figure 12-5: Synchronous and Asynchronous implementation of VerySlowWSFunction.

Notice there are two versions of VerySlowWSFunction, the VerySlowWSFunction without the Async suffix is
used for synchronous operations whilst the other VerySlowWSFunctionAsync is auto generated for the proxy to
use for Asynchronous implementations (see figure 12-5).
The idea is that we can call VerySlowWSFunctionAsync() to launch the request. This method returns
immediately, before the request is even sent over the network, and the proxy class waits on a free thread until it
receives the response. As soon as the response is received and deserialized, .NET fires an event to notify our
application. We can then retrieve the results.
The proxy class also adds an event for each web method. This event is fired when the asynchronous method
is finished.
Let us have a look at using this asynchronous (see listing 12-39 and listing 12-40).

Listing 12-39. Asynchronous implementation C#

473
The Complete Reference To Professional SOA with Visual Studio 2005

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using CSTestAsyncClient.WSAsync;

namespace CSTestAsyncClient
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void buttonCheckResponse_Click(object sender, EventArgs e)


{
//dummy button to test return
}

private void buttonSynchronous_Click(object sender, EventArgs e)


{
DateTime starttime = DateTime.Now;

WSAsync.Service wsAsyncService =
new CSTestAsyncClient.WSAsync.Service();
String result = wsAsyncService.VerySlowWSFunction();
ComplexTimeconsumingLogic();

this.labelSynchTimeTaken.Text =
((TimeSpan)DateTime.Now.Subtract(starttime))
.TotalSeconds.ToString();
MessageBox.Show(result);
}

public delegate string VerySlowWebMethodAsyncDelegate();


private void buttonAsynchronous_Click(object sender, EventArgs e)
{
DateTime starttime = DateTime.Now;
WSAsync.Service wsAsyncService =
new CSTestAsyncClient.WSAsync.Service();

wsAsyncService.VerySlowWSFunctionCompleted +=
new CSTestAsyncClient.WSAsync.
VerySlowWSFunctionCompletedEventHandler
(VerySlowWSFunctionCompleted);

wsAsyncService.VerySlowWSFunctionAsync();
this.labelAsyncTimetaken.Text =

474
The Complete Reference To Professional SOA with Visual Studio 2005

((TimeSpan)DateTime.Now.Subtract(starttime)).
TotalSeconds.ToString();
}

private void ComplexTimeconsumingLogic()


{
Thread.Sleep(5000);
}

private void VerySlowWSFunctionCompleted(object sender,


WSAsync.VerySlowWSFunctionCompletedEventArgs e)
{
try
{
MessageBox.Show(e.Result);
}
catch (System.Reflection.TargetInvocationException err)
{
MessageBox.Show("Error: " + err.Message);
}
}
}
}

Listing 12-40. Asynchronous implementation Visual Basic 2005

Imports System.Threading

Public Class Form1

Private Sub buttonSynchronous_Click(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles buttonSynchronous.Click
Dim starttime As DateTime = DateTime.Now
Dim wsAsyncService As WSAsync.Service = _
New VBTestAsyncClient.WSAsync.Service
Dim result As String = wsAsyncService.VerySlowWSFunction
ComplexTimeconsumingLogic()

Me.labelSynchTimeTaken.Text = _
CType(DateTime.Now.Subtract(starttime), TimeSpan) _
.TotalSeconds.ToString()

MessageBox.Show(result)
End Sub

Public Delegate Function VerySlowWebMethodAsyncDelegate() As String

Private Sub buttonAsynchronous_Click(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles buttonAsynchronous.Click
Dim starttime As DateTime = DateTime.Now

Dim wsAsyncService As WSAsync.Service = _

475
The Complete Reference To Professional SOA with Visual Studio 2005

New VBTestAsyncClient.WSAsync.Service

' perform some very length calculation in the main application


Dim vsd As VerySlowWebMethodAsyncDelegate = _
New VerySlowWebMethodAsyncDelegate( _
AddressOf wsAsyncService.VerySlowWSFunction)

Dim handle As IAsyncResult = _


vsd.BeginInvoke(Nothing, Nothing)
ComplexTimeconsumingLogic()

Dim result As String = ""


Try
result = vsd.EndInvoke(handle)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
Me.labelAsyncTimetaken.Text = _
CType(DateTime.Now.Subtract(starttime), TimeSpan) _
.TotalSeconds.ToString()
MessageBox.Show(result)
End Sub

Private Sub ComplexTimeconsumingLogic()


Thread.Sleep(5000)
End Sub
End Class

The listing 12-39 and 12-40 implements asynchronous through the proxy’s VerySlowWSFunctionAsync()
function to start the process. But first, it needs to attach an event handler to the VerySlowWSFunctionCompleted
event. This is so that once we have executed VerySlowWSFunctionAsync() the code will return immediately.
Thus we don’t know when the VerySlowWSFunctionAsync() will finish executing. By attaching the event to the
asynchronous thread. Once the VerySlowWSFunctionAsync() has finished execution it will call on the
VerySlowWSFunctionCompleted() as we had specified in our event. See listing 12-41and listing 12-42.

Listing 12-41. Asynchronous implementation using events using C#

wsAsyncService.VerySlowWSFunctionCompleted += new
CSTestAsyncClient.WSAsync.VerySlowWSFunctionCompletedEventHandler(VerySlowWSFunctionCompleted);

Listing 12-42. Asynchronous implementation using events using Visual Basic 2005

AddHandler wsAsyncService.VerySlowWSFunctionCompleted, _
New VBTestAsyncClientWinForm.WSAsync.VerySlowWSFunctionCompletedEventHandler(AddressOf
VerySlowWSFunctionCompleted)
This implementation is extremely useful in Windows application because it allows the UI to remain
responsive whilst the asynchronous thread did the work. Once the results are obtained by the Asynchronous
thread the UI can be updated with the new results.

476
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 12-6. Shows the difference of using Asynchronous implementation with event and that of synchronous implementation.

In Figure 12-6 we can see that the asynchronous implementation utilizing events has returned immediately
after the button has been pressed and thus allowing the UI to continue work and thus remain responsive. This is
particularly important in distributed systems where latency between request and response greatly varies.

Soap Extensions
A XML Web service sends and receives data from clients in the form of SOAP messages. These SOAP
messages can consist of information about a certain operation or about the result of an operation. Whenever a
client requires information from the server that hosts the XML Web service, the client sends a SOAP request to
the server. The SOAP request should be in compliance with a format that the XML Web service understands.
The XML Web service processes the SOAP request and sends a response to the client. The client receives the
SOAP response, interprets it, and performs a specified operation. If we need to access and modify the SOAP
messages that are exchanged between an XML Web service and its clients, we can use SOAP extensions.
SOAP extensions enable us to access and modify the SOAP messages that are exchanged between the client
and the XML Web service. For example, we can use SOAP extensions to validate the SOAP message before it
reaches the XML Web service and change the SOAP message after validation so that the XML Web service
receives a valid SOAP request. We can also implement an encryption or compression algorithm that can be
executed within an existing XML Web service by using SOAP extensions.

Figure 12-7. ASP.NET extension architecture

In ASP.NET architecture see figure 12-7 when ever IIS receives a request, the extension is mapped to an
ISAPI filter according to the IIS settings. The .NET extension types .aspx, .asmx, .asx and other file types are
mapped to the aspnet_isapi.dll which is simply an ISAPI filter that launches the ASP.NET runtime. The

477
The Complete Reference To Professional SOA with Visual Studio 2005

ASP.NET Runtime then launches the relevant Web service application and executes the SOAP Extensions
before passing the request into the relevant web service.
ASP.NET SOAP extensions are implemented by classes deriving from the SoapExtension class. They allow
us to intercept messages and modify the corresponding streams. We can easily implement SOAP extension by
overriding a few simple functions.
The basis of SOAP extensions is the SoapExtension class. The main methods of concern are ChainStream(),
GetInitializer(), Initialize(), and ProcessMessage(). The ChainStream() helps to capture the message stream within
the SOAP call. The GetInitializer() and Initialize() are used to provide a means of initialization. While the
ProcessMessage() method is the heart of the extension where most of the development attention goes.

Using SOAP Extensions


A SOAP extension can be entered into the Web Services infrastructure to inspect or modify the SOAP messages
before they are transmitted. The SoapExtension class includes a ProcessMessage() method that’s triggered
automatically as the SOAP message passes through several stages. These stages are enclosed within an
enumeration called SoapMessageStage.

* AfterDeserialize – This stage is just after a SoapMessage is deserialized from a SOAP message into an object.
* AfterSerialize - This stage just after a SoapMessage is serialized, but before the SOAP message is sent over the
wire.

* BeforeDeserialize - This stage just before a SoapMessage is deserialized from the SOAP message sent across
the network into an object.

* BeforeSerialize - This stage just prior to a SoapMessage being serialized.

At each stage, we can retrieve various bits of information about the SOAP message. In the
BeforeDeserialize or AfterSerialize stage, we can retrieve the full SOAP message text. We can also implement a
SOAP extension on the client. In this case, the same four stages occur. Except now, the message is being
received, deserialized, and acted upon by the proxy class, not the web service.
To create a SOAP extension, we need to create a class that derives from the
System.Web.Services.Protocols.SoapExtension class. The SoapExtension class provides a few methods that we
need to override, these are:

Table 12-2: Overridable methods of the SoapExtension class

Name Description

ChainStream This method when overridden allows a SOAP extension to access memory buffer that contains the SOAP request or
response.

GetInitializer This method when overridden allows a SOAP extension to initialize a one time only data specific to a XML Web service.

Initialize This method when overridden allows a SOAP extension to initialize itself using the data cached in the GetInitilizer
method.

ProcessMessage This method when overridden allows a SOAP extension to receive a SoapMessage to process at each SoapMessageStage.

We will now create a Web service which provides an Add WebMethod. We will use overridable methods
from SoapExtension class to implement a SOAP logging application to monitor the SOAP exchange performed
on the Add WebMethod (see listing 12-43 and listing 12-44).

478
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 12-43. SoapLogger.cs using C#

namespace Logging
{
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.IO;
using System.Xml;

// Create a new custom attribute that will allow


// users to configure the log file. This attribute
// will also tell the ASP.NET system which type to
// load for our extension
[AttributeUsage(AttributeTargets.Method)]
public class SoapLoggerAttribute : SoapExtensionAttribute
{
private int _priority = 0;
private string _logFile = @"C:\soap.log";
public SoapLoggerAttribute() {
}
public SoapLoggerAttribute(string logFile){
_logFile = logFile;
}
public string LogFile {
get { return _logFile; }
}
public override Type ExtensionType {
get { return typeof(SoapLogger); }
}
public override int Priority {
get { return _priority; } set { _priority = value; }
}
}

// Create a new SoapExtension class. When users


// apply the above attribute to a method of their
// web service, this class will be instantiated
// by the ASP.NET system
public class SoapLogger : SoapExtension
{
private string LogFile = "";
private Stream SoapStream;
private Stream TempStream;

public override object GetInitializer(Type serviceType)


{

479
The Complete Reference To Professional SOA with Visual Studio 2005

// we need to read some service configuration


// from the attribute so differ creating
// an initializer
return null;
}
public override object GetInitializer(LogicalMethodInfo methodInfo,
SoapExtensionAttribute attribute)
{
// whatever we return here will be passed back to
// our initialize method every time the ASP.NET
// system needs to create a new instance of
// this extension class
return ((SoapLoggerAttribute)attribute).LogFile;
}
public override void Initialize(object initializer)
{
// grab the logfile name that we returned in
// GetInitializer
LogFile = (string)initializer;
}
public override Stream ChainStream(Stream stream)
{
// by overriding ChainStream we can
// cause the ASP.NET system to use
// our stream for buffering SOAP messages
// rather than the default stream.
// we will store off the original stream
// so we can pass the data back down to the
// ASP.NET system in original stream that
// it created.
SoapStream = stream;
TempStream = new MemoryStream();
return TempStream;
}
public void CopyTextStream(Stream src, Stream dest)
{
TextReader reader = new StreamReader(src);
TextWriter writer = new StreamWriter(dest);
writer.WriteLine(reader.ReadToEnd());
writer.Flush();
}
public override void ProcessMessage(SoapMessage message)
{
// this method will be called several times during
// the processing of a SOAP request. The
// ASP.NET system tells us which stage the
// SOAP request is at with the Stage property
// of the SoapMessage class
switch (message.Stage)
{
case SoapMessageStage.BeforeDeserialize:
{
// copy the SOAP request from the

480
The Complete Reference To Professional SOA with Visual Studio 2005

// network stream into our memory buffer


CopyTextStream(SoapStream, TempStream);
FileStream fs = new FileStream(LogFile,
FileMode.Append, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine("** BEGIN SOAP REQUEST: {0}",
DateTime.Now);
sw.Flush();

// copy the mem buffer stream to the


// log file
TempStream.Position = 0;
CopyTextStream(TempStream, fs);
sw.WriteLine("** END SOAP REQUEST");
sw.Flush();
fs.Close();

// reset the memory buffer position


// so the ASP.NET system can parse and
// decode the message
TempStream.Position = 0;
}
break;
case SoapMessageStage.AfterDeserialize:
break;
case SoapMessageStage.BeforeSerialize:
break;
case SoapMessageStage.AfterSerialize:
{
FileStream fs = new FileStream(LogFile,
FileMode.Append, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine("** BEGIN SOAP RESPONSE: {0}",
DateTime.Now);
sw.Flush();
TempStream.Position = 0;
CopyTextStream(TempStream, fs);
sw.WriteLine("** END SOAP RESPONSE");
sw.Flush();

// copy the memory buffered response


// to the network stream
TempStream.Position = 0;
CopyTextStream(TempStream, SoapStream);

fs.Close();
}
break;
}

return;
}
}

481
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 12-44. SoapLogger.vb using Visual Basic 2005

Imports System.Xml
Imports System.IO
Imports System.Web.Services.Protocols
Imports System.Web.Services
Imports System.Web
Imports System.Diagnostics
Imports System.Data
Imports System.ComponentModel
Imports System.Collections
Imports System
Namespace Logging

<AttributeUsage(AttributeTargets.Method)> _
Public Class SoapLoggerAttribute
Inherits SoapExtensionAttribute
Private _priority As Integer = 0
Private _logFile As String = "C:\soap.log"

Public Sub New()


End Sub

Public Sub New(ByVal logFile As String)


_logFile = logFile
End Sub

Public ReadOnly Property LogFile() As String


Get
Return _logFile
End Get
End Property

Public Overloads Overrides ReadOnly Property ExtensionType() As Type


Get
Return GetType(SoapLogger)
End Get
End Property

Public Overloads Overrides Property Priority() As Integer


Get
Return _priority
End Get
Set(ByVal value As Integer)
_priority = value
End Set
End Property
End Class

Public Class SoapLogger

482
The Complete Reference To Professional SOA with Visual Studio 2005

Inherits SoapExtension
Private LogFile As String = ""
Private SoapStream As Stream
Private TempStream As Stream

Public Overloads Overrides Function _


GetInitializer(ByVal serviceType As Type) As Object
Return Nothing
End Function

Public Overloads Overrides Function _


GetInitializer(ByVal methodInfo As LogicalMethodInfo, _
ByVal attribute As SoapExtensionAttribute) As Object
Return CType(attribute, SoapLoggerAttribute).LogFile
End Function

Public Overloads Overrides Sub Initialize(ByVal initializer As Object)


LogFile = CType(initializer, String)
End Sub

Public Overloads Overrides Function ChainStream(ByVal stream As Stream) As Stream


SoapStream = stream
TempStream = New MemoryStream
Return TempStream
End Function

Public Sub CopyTextStream(ByVal src As Stream, ByVal dest As Stream)


Dim reader As TextReader = New StreamReader(src)
Dim writer As TextWriter = New StreamWriter(dest)
writer.WriteLine(reader.ReadToEnd)
writer.Flush()
End Sub

Public Overloads Overrides Sub ProcessMessage(ByVal message As SoapMessage)


Select Case message.Stage
Case SoapMessageStage.BeforeDeserialize
CopyTextStream(SoapStream, TempStream)
Dim fs As FileStream = New FileStream(LogFile, _
FileMode.Append, FileAccess.Write)
Dim sw As StreamWriter = New StreamWriter(fs)
sw.WriteLine("** BEGIN SOAP REQUEST: {0}", _
DateTime.Now)
sw.Flush()
TempStream.Position = 0
CopyTextStream(TempStream, fs)
sw.WriteLine("** END SOAP REQUEST")
sw.Flush()
fs.Close()
TempStream.Position = 0
Case SoapMessageStage.AfterDeserialize
Case SoapMessageStage.BeforeSerialize
Case SoapMessageStage.AfterSerialize
Dim fs As FileStream = New FileStream(LogFile, _

483
The Complete Reference To Professional SOA with Visual Studio 2005

FileMode.Append, FileAccess.Write)
Dim sw As StreamWriter = New StreamWriter(fs)
sw.WriteLine("** BEGIN SOAP RESPONSE: {0}", _
DateTime.Now)
sw.Flush()
TempStream.Position = 0
CopyTextStream(TempStream, fs)
sw.WriteLine("** END SOAP RESPONSE")
sw.Flush()
TempStream.Position = 0
CopyTextStream(TempStream, SoapStream)
fs.Close()
End Select
Return
End Sub
End Class
End Namespace

The above code shows the SOAP logger library. In order to use the SOAP logger we need to have a Web
service for the SOAP extensions to work with. Below is a Web service which performs addition operations (see
listing 12-45 and listing 12-46).

Listing 12-45. Web service which performs addition C#

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.IO;
using Logging;

[WebService(Namespace = "http://tempuri.org/")]
public class Service : System.Web.Services.WebService
{
public Service () {
}

[WebMethod]
[SoapLogger]
public int Add(int x, int y) {
return x + y;
}

Listing 12-46. Web service which performs addition Visual Basic 2005

Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols

484
The Complete Reference To Professional SOA with Visual Studio 2005

Imports Logging

<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class Service
Inherits System.Web.Services.WebService

<WebMethod()> _
<SoapLogger()> _
Public Function Add(ByVal x As Integer, _
ByVal y As Integer) As Integer
Return x + y
End Function

End Class

Now we will look at the structure of the SOAP extensions code. We will start by inheriting from the SoapExtension
class (see listing 12-47 and listing 12-48),

Listing 12-47. Extending from SoapExtension C#

public class SoapLogger : SoapExtension

Listing 12-48. Extending from SoapExtension Visual Basic 2005

Public Class SoapLogger Inherits SoapExtension

ASP.NET then calls the GetInitializer() method the first time our extension is used for a particular web
method. It gives us the chance to initialize and store some data that will be used when processing SOAP
messages. We can store this information by passing it back as the return value from the GetInitializer() method.
When the GetInitializer() method is called, it allows us to receive the custom attribute that was applied to the
corresponding web method. In the case of the SoapLogger, this is an instance of the SoapLoggerAttribute class,
which provides the LogFile and Priority property (see listing 12-49 and listing 12-50).

Listing 12-49. GetIntializer C#

public override object GetInitializer(LogicalMethodInfo methodInfo,


SoapExtensionAttribute attribute)
{
return ((SoapLoggerAttribute)attribute).LogFile;
}

Listing 12-50. GetIntializer Visual Basic 2005

Public Overloads Overrides Function _


GetInitializer(ByVal methodInfo As LogicalMethodInfo, _
ByVal attribute As SoapExtensionAttribute) As Object
Return CType(attribute, SoapLoggerAttribute).LogFile
End Function

485
The Complete Reference To Professional SOA with Visual Studio 2005

There is also another version of GetInitializer() the reason is that SOAP extension can be loaded in two
ways. One way is through the attribute for the WebMethod the other way is to specify it within the Web.Config
file. We will be looking at this a little later (see listing 12-51 and listing 12-52).

Listing 12-51. GetInitializer used by the Web.Config load implementation file C#

public override object GetInitializer(Type serviceType)


{
return null;
}

Listing 12-52. GetInitializer used by the Web.Config load implementation file Visual Basic 2005

Public Overloads Overrides Function _


GetInitializer(ByVal serviceType As Type) As Object
Return Nothing
End Function

GetInitializer() is called only the first time our SOAP extension is executed for a method. However, every
time a WebMethod is invoked, the Initialize() method is triggered. If we returned an object from the
GetInitializer() method, ASP.NET provides this object to the Initialize() method every time it’s called. In the
SoapLogger extension, this is where we can extract the LogFile information and store it in member variables so it
will be available for the remainder of the SOAP processing work (see listing 12-53 and listing 12-54).

Tip: We can not store any information in the GetInitialize() method, because it will not be called every time the SOAP extension is
executed.

Listing 12-53. Intialize() using C#

public override void Initialize(object initializer)


{
// grab the logfile name that we returned in
// GetInitializer
LogFile = (string)initializer;
}

Listing 12-54. Intialize() using Visual Basic 2005

Public Overloads Overrides Sub Initialize(ByVal initializer As Object)


LogFile = CType(initializer, String)
End Sub
The majority of the work within the SOAP extensions is done by the ProcessMessage() method, this is the
method which ASP.NET calls at various stages of the serialization process. A SOAP message object is passed to
the ProcessMessage() method, and here we can examine this method to retrieve information about the message,
such as its stage and the message text. The SoapLogger extension reads the full message only in the AfterSerialize
and BeforeDeserialize stages, because these are the only stages when we can retrieve the full XML of the SOAP
message (see listing 12-55 and listing 12-56).

Listing 12-55. ProcessMessage() using C#

public override void ProcessMessage(SoapMessage message)

486
The Complete Reference To Professional SOA with Visual Studio 2005

{
// this method will be called several times during
// the processing of a SOAP request. The
// ASP.NET system tells us which stage the
// SOAP request is at with the Stage property
// of the SoapMessage class
switch (message.Stage)
{
case SoapMessageStage.BeforeDeserialize:
{
// copy the SOAP request from the
// network stream into our memory buffer
CopyTextStream(SoapStream, TempStream);
FileStream fs = new FileStream(LogFile,
FileMode.Append, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine("** BEGIN SOAP REQUEST: {0}",
DateTime.Now);
sw.Flush();

// copy the mem buffer stream to the


// log file
TempStream.Position = 0;
CopyTextStream(TempStream, fs);
sw.WriteLine("** END SOAP REQUEST");
sw.Flush();
fs.Close();

// reset the memory buffer position


// so the ASP.NET system can parse and
// decode the message
TempStream.Position = 0;
}
break;
case SoapMessageStage.AfterDeserialize:
break;
case SoapMessageStage.BeforeSerialize:
break;
case SoapMessageStage.AfterSerialize:
{
FileStream fs = new FileStream(LogFile,
FileMode.Append, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine("** BEGIN SOAP RESPONSE: {0}",
DateTime.Now);
sw.Flush();
TempStream.Position = 0;
CopyTextStream(TempStream, fs);
sw.WriteLine("** END SOAP RESPONSE");
sw.Flush();

// copy the memory buffered response


// to the network stream

487
The Complete Reference To Professional SOA with Visual Studio 2005

TempStream.Position = 0;
CopyTextStream(TempStream, SoapStream);

fs.Close();
}
break;
}

return;
}

Listing 12-56. ProcessMessage() using Visual Basic 2005

Public Overloads Overrides Sub ProcessMessage(ByVal message As SoapMessage)


Select Case message.Stage
Case SoapMessageStage.BeforeDeserialize
CopyTextStream(SoapStream, TempStream)
Dim fs As FileStream = New FileStream(LogFile, _
FileMode.Append, FileAccess.Write)
Dim sw As StreamWriter = New StreamWriter(fs)
sw.WriteLine("** BEGIN SOAP REQUEST: {0}", _
DateTime.Now)
sw.Flush()
TempStream.Position = 0
CopyTextStream(TempStream, fs)
sw.WriteLine("** END SOAP REQUEST")
sw.Flush()
fs.Close()
TempStream.Position = 0
Case SoapMessageStage.AfterDeserialize
Case SoapMessageStage.BeforeSerialize
Case SoapMessageStage.AfterSerialize
Dim fs As FileStream = New FileStream(LogFile, _
FileMode.Append, FileAccess.Write)
Dim sw As StreamWriter = New StreamWriter(fs)
sw.WriteLine("** BEGIN SOAP RESPONSE: {0}", _
DateTime.Now)
sw.Flush()
TempStream.Position = 0
CopyTextStream(TempStream, fs)
sw.WriteLine("** END SOAP RESPONSE")
sw.Flush()
TempStream.Position = 0
CopyTextStream(TempStream, SoapStream)
fs.Close()
End Select
Return
End Sub
We also need a CopyTextStream() method see listing 12-55 and listing 12-56. That is because the XML in
the SOAP message is contained in a stream. The stream has a pointer that indicates the current position in the
stream. The problem is that as we read the message data from the stream (for example, to log it), we move the
pointer. This means that if the log extension reads a stream that is about to be deserialized, it will move the
pointer to the end of the stream. For ASP.NET to properly deserialize the SOAP message, the pointer must be set

488
The Complete Reference To Professional SOA with Visual Studio 2005

back to the beginning of the stream. If we don’t take this step, a deserialization error will occur. Notice we have
copied the stream using the CopyTextStream method then write it to a file before reseting the
TempStream.Postion back to 0 (see listing 12-57 and listing 12-58).

Listing 12-57. CopyTextStream() using C#

public void CopyTextStream(Stream src, Stream dest)


{
TextReader reader = new StreamReader(src);
TextWriter writer = new StreamWriter(dest);
writer.WriteLine(reader.ReadToEnd());
writer.Flush();
}

Listing 12-58. CopyTextStream() using Visual Basic 2005

Public Sub CopyTextStream(ByVal src As Stream, ByVal dest As Stream)


Dim reader As TextReader = New StreamReader(src)
Dim writer As TextWriter = New StreamWriter(dest)
writer.WriteLine(reader.ReadToEnd)
writer.Flush()
End Sub
Another method that we need to override is the ChainStream() method, which the ASP.NET plumbing calls
before serialization or deserialization takes place. SOAP extensions should save references of the Stream passed
into ChainStream and the Stream returned from ChainStream. The Stream passed into ChainStream contains the
serialized SOAP request at the BeforeDeserialize SoapMessageStage. Similarily, the Stream reference returned
from ChainStream is written into when the serialization occurs and thus contains the serialized SOAP response in
the AfterSerializeSoapMessageStage. At this point, the extension can cache a reference to the original stream and
create a new in-memory stream, which is then returned to the next extension in the chain (see listing 12-59 and
listing 12-60).

Listing 12-59. ChainStream() using C#

public override Stream ChainStream(Stream stream)


{
SoapStream = stream;
TempStream = new MemoryStream();
return TempStream;
}

Listing 12-60. ChainStream() using Visual Basic 2005

Public Overloads Overrides Function ChainStream(ByVal stream As Stream) As Stream


SoapStream = stream
TempStream = New MemoryStream
Return TempStream
End Function
To help us run the SOAP extensions we have created a custom attribute class called SoapLoggerAttribute. It
is this class that is accessed by the SOAPLogger for parameter values that’s passed in from the parameters
defined in the attribute (see listing 12-61 and listing 12-62).

Listing 12-61. Custom SoapLoggerAttribute using C#

[AttributeUsage(AttributeTargets.Method)]

489
The Complete Reference To Professional SOA with Visual Studio 2005

public class SoapLoggerAttribute : SoapExtensionAttribute


{
private int _priority = 0;
private string _logFile = @"C:\soap.log";
public SoapLoggerAttribute() {
}
public SoapLoggerAttribute(string logFile){
_logFile = logFile;
}
public string LogFile {
get { return _logFile; }
}
public override Type ExtensionType {
get { return typeof(SoapLogger); }
}
public override int Priority {
get { return _priority; } set { _priority = value; }
}
}

Listing 12-62. Custom SoapLoggerAttribute using Visual Basic 2005

<AttributeUsage(AttributeTargets.Method)> _
Public Class SoapLoggerAttribute
Inherits SoapExtensionAttribute
Private _priority As Integer = 0
Private _logFile As String = "C:\soap.log"

Public Sub New()


End Sub

Public Sub New(ByVal logFile As String)


_logFile = logFile
End Sub

Public ReadOnly Property LogFile() As String


Get
Return _logFile
End Get
End Property

Public Overloads Overrides ReadOnly Property ExtensionType() As Type


Get
Return GetType(SoapLogger)
End Get
End Property

Public Overloads Overrides Property Priority() As Integer


Get
Return _priority
End Get
Set(ByVal value As Integer)
_priority = value
End Set

490
The Complete Reference To Professional SOA with Visual Studio 2005

End Property
End Class
XML Web service methods created using ASP.NET can be configured to run with a SOAP extension by
applying an attribute to the XML Web service method. When a custom extension attribute is added to an XML
Web service method, ASP.NET calls the associated extension at the appropriate time. An extension attribute is a
custom attribute class deriving from SoapExtensionAttribute. Derived attributes must override the ExtensionType
property to return the type of extension that is associated with the attribute.

Using SoapLogger
There’s two ways to enable our SOAP Extensions. One way is to enable the SOAP extension through using an
attribute (see listing 12-63 and listing 12-64).

Listing 12-63. Invoking the SOAP Extensions using C#

[WebMethod]
[SoapLogger]
public int Add(int x, int y) {

Listing 12-64. Invoking the SOAP Extensions using Visual Basic 2005

<WebMethod()> _
<SoapLogger()> _
Public Function Add(ByVal x As Integer, _
ByVal y As Integer) As Integer
This will provide us with flexiblity in specifying which WebMethod we’d really like to add our SOAP
extensions for.
The second method is to specify it within the Web service’s Web.Config file. Doing so will enable our
SOAP logger extensions to be executed for all Web service within control of the configuration file (see listing
21-65).

Listing 12-65. Web.Config implementation

<webServices>
<soapExtensionTypes>
<add type="Logging.SoapLogger, Logging" priority="1" group="0" />
</soapExtensionTypes>
</webServices>

Tip: We cannot test the SOAP extensions using the asmx autogenerated test harness for web method. There is a
TestSOAPExtensionsClient application on the source CD which we can use to test the SOAP extensions. Its also important to remember
that we need to start the Web service first, we may also need to adjust the port number for the web service within the client application as
the web service will be running off the ASP.NET Development Server Environment for file system web applications.

The client code that we use call the Web service is as how we would call a normal Web service (see listing
12-66 and listing 12-67).

491
The Complete Reference To Professional SOA with Visual Studio 2005

NOTE: Please give the correct privileges to the Web Service so that the log file can be written to the hard drive.

Listing 12-66. Client side code using C#

private void button1_Click(object sender, EventArgs e)


{
SOAPExtension.Service wse = new winclient.SOAPExtension.Service();
this.labelResult.Text = wse.Add(5, 6).ToString();

Listing 12-67. Client side code using Visual Basic 2005

Private Sub buttonRequest_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles buttonRequest.Click


Dim wse As SOAPExtension.Service = New SOAPExtension.Service
Me.labelResult.Text = wse.Add(5, 6).ToString
End Sub
The above listing shows the client side code that we use to invoke our Web service with the addition
WebMethod implementation. The call to the Web service is unaffected by the SOAP extensions implementation.
Our SOAP logger extension will log the soap call before the request is deserialized and after it is serialized.
The result of the SOAP extension is captured with a text file.

Listing 12-68. Result captured by the SOAP Logger

** BEGIN SOAP REQUEST: 5/22/2006 11:46:04 PM


<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><Add
xmlns="http://tempuri.org/"><x>5</x><y>6</y></Add></soap:Body></soap:Envelope>

** END SOAP REQUEST


** BEGIN SOAP RESPONSE: 5/22/2006 11:46:04 PM
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><AddResponse
xmlns="http://tempuri.org/"><AddResult>11</AddResult></AddResponse></soap:Body></soap:Envelope>
** END SOAP RESPONSE
The SoapLog extension is a useful tool when developing or monitoring web services. However, we should
use it sensibly. Especially if there’re large numbers of Web methods that the SOAP extenions are monitoring.

Summary
In this chapter, we have looked at a variety of advanced SOAP techniques; these include using various
WebMethod properties, implementing web services using asynchronously implementations, and how to use
SOAP extensions.
We have also examined WebMethod properties these are BufferResponse, CacheDuration, Description,
EnableSession, MessageName, TransactionOption.
In this chapter we have also looked at asynchronous implementation which is used to allow applications to
execute a method without waiting for it complete. This is very useful in a distributed architecture, because the

492
The Complete Reference To Professional SOA with Visual Studio 2005

inherent nature of the internet, the response time between request and response can vary greatly. As such we do
not want our program to wait for the method to return.
The last thing we have looked at is SOAP extensions. SOAP extensions enable us to access and modify the
SOAP messages that are exchanged between the client and the XML Web service. For example, we can use
SOAP extensions to validate the SOAP message before it reaches the XML Web service and change the SOAP
message after validation so that the XML Web service receives a valid SOAP request. We can also implement an
encryption or compression algorithm that can be executed within an existing XML Web service by using SOAP
extensions.

493
The Complete Reference To Professional SOA with Visual Studio 2005

Chapter 13 .NET Remoting


.NET Remoting is the .NET alternative to XML Web services. .NET Remoting is an enabler for application
communication. It is a generic system for different applications to use to communicate with one another. .NET
objects are exposed to remote processes, thus allowing interprocess communication. The applications can be
located on the same computer, different computers on the same network, or even computers across separate
networks.
In the last few chapters, we have looked at how ASP.NET Web services are created and consumed.
ASP.NET Web services use the ASP.NET runtime as the hosting environment to run. Using .NET Remoting
directly, we can host Web service in any application we want. .NET Remoting allows different transport
protocols to be used. We can also benefit from performance increase with different formatting options, and it is
possible to host the server in different application types.

Table 13-1. The table below outlines differences between .NET Remoting and Web services.

Web Service .NET Remoting

.NET Web services are typically accessed over .NET Remoting can be used across three channels
HTTP. TCP, HTTP, IPC. and two formatters SOAP and
Binary.
Web services work in a stateless environment. Each .NET Remoting supports state management options
request results in a new object created to service the and can associate multiple calls from the same
request. client. Remoting model also support Asynchronous
callbacks.
Web services serialize objects into XML that is .NET Remoting relies the Common Language
contained in the SOAP message and as such can Runtime assemblies that contain information about
only handle items that can be fully expressed in data types. This allows objects to be passed by value
XML. or by reference.
Web services are interoperable across platforms and .NET Remoting can only be created using .NET
are good for environment that consists of different
technologies but are required to work together.

In the world of SOA .NET remoting may not be ideal for public facing as it is not as interoperable as Web
service. However we can use .NET remoting internally within an architecture to improve the performance of
communication between .NET to .NET applications.

.NET Remoting Proxy Architecture


To communicate between server objects and clients in .NET Remoting, we simply need to add an object
references of the server object in the client application. Whenever we create an instance of the remote object
using the new keyword, our client receives a reference to the server object. After obtaining the object reference,

494
The Complete Reference To Professional SOA with Visual Studio 2005

the client can call methods on the server object as if the object resides in the client's process. This process of
invoking methods on the server is very much like how we invoke methods of Web services.
.NET Remoting uses proxy objects to allow the use of the server object in the client process. When we
create an instance of the remote object type in the client application, .NET Remoting creates a proxy object and
sends it to the client application. This proxy object contains references to all the methods and properties of the
server object. When a call is made on the proxy object, the remoting system receives the call and routes the call
to the server process. This invokes the server object, which then returns the result to the client proxy. The client
proxy then in turn return the result to the client application (see figure 13-1). The .NET Remoting architecture is
quite flexible we can use different transport protocols such as HTTP, TCP and IPC we can also communicate
using different formatters such as SOAP and Binary.

Figure 13-1. Communication between a client process and a server process.

Remotable and Nonremotable Objects


In distributed applications, there are two categories of objects: Remotable and nonremotable. Nonremotable objects do
not provide the Remoting system with a method to either copy them or use them in another application domain.
Therefore, we can access these objects only in their own application domain. Remotable objects can either be accessed
outside their application domain or context using a proxy or copied and passed outside their application domain or
context. This implies that some remotable objects are passed by reference and some are passed by value. For example,
if we have a large object with a number of methods, our best option is to make the object nonremotable. Then, we can
create a remotable object that is small in size that can be published or copied to the client application. We can then use
the remotable object to direct the call to the larger nonremotable object.
A remotable object is an object that inherits from MarshalByRefObject. There are two types of remotable
objects Marshal-by-value objects and Marshal-by-reference objects.

Marshal-by-value Objects
In marshal-by-value objects are copied by the Remoting system and passed in their entirety to the caller’s
application domain. Once the objects are copied to the caller’s application domain, all method calls and property
accesses are executed entirely within the domain of the calling application. Since the entire object exists in the
caller’s domain, there is no need to marshal access across domain boundaries. Marshal-by-value is ideal for
small objects because smaller objects increase performance by reducing network traffic especially if the objects
needs to be accessed frequently. However because the object exists in the caller application domain, no state
change to the object will be reflected to the originating application domain or from the originator back to the

495
The Complete Reference To Professional SOA with Visual Studio 2005

caller. Marshal-by-value is not ideal for large objects which need to be accessed frequently. We should also keep
in mind to only marshal the field, method or property that we really need to access. This will dramatically reduce
the network requirements.
We create a marshal-by-value object by decorating the class with the [Serializable] attribute see listing 13-1
and listing 13-2.

Listing 13-1. Demonstrates Marshal-by-value using C#

using System;
namespace RemotingSamples {

[Serializable]
public class MarshalByValue {

private int mValue = 1;

public void Increment() {


mValue++;
}

public int getValue() {


return mValue;
}
}
}

Listing 13-2. Demonstrates Marshal-by-value using Visual Basic 2005


Imports System
Namespace RemotingSamples

<Serializable()> _
Public Class MarshalByValue
Dim mValue As Integer = 1

Public Sub Increment ()


mValue += 1
End Sub

Public Function getValue() As Integer


Return mValue
End Function
End Class
End Namespace

In the listing above we have defined a MarshalByValue class which is flagged with the [Serializable]
attribute. This allows the class to be serialized and streamed to and from the server. Additionally, implementing
the ISerializable interface gives us an opportunity to plug into the standard marshalling formatters.

496
The Complete Reference To Professional SOA with Visual Studio 2005

Marshal-by-reference Objects
In marshal-by-reference when a client instantiates a marshal-by-reference object the .NET Remoting
infrastructure creates a proxy object in the caller application domain and returns the reference of that proxy to
the caller. When the client makes calls on the object through the proxy, the Remoting infrastructure marshals the
calls, and sends them to the originator’s application domain. The application domain then invokes the call on the
actual object. The return value from the call and or any out parameters are handled similarly on the way back.
We should use marshal-by-reference objects when the state of the object and any executable functionality
must remain in the application domain in which it was created (that is, on the server).

Listing 13-3. Demonstrates Marshal-by-reference by C#

using System;
namespace RemotingSamples {

public class MarshalByReference: MarshalByRefObject {

public void PrintText(String text) {


Console.WriteLine(text);
}
}
}

Listing 13-4. Demonstrates Marshal-by-reference using Visual Basic 2005

Imports System
Namespace RemotingSamples

Public Class MarshalByReference : Inherits MarshalByRefObject

Sub PrintText(ByVal text As String)


Console.WriteLine(Text)
End Sub
End Class
End Namespace

This example demonstrates how to create an object that derives from MarshalByRefObject on the client.

Tip: It is generally good idea to implement the class of the remote object in a different assembly from that of the remote server itself. This
assembly can then be used by different server applications, and the client application can use it to get the metadata needed to build the
proxy.

Server Activated and Client Activated Objects


When we develop an object, we don’t need to track the creation of the object. we only need to ensure that the
object responds to the method calls. However, when we develop a remote object, we need to track the creation
and initialization of the object because the way a remote object behaves depends on how the object is created and

497
The Complete Reference To Professional SOA with Visual Studio 2005

activated. We have to be aware of how remote objects are activated. We need to specify to the remoting system
what type of activation is required on the objects before the remoting system provides these objects to the clients.
There’re two groups Server Activated Objects (SAOs) and Client-Activated Objects (CAOs).

Server Activated Objects (SAOs)


Server-activated objects are similar to classic stateless Web Services. When a client make a request to a
reference to a SAO, no message is actually sent to the server. The server will only be notified when a method
call is made on the remote reference. Depending on the configuration of its objects, the server then decides
whether a new instance will be created or an existing object will be reused. SAOs can be marked as either
Singleton or SingleCall.

* Singleton – Refers to one instance serving the requests of all clients in a multithreaded fashion. Singleton is
defined by the WellKnownObjectMode.Singleton.

* SingleCall – Refers to a new object created for each request and destroyed afterwards. SingleCall is defined by
the WellKnownObjectMode.SingleCall.

Consider the following example: An insurance company has a service component that enables organizations,
such as insurance brokers and vehicle repair shops, to check the validity of a claim on a car by entering its
registration number. Clients connect to this service and provide the registration number of the vehicle for
validation. The service validates the registration returns the appropriate information from the insurance company
advising claim details on the vehicle. In this scenario, clients are always connected to the server at the insurance
company. The service is activated only when a method call arrives from the clients requesting for details on the
vehicle.

An example of implementation using WellKnownObjectMode.Singleton is shown below.

Listing 13-5. Shows an implementation of Remoting server using WellKnownObjectMode.Singleton in C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

namespace InsuranceServer
{
public class VehicleDetailsServer : MarshalByRefObject
{
public static void Main(string[] args)
{
// Create an instance of a channel
TcpChannel channel = new TcpChannel(8080);
ChannelServices.RegisterChannel(channel, true);

// Register as an available service with the name


// ValidateRegistration
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(InsuranceOperation),

498
The Complete Reference To Professional SOA with Visual Studio 2005

"ValidateRegistration",
WellKnownObjectMode.Singleton);

System.Console.WriteLine
("Press the enter key to exit...");
System.Console.ReadLine();
}
}
}

Listing 13-6. Shows an implementation of Remoting server using WellKnownObjectMode.Singleton in Visual Basic 2005

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp
Imports VBSampleObject
Namespace InsuranceServer

Public Class VehicleDetailsServer


Inherits MarshalByRefObject

Shared Sub Main()


Dim channel As TcpChannel = New TcpChannel(8080)
ChannelServices.RegisterChannel(channel, True)

RemotingConfiguration.RegisterWellKnownServiceType _
(GetType(InsuranceOperation), "ValidateRegistration", _
WellKnownObjectMode.Singleton)
System.Console.WriteLine("Press the enter key to exit...")
System.Console.ReadLine()
End Sub
End Class
End Namespace

The code above shows an implementation of the .NET remoting server using
WellKnownObjectMode.Singleton. By implementing Singleton we have one instance serving all in-coming
requests. The above remoting server implementation will make the remotable object available to the requesting
clients.
To use Single Call so that an object is created for each request and the object is destroyed afterward. We can
use the code below.

Listing 13-7. Demonstrates using SingleCall in C#

RemotingConfiguration.RegisterWellKnownServiceType(
typeof(InsuranceOperation),
"ValidateRegistration",
WellKnownObjectMode.SingleCall);

499
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 13-8. Demonstrates using SingleCall in Visual Basic 2005

RemotingConfiguration.RegisterWellKnownServiceType _
(GetType(VBSampleObject.InsuranceOperation), _
"ValidateRegistration", WellKnownObjectMode.SingleCall)

Notice in the code we’ve specified TcpChannel and assigned a port of 8080. This means that our server will
wait for incoming connections at that port. Once the designated port has been specified we will register the
channel by using ChannelServices.RegisterChannel. .NET 2.0 now supports security with channels we can
register our connection to use security when set to true or false otherwise.
We will be going into more details on channels in a later section.

Listing 13-9. Demonstrates InsuranceOperation class using C#

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

/// <remarks>
/// Sample object to demonstrate the use of .NET Remoting.
/// </remarks>
public class InsuranceOperation : MarshalByRefObject
{
/// <summary>
/// Constructor
/// </summary>
public InsuranceOperation()
{
Console.WriteLine("Constructor has been called");
}

public string ValidateRegistration(string regno)


{
if (regno == "xyz-123")
return "claim has been approved";
else
return "No claim has been lodged";
}
}

Listing 13-10. Demonstrates InsuranceOperation class using Visual Basic 2005

Imports System
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels

Public Class InsuranceOperation


Inherits MarshalByRefObject

Public Sub New()

500
The Complete Reference To Professional SOA with Visual Studio 2005

Console.WriteLine("Constructor has been called")


End Sub

Public Function ValidateRegistration(ByVal regno As String) As String


If regno = "xyz-123" Then
Return "claim has been approved"
Else
Return "No claim has been lodged"
End If
End Function
End Class

The above code implements InsuranceOperation class. the class implements MarshalByRefObject which is
used to marshal the reference calls from the client back to the server. This allows a proxy to be created for the
operations on the server the proxy will then be used to invoke and marshal calls to the server. The constructor in
marshal-by-reference will not be invoked. The SampleObject refered to below is actually the assembly for
InsuranceOperation.

Listing 13-11. The client application using C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

namespace InsuranceClient
{
class Program
{
public static void Main(string[] args)
{
// Create a channel for communicating with the remote object
TcpChannel chan = new TcpChannel();
ChannelServices.RegisterChannel(chan, true);

// Create an instance of the remote object


SampleObject obj = (SampleObject)Activator.GetObject(
typeof(SampleObject),
"tcp://localhost:8080/ValidateRegistration");

// Use the object


if (obj.Equals(null))
{
System.Console.WriteLine("Error: unable to locate server");
}
else
{
Console.WriteLine(obj.ValidateRegistration("xyz-123"));
}
Console.ReadLine();
}
}

501
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 13-12. The client application using Visual Basic 2005

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp
Imports VBSampleObject
Namespace InsuranceClient

Class Program

Shared Sub Main()


Dim chan As TcpChannel = New TcpChannel
ChannelServices.RegisterChannel(chan, True)
Dim obj As SampleObject = CType(Activator.GetObject( _
GetType(SampleObject), _
"tcp://localhost:8080/ValidateRegistration"), SampleObject)
If obj.Equals(Nothing) Then
System.Console.WriteLine("Error: unable to locate server")
Else
Console.WriteLine(obj.ValidateRegistration("xyz-123"))
End If
Console.ReadLine()
End Sub
End Class
End Namespace

The above code shows the client application required to consume our remoting objects. Notice how we have
also registered a channel object. However we do not need to specify a opening port as we will only be requesting
rathering than waiting for incoming connections. In the above code we have used
Activator.GetObject.Activator.GetObject allows us to call the proxy to send messages to the remote object.
However no messages are sent over the network until a method is called on the proxy. Activator.GetObject as
well as using new() are used to call a remoting object as a Server Activated Object. See table 13-3 in the later
section of (Differences between Server Activated Objects and Client Activated Objects) for more detailed
comparisons between SAOs and CAOs.

Figure 13-2. Remoting server

502
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 13-3. Remoting client

Using Configuration File


We can programmatically specify the configuration or we can define the configuration file. The advantage of
using configuration files for Remoting clients and servers is that we do not have to change the code or need to
recompile. Another advantage is that it simplifies the remoting code that we’re required to write.
The xml configuration below shows how to configure for a remoting server (listing 13-13).

Listing 13-13. Shows the xml configuration RemoteServerConfig.xml file for the above remoting server implementation.

<?xml version="1.0" encoding="utf-8" ?>


<configuration>
<system.runtime.remoting>
<application name="ValidateRegistration">
<service>
<wellknown
mode="SingleCall"
type="InsuranceOperation, InsuranceOperation"
objectUri="MyRemoteObject" />
</service>
<channels>
<channel ref="tcp server" port="3080" />
</channels>
</application>
</system.runtime.remoting>
</configuration>

In the above configuration file, RemoteServerConfig.xml, all of the remoting configurations must be added
as child elements to <system.runtime.remoting>. The <application> element defines the name of the application.
The service that is offered from the application must be listed as a child of <service>. This is where we define
the remote object itself. The remote object is defined within the <wellknown> element. Here we need to define
the name of the assembly where the type of this object can be loaded from this is defined in the <type> element.
The last property in the <wellknow> object is the objectUri. objectUri is a name that is assigned to the object
which will be used by the client. The mode attribute is set to SingleCall. If Singleton is required we simply alter
the mode to Singleton:
<service>
<wellknown
mode="Singleton"
type="InsuranceOperation, InsuranceOperation"
objectUri="ValidateRegistration" />
</service>

Once the configuration file has been defined all that the application needs to do is read the configuration file
to activate the channel by using the static method RemotingConfiguration.Configure().

503
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 13-14. The listing below shows the C# implementation of the remoting server

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

namespace InsuranceServer
{
public class VehicleDetailsServer : MarshalByRefObject
{
public static void Main(string[] args)
{
RemotingConfiguration.Configure
("RemoteServerConfig.xml", false);

System.Console.WriteLine
("Press the enter key to exit...");
System.Console.ReadLine();
}
}
}

Listing 13-15. The listing below shows the Visual Basic 2005 implementation of the remoting server

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp
Namespace InsuranceServer

Public Class VehicleDetailsServer


Inherits MarshalByRefObject

Public Shared Sub Main(ByVal args As String())


RemotingConfiguration.Configure _
("RemoteServerConfig.xml", False)
System.Console.WriteLine("Press the enter key to exit...")
System.Console.ReadLine()
End Sub
End Class
End Namespace

Here the server is implemented in a console application. RemotingConfiguration.Configure() reads the


configuration file RemoteServerConfig.xml to configure and activate the channel. The creation of the remote
object and communication with the client is done by the remoting infrastructure. To make sure that the server is
there for the client after it is initialized we use Console.ReadLine() to make sure that the server process will not
end immediately.

504
The Complete Reference To Professional SOA with Visual Studio 2005

Creating a client using configuration file is as simple as creating the server with configuration. Here we will
create a client using a configuration file.

Listing 13-16. Shows RemoteClientConfig.xml which contains the client configuration for remoting.

<?xml version="1.0" encoding="utf-8" ?>


<configuration>
<system.runtime.remoting>
<application name="ValidateRegistrationClient">
<client>
<wellknown
type="InsuranceOperation, InsuranceOperation"
url = "tcp://localhost:3080/ValidateRegistration"/>
</client>
<channels>
<channel ref="tcp client" />
</channels>
</application>
</system.runtime.remoting>
</configuration>

The XML client configuration file RemoteClientConfig.xml uses the <client> element to specify the
interested remote server object. Under <client> we can specify the URL of the server using
protocol://hostname:port/application. In the example we had illustrated we have used tcp as the protocol, and the
server runs on localhost with the port number 3080. The application name of the server is defined with the name
attribute of the <application> element in the server configuration file.
The <wellknown> element specifies the remote object we want to access. As in the server configuration file,
the type attribute defines the type of the remote object and the assembly. The url attribute defines the path to the
remote object. Appended to the URL of the application is the endpoint name ValidateRegistration. The channel
that is configured with the client can again be found in the configuration file machine.config, but this time it is
the client channel and thus specified as “tcp client”.
Let us have a look at the code required to load the configuration settings for the client.

Listing 13-17. Shows the C# code for a remoting client using configurations

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting;

namespace InsuranceClient
{
class Client
{
public static void Main(string[] args)
{
RemotingConfiguration.Configure
("RemoteClientConfig.xml", true);
InsuranceOperation obj = new InsuranceOperation();

505
The Complete Reference To Professional SOA with Visual Studio 2005

// Use the object


if (obj.Equals(null))
{
System.Console.WriteLine
("Error: unable to locate server");
}
else
{
Console.WriteLine(obj.ValidateRegistration("xyz-123"));
}
Console.ReadLine();
}
}
}

Listing 13-18. Shows the Visual Basic 2005 code for a remoting client using configurations

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp
Namespace InsuranceClient

Class Client

Public Shared Sub Main(ByVal args As String())


RemotingConfiguration.Configure _
("RemoteClientConfig.xml", True)
Dim obj As VBSampleObject.InsuranceOperation = _
New VBSampleObject.InsuranceOperation

If obj.Equals(Nothing) Then
System.Console.WriteLine _
("Error: unable to locate server")
Else
Console.WriteLine(obj.ValidateRegistration("xyz-123"))
End If
Console.ReadLine()
End Sub
End Class
End Namespace

As in the server, we can activate the client channel by calling the RemotingConfiguration.Configure(). Using
configuration files we can simply use new to create the remote object. By using new the remoting framework
will automatically reference the remote object for us. Any call made to the reference will be automatically
marshaled to the server.

506
The Complete Reference To Professional SOA with Visual Studio 2005

Client Activated Objects (CAOs)


Client-activated objects are unlike well-known objects, these objects can have states. A client-activated object is
not created with every call it is only instantiated on the server when the client creates it. Client-activated objects
(CAOs) are server-side objects that are activated upon request from the client. When the client submits a request
for a server object using "new" operator or Activator.CreateInstance(), an activation request message is sent to
the remote application. The server then creates an instance of the requested class and returns an ObjRef back to
the client application that invoked it. A proxy is then created on the client side using the ObjRef. The client's
method calls will be executed on the proxy. Client-activated objects can store state information between method
calls for its specific client and not across different client objects. Each invocation of "new" returns a proxy to an
independent instance of the server type. See listing 13-19 and listing 13-20 for an example of client activated
object of the same insurance application in the previous example.

Listing 13-19. Client Activated Object server implementation using C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Activation;

namespace InsuranceServer
{
public class VehicleDetailsServer : MarshalByRefObject
{
public static void Main(string[] args)
{
TcpServerChannel channel = new TcpServerChannel(9080);
ChannelServices.RegisterChannel(channel, true);

RemotingConfiguration.ApplicationName =
"ValidateRegistration";
RemotingConfiguration.RegisterActivatedServiceType
(typeof(InsuranceOperation));

System.Console.WriteLine
("Press the enter key to exit...");
System.Console.ReadLine();
}
}
}

Listing 13-20. Client Activated Object server implementation using Visual Basic 2005

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp

507
The Complete Reference To Professional SOA with Visual Studio 2005

Imports System.Runtime.Remoting.Activation
Namespace InsuranceServer

Public Class VehicleDetailsServer


Inherits MarshalByRefObject

Public Shared Sub Main(ByVal args As String())


Dim channel As TcpServerChannel = _
New TcpServerChannel(9080)
ChannelServices.RegisterChannel(channel, True)
RemotingConfiguration.ApplicationName = _
"ValidateRegistration"
RemotingConfiguration.RegisterActivatedServiceType _
(GetType(VBSampleObject.InsuranceOperation))
System.Console.WriteLine _
("Press the enter key to exit...")
System.Console.ReadLine()
End Sub
End Class
End Namespace

The RemotingConfiguration class provides the RegisterActivatedServiceType method which to allow us to


programmatically configure a type for client activation. We use this method to configure the server application
for the client-activated implementation:

Listing 13-21. Implement client activation using RegisterActivatedServiceType using C#

RemotingConfiguration.RegisterActivatedServiceType
(typeof(InsuranceOperation));

Listing 13-22. Implement client activation using RegisterActivatedServiceType using Visual Basic 2005

RemotingConfiguration.RegisterActivatedServiceType _
(GetType(VBSampleObject.InsuranceOperation))

When the server application executes this line of code, it registers the InsuranceOperation type as a client
activated object. This means that the host will accept client activation requests for the InsuranceOperation type.
Upon receiving an activation request, the Remoting infrastructure instantiates an instance of the
InsuranceOperation class.

Listing 13-23. Client Activated Object InsuranceOperation using C#

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

/// <remarks>
/// Sample object to demonstrate the use of .NET Remoting.
/// </remarks>
public class InsuranceOperation : MarshalByRefObject
{
/// <summary>

508
The Complete Reference To Professional SOA with Visual Studio 2005

/// Constructor
/// </summary>
///

public InsuranceOperation()
{
Console.WriteLine("Constructor has been called");
}

public string ValidateRegistration(string regno)


{
if (regno == "xyz-123")
return "claim has been approved";
else
return "No claim has been lodged";
}
}

Listing 13-24. Client Activated Object InsuranceOperation using Visual Basic 2005

Imports System
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels

Public Class InsuranceOperation


Inherits MarshalByRefObject

Public Sub New()


Console.WriteLine("Constructor has been called")
End Sub

Public Function ValidateRegistration(ByVal regno As String) As String


If regno = "xyz-123" Then
Return "claim has been approved"
Else
Return "No claim has been lodged"
End If
End Function
End Class

The above InsuranceOperation class is similar to the previous server activated InsuranceOperation
implementation except we have added a constructor so that we can see and monitor when the constructor is
called. Unlike server-activated implement client-activated implementation will invoke the constructor.

Listing 13-25. Client Activated Object client implementation using C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting;

509
The Complete Reference To Professional SOA with Visual Studio 2005

using System.Runtime.Remoting.Activation;

namespace InsuranceClient
{
class Client
{
static void Main(string[] args)
{
TcpClientChannel channel = new TcpClientChannel();
ChannelServices.RegisterChannel(channel, true);
object[] attrs = {
new UrlAttribute(
"tcp://localhost:9080/ValidateRegistration") };
InsuranceOperation obj =
(InsuranceOperation)Activator.CreateInstance(
typeof(InsuranceOperation), null, attrs);
// Use the object
if (obj.Equals(null))
{
System.Console.WriteLine
("Error: unable to locate server");
}
else
{
Console.WriteLine(
obj.ValidateRegistration("xyz-123"));
}
Console.ReadLine();

Console.WriteLine();
}
}
}

Listing 13-26. Client Activated Object client implementation using Visual Basic 2005

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp
Imports System.Runtime.Remoting.Activation
Imports VBSampleObject
Namespace InsuranceClient

Class Program

Shared Sub Main()


Dim channel As TcpClientChannel = New TcpClientChannel
ChannelServices.RegisterChannel(channel, True)

Dim attrs As Object() = { _


New UrlAttribute( _

510
The Complete Reference To Professional SOA with Visual Studio 2005

"tcp://localhost:9080/ValidateRegistration")}

Dim obj As InsuranceOperation = _


CType(Activator.CreateInstance( _
GetType(InsuranceOperation), Nothing, attrs), _
InsuranceOperation)

If obj.Equals(Nothing) Then
System.Console.WriteLine("Error: unable to locate server")
Else
Console.WriteLine(obj.ValidateRegistration("xyz-123"))
End If
Console.ReadLine()
End Sub
End Class
End Namespace

The above code listing 13-25, listing 13-26 shows the client implementation using client-activate
implementation. Instead of using the new operator, we can create client-activated objects with the Activator
class. Well-known objects are created with the GetObject() method. Client-activated objects require the method
CreateInstance() this is because the remote object is instantiated on the request of the client. By using the
CreateInstance() method we can also invoke non-default constructors.
By using the Activator.CreateInstance() we can instantiated a client-activated remote object. We must define
the URL to the remote server. The UrlAttribute can be used to provide the URL of the remote object that is
passed to the CreateInstance() method. The second argument of CreateInstance allows passing arguments to the
constructor we can pass any number of parameters or datatype because the parameter value is of object[] type. In
the example in listing 13-25 and listing 13-26 we have defined null as the constructor do not require any
parameters. The last parameter of the Activator.CreateInstance() is the attrs array. This is an object array that has
only one element. This is an UrlAttribute where we specific the URL to the remote object to the constructor of
this class.

Figure 13-4. Server window

The above figure shows an image of the response from the server. We can see that our server is started and when
a request is received the InsuranceOperation’s constructor is executed. Whilst the constructor has also been
executed on the server window shows that the reference call from the client had been marshaled to the server
where it is executed.

511
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 13-5. Client window.

In the above diagram, the client window shows the response from invoking the validation function on the server.

Using Configuration File


For client-activated objects the code required for client and server are the same namely:

Listing 13-27. Loading client configuration using C#

RemotingConfiguration.Configure
("RemoteClientConfig.xml", true);
InsuranceOperation obj = new InsuranceOperation();

Listing 13-28. Loading client configuration using Visual Basic 2005

RemotingConfiguration.Configure _
("RemoteClientConfig.xml", True)
Dim obj As InsuranceOperation = New InsuranceOperation

The code required to load configuration for that of server-activate and client-activated are the same.

Listing 13-29. Loading server configuration using C#

RemotingConfiguration.Configure
("RemoteServerConfig.xml", false);

Listing 13-30. Loading server configuration using Visual Basic 2005

RemotingConfiguration.Configure _
("RemoteServerConfig.xml", True)

Though the XML configuration which defines client activated code is slightly different.

Listing 13-31. RemoteClientConfig.xml client configuration

<?xml version="1.0" encoding="utf-8" ?>


<configuration>
<system.runtime.remoting>
<application name="ValidateRegistration">
<service>
<wellknown

512
The Complete Reference To Professional SOA with Visual Studio 2005

mode="SingleCall"
type="InsuranceOperation, InsuranceOperation"
objectUri="ValidateRegistration" />
</service>
<channels>
<channel ref="tcp server" port="3080" />
</channels>
</application>
</system.runtime.remoting>
</configuration>

Listing 13-32. RemoteServerConfig.xml client configuration

<?xml version="1.0" encoding="utf-8" ?>


<configuration>
<system.runtime.remoting>
<application name="ValidateRegistration">
<service>
<activated type="InsuranceOperation,
InsuranceOperation" />
</service>
<channels>
<channel ref="tcp server" port="9080" />
</channels>
</application>
</system.runtime.remoting>
</configuration>

The server configuration file must set the tag <activated> instead of <wellknown>. With the <activated> tag,
only the type attribute with the namespace and assembly name must be defined.

Using Lifetime Leases


Client-activated objects use lifetime leases to determine the duration of their existence. When a client creates an
object, it specifies a default duration for which the object should exist. If the remote object reaches the end of its
default lifetime duration, the object contacts the client and asks whether it should continue to exist and for how
long. If the client is not currently available, a default time limit is specified for which the server object waits
while trying to contact the client before marking itself available for garbage collection. The client might even
request an indefinite default lifetime, preventing the remote object from being recycled until the server
application domain is torn down.
The lifetime of a marshal-by-reference object is the duration for which the object resides in memory. All
marshal-by-reference server-activated and client-activated objects have a lifetime of their own. These objects
are released from memory after the lifetime expires and the object is marked for garbage collection. The garbage
collector then removes the objects from memory.
The .NET Remoting system deletes an object only when it is marked as ready for garbage collection. The
lifetime lease manager of the server application domain is responsible for determining the objects that are ready
for garbage collection. However, a sponsor object can request a new lease for a particular object by registering
itself with the lease manager.

513
The Complete Reference To Professional SOA with Visual Studio 2005

A lifetime lease is created for the marshal-by-reference object when the object is remoted outside an
application domain. Each application domain contains a lease manager that manages the leases in its domain.
The role of the lease manager is to periodically review the leases for expiration. If a lease expires, the lease
manager goes through its list of sponsors for that object and checks to see if any of the sponsors want to renew
the object’s lease. If no sponsor wishes to renew the lease then the lease manager removes the lease. The object
is then deleted, and garbage collection reclaims the object memory. As such the lifetime of an object can be
extended to longer than specified by its lifetime lease.
There are a few ways in which we can influence leasing times of objects. One way is to use configuration
files, and another way is to do it programmatically for the server, the remote object, or in the client. Let us look
at what can be configured first.

Table 13-2. Default configuration

Attribute Description

leaseTime Define the period of the lease for the application. The default leaseTime is 5
minutes.

sponsorshipTimeout Define the period of time the lease manager waits for the sponsor to respond
when notified that a lease has expired. If the sponsor does not respond in the
specified time. The garbage collector disposes of the remote object. The
default period is 2 minutes.

renewOnCallTime Define the amount of time that the lease time is extended when a function call
is made on the object. The default period is 2 minutes.

leaseManagerPollTime Define how often the lease manager should check the expiration of the lease.
The default period is 10 seconds.

Configuration
The below configuration contains information about the lifetime of all client-activated objects serviced by this
application

Listing 13-33. The below configuration can be set inside the configuration of the remoting application

<lifetime
leaseTime="5M"
sponsorshipTimeOut="2M"
renewOnCallTime="2M"
leaseManagerPollTime="10S"
/>
The configuration listed in listing 13-33 will set the lease time to five minutes, sponsorshiptime out to 2
minutes, renew on call time to two minutes and lease manager poll time to ten seconds. Valid values for
each are a decimal number and a time unit. Time units are defined as D for days, H for hours, M for
minutes, S for seconds, and MS for milliseconds.

Listing 13-34. The xml configuration below shows a remoting client application’s configuration file with lifetime leases.

<?xml version="1.0" encoding="utf-8" ?>


<configuration>

514
The Complete Reference To Professional SOA with Visual Studio 2005

<system.runtime.remoting>
<application name="ValidateRegistration">
<service>
<activated type="InsuranceOperation,
InsuranceOperation" />
</service>
<channels>
<channel ref="tcp server" port="9080" />
</channels>

<lifetime leaseTime="10M"
sponsorshipTimeOut="2M"
renewOnCallTime="2M"
leaseManagerPollTime="10S"/>

</application>
</system.runtime.remoting>
</configuration>

Code
Setting the lifetime option in the configuration file is quite useful especially if we wanted to have the same
lifetime management for all objects for the server. If we need to define remote objects with different lifetime
requirements then we would need to set the lifetime for the object programmatically.
We can configure the lifetime lease within our code. To do this we need to override the
InitializeLifetimeService function of the MarshalByRefObject class. The following is the syntax used to override
the InitializeLifetimeService function see listing 13-35 and 13-36.

Listing 13-35. C# implementation of configuring lease by code

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Lifetime;

public class InsuranceOperation : MarshalByRefObject


{
/// <summary>
/// Constructor
/// </summary>
///

public InsuranceOperation()
{
Console.WriteLine("Constructor has been called");
}

public string ValidateRegistration(string regno)


{
if (regno == "xyz-123")

515
The Complete Reference To Professional SOA with Visual Studio 2005

return "claim has been approved";


else
return "No claim has been lodged";
}

public override object InitializeLifetimeService()


{
ILease lease = (ILease)base.InitializeLifetimeService();
if (lease.CurrentState == LeaseState.Initial)
{
lease.InitialLeaseTime = TimeSpan.FromMinutes(2);
lease.SponsorshipTimeout = TimeSpan.FromMinutes(3);
lease.RenewOnCallTime = TimeSpan.FromSeconds(3);
}
return lease;
}
}

Listing 13-36. Visual Basic 2005 implementation of configuring lease by code

Imports System
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Lifetime

Public Class InsuranceOperation


Inherits MarshalByRefObject

Public Sub New()


Console.WriteLine("Constructor has been called")
End Sub

Public Function ValidateRegistration(ByVal regno As String) _


As String
If regno = "xyz-123" Then
Return "claim has been approved"
Else
Return "No claim has been lodged"
End If
End Function

Public Overloads Overrides Function _


InitializeLifetimeService() As Object
Dim lease As ILease = _
CType(MyBase.InitializeLifetimeService, ILease)
If lease.CurrentState = LeaseState.Initial Then
lease.InitialLeaseTime = TimeSpan.FromMinutes(2)
lease.SponsorshipTimeout = TimeSpan.FromMinutes(3)
lease.RenewOnCallTime = TimeSpan.FromSeconds(3)
End If
Return lease
End Function

516
The Complete Reference To Professional SOA with Visual Studio 2005

End Class

The LeaseTime option defines the remote object’s maximum time to lease. The object will be deactivated if
the client does not need the remote object for this time period. Every time a method is invoked the leasing time is
incremented by the value defined with within RenewOnCallTime.
In listing 13-35 and listing 13-36, we have set the InitialLeaseTime to two minutes, SponsorshipTimeout to
three minutes and RenewOnCallTime to three. In the remote object class we can override the
InitializeLifetimeService() method. The method InitializeLifetimeService() from the base class MarshalByRefObject
returns a reference to the ILease interface that can be used to change the default values. Changing the values is
only possible as long as the lease has not been activated, so that is why we need to check for the current state to
compare it with the enumeration value LeaseState.Initial.

Renewing Lifetime Leases


After we have created a lifetime lease for an object, we can only extend LeaseTime property of the lease object.
The CurrentLeaseTime property returns the amount of time remaining on the lease. One way to renew the lease
is by having the client application call the ILease.Renew method. The other way is to have a sponsor renew the
lease.
The listing 13-37 and 13-38 shows how we can use ILease.Renew to extend our lease time.

Listing 13-37. Shows implementation of ILease.Renew in C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Activation;
using System.Runtime.Remoting.Lifetime;
using System.Threading;

namespace InsuranceClient
{
class Client
{
static void Main(string[] args)
{
TcpClientChannel channel = new TcpClientChannel();
ChannelServices.RegisterChannel(channel, true);
object[] attrs = {
new UrlAttribute(
"tcp://localhost:9080/ValidateRegistration") };
InsuranceOperation obj =
(InsuranceOperation)Activator.CreateInstance(
typeof(InsuranceOperation), null, attrs);
// Use the object

Thread.Sleep(5000);
ILease lease =
(ILease)RemotingServices.GetLifetimeService(obj);

517
The Complete Reference To Professional SOA with Visual Studio 2005

Console.WriteLine("Current Lease Time: " +


lease.CurrentLeaseTime);
TimeSpan expireTime =
lease.Renew(TimeSpan.FromMinutes(5));
Console.WriteLine("After Lease Renew: " + expireTime);
if (obj.Equals(null))
{
System.Console.WriteLine
("Error: unable to locate server");
}
else
{
Console.WriteLine(
obj.ValidateRegistration("xyz-123"));
}
Console.ReadLine();

Console.WriteLine();
}
}
}

Listing 13-38. Shows implementation of ILease.Renew in Visual Basic 2005

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp
Imports System.Runtime.Remoting.Activation
Imports VBSampleObject
Imports System.Runtime.Remoting.Lifetime
Imports System.Threading
Namespace InsuranceClient

Class Program

Shared Sub Main()


Dim channel As TcpClientChannel = New TcpClientChannel
ChannelServices.RegisterChannel(channel, True)
Dim attrs As Object() = { _
New UrlAttribute("tcp://localhost:9080/ValidateRegistration")}
Dim obj As InsuranceOperation = _
CType(Activator.CreateInstance(GetType(InsuranceOperation), _
Nothing, attrs), InsuranceOperation)

Thread.Sleep(5000)
Dim lease As ILease = _
CType(RemotingServices.GetLifetimeService(obj), ILease)
Console.WriteLine("Current Lease Time: " + _
lease.CurrentLeaseTime.ToString())

518
The Complete Reference To Professional SOA with Visual Studio 2005

Dim expireTime As TimeSpan = _


lease.Renew(TimeSpan.FromMinutes(5))
Console.WriteLine("After Lease Renew: " + _
expireTime.ToString())

If obj.Equals(Nothing) Then
System.Console.WriteLine("Error: unable to locate server")
Else
Console.WriteLine(obj.ValidateRegistration("xyz-123"))
End If
Console.ReadLine()
End Sub
End Class
End Namespace

In the above code we’re using the ILease interface of the remote object by calling the method
GetLifetimeService(). Calling the property CurrentLeaseTime we can access the actual value of the lease to
display it in the console. We then renew the lease time by another 5 minutes. The result is shown in figure 13-6.

Figure 13-6. Shows the result from the renewal in leaes time.

In figure 13-6 we can see that even though five seconds has elapsed and the lease time is set at four minutes
and fifty-five seconds. By renewing our lease time to five minutes it has reset the lease time.

Differences between Server Activated Objects and Client Activated


Objects
The difference between server activated and client activated objects are shown in the table below.

Table 13-3. The table above highlights the difference between server-activated and client-activated objects.

Single Call/Singleton Objects Client-Activated Objects

Client side- a) Activator.GetObject() a) Activator.CreateInstance()


activation code
b) new() with config file b) new() with CFG file
(Code required
on the client Client's config file references the URL: Client's CFG file references the URL. For
side) example
ValidateRegistration = http://localhost:80/
http://localhost:80/ValidateRegistration
ValidateRegistration/ ValidateRegistration.soap

519
The Complete Reference To Professional SOA with Visual Studio 2005

Activation of the Message is only sent when the first method call is Activation messages is sent to the server
server object made. No activation messages is sent upon when a proxy is created after the client
requesting the reference. Constructor is not creates the object. Constructors with
executed. parameters are supported.

Lifetime of the The lifetime for single call and singleton is Lifetime is the earlier of these two events:
server object determined by the configuration on the server.
a) Lease expires
Singleton objects are also subjected to lifetime
management. b) When the client loses its reference on the
server object

Server side a) Use configuration file to specify the type configuration file can be used to export the
registration (SingleCall or Singleton). client-activated object.
b) Use RegisterWellKnownServiceType() api to
register the type.

Advantages of a) Clients can be compiled against server a) Classic COM "coclass" like invocation of
the models component’s base class or interface definition. the server object.
b) Useful to perform finite operations on the b) Gives clients more flexibility to govern the
server side. server object's lifetime.
c) Applications that uses Single call objects are c) Client can pass constructor parameters to
easily deployed in a Load Balanced environment, the created object.
as they don't hold state.
d) Server Objects can hold state for its
d) Singleton Objects can maintain state specific client between method calls.
information across client objects.

Transport Channels
Channels are stateless objects that transport messages between applications across remoting boundaries, whether
between application domains, processes, or computers. A channel can listen on an endpoint for inbound
messages, send outbound messages to another endpoint, or both. This allows us to plug in a wide range of
protocols, even if the common language runtime is not at the other end of the channel. The .NET Remoting
infrastructure defines three kinds of channels: TCP, HTTP and IPC. IPC is the named pipe protocol which can be
used to transmit messages. In remoting it also is possible to create our own custom channels and plug them into
the .NET Remoting infrastructure.
The .NET Framework provides the System.Runtime.Remoting.Channels name-space, which includes the
interfaces and classes that we use to work with channels. All channels implement the IChannel interface. The
IChannel interface provides properties such as ChannelName and ChannelPriority, which uniquely identify a
channel and define the channel priority, respectively.

TCP Channel
The TCP protocol is support by the .NET remoting infrastructure. TCP protocol is utilized for transporting
serialized stream across .NET Remoting boundaries. The TcpChannel type is defined in the
System.Runtime.Remoting.Channels.Tcp namespace. Which implements the IChannel, IChannelReceiver, and
IChannelSender interfaces. This means that the TcpChannel supports both sending and receiving data across the

520
The Complete Reference To Professional SOA with Visual Studio 2005

.NET Remoting boundaries. The TcpChannel type uses binary wire format to serialize object by default. We had
demonstrated implementing Remoting by using TCP in the previous example.

HTTP Channel
The .NET Remoting infrastructure also provides a transport that utilizes the HTTP protocol for transporting the
serialized message stream across the Internet. By utilizing HTTP it is particularly useful across network
boundaries where there are firewalls. As HTTP is a typical web protocol most networks support HTTP. The
HttpChannel type defined in the System .Runtime.Remoting.Channels.Http namespace implements the HTTP
transport functionality. Like the TcpChannel type, HttpChannel can send and receive data across .NET Remoting
boundaries. The HttpChannel type serializes message objects by using a SOAP wire format by default. The
below shows an application implementing HTTP channel configuration.

Listing 13-39. Implementation of Server using C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;

namespace InsuranceServer
{
public class VehicleDetailsServer : MarshalByRefObject
{
public static void Main(string[] args)
{
// Create an instance of a channel
HttpChannel channel = new HttpChannel(8081);
ChannelServices.RegisterChannel(channel, false);

// Register as an available service with the name


// ValidateRegistration
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(InsuranceOperation),
"ValidateRegistration",
WellKnownObjectMode.Singleton);

System.Console.WriteLine
("Press the enter key to exit...");
System.Console.ReadLine();
}
}
}

Listing 13-40. Implementation of Server using Visual Basic 2005

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.Remoting

521
The Complete Reference To Professional SOA with Visual Studio 2005

Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Http
Imports System.Runtime.Remoting.Activation
Imports VBSampleObject
Namespace InsuranceServer

Public Class VehicleDetailsServer


Inherits MarshalByRefObject

Public Shared Sub Main(ByVal args As String())


Dim channel As HttpChannel = New HttpChannel(8081)
ChannelServices.RegisterChannel(channel, False)
RemotingConfiguration.RegisterWellKnownServiceType _
(GetType(InsuranceOperation), "ValidateRegistration", _
WellKnownObjectMode.Singleton)
System.Console.WriteLine("Press the enter key to exit...")
System.Console.ReadLine()
End Sub
End Class
End Namespace

In the listing above we have demonstrated creating a remoting server using HTTP protocol by creating an
instance of the HttpChannel type that listens for incoming connections on port 8081. We can change the port to
any available number on the systems.

Note: Keep in mind that Internet Information Services (IIS) runs on port 80. If port 80 is already occupied then we will need to specify
another port. This may involve opening the port in the firewall.

Listing 13-41. Implementation of the client remoting application using C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;

namespace InsuranceClient
{
class Client
{
public static void Main(string[] args)
{
// Create a channel for communicating with the remote object
HttpChannel chan = new HttpChannel();
ChannelServices.RegisterChannel(chan, false);

// Create an instance of the remote object


InsuranceOperation obj =
(InsuranceOperation)Activator.GetObject(
typeof(InsuranceOperation),

522
The Complete Reference To Professional SOA with Visual Studio 2005

"http://localhost:8081/ValidateRegistration");

// Use the object


if (obj.Equals(null))
{
System.Console.WriteLine
("Error: unable to locate server");
}
else
{
Console.WriteLine(obj.ValidateRegistration("xyz-123"));
}
Console.ReadLine();
}
}
}

Listing 13-42. Implementation of the client remoting application using Visual Basic 2005

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Http
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Activation
Imports VBSampleObject
Namespace InsuranceClient

Class Client

Shared Sub Main(ByVal args As String())


Dim chan As HttpChannel = New HttpChannel
ChannelServices.RegisterChannel(chan, False)
Dim obj As InsuranceOperation = _
CType(Activator.GetObject(GetType(InsuranceOperation), _
"http://localhost:8081/ValidateRegistration"), _
InsuranceOperation)

If obj.Equals(Nothing) Then
System.Console.WriteLine("Error: unable to locate server")
Else
Console.WriteLine(obj.ValidateRegistration("xyz-123"))
End If
Console.ReadLine()
Console.WriteLine()
End Sub
End Class
End Namespace

523
The Complete Reference To Professional SOA with Visual Studio 2005

The above code shows the implementation of the remoting client implementing HTTP channel. Switching
between TCP, HTTP and IPC is fairly simple in most cases its just a simple matter of substituting the TCP for
HTTP or for IPC.
Using HTTP Channel we can also view the wsdl document generated by using a browser. We can do this by
simply browsing to http://localhost/ValidateRegisration?wsdl to view the WSDL document.

Figure 13-7. The figure above shows the WSDL document for the remoting object.

IPC Channel
With the release of .NET Framework 2.0 the .NET Remoting infrastructure now provide Inter-Process
Communication (IPC). IPC is a form of communication channel for .NET Remoting and can be used with the
IPC system of the Windows operating system. Since IPC does not use network communication. The IPC channel
is thus much faster than the HTTP and TCP channel. But it can only be used for communication between
application domains on the same physical computer. Like the HTTP and TCP channels the IpcChannel Type is
defined in the System.Runtime.Remoting.Channels.Ipc namespace which implements the IPC transport
functionality. The IpcChannel can send and receive data across the .NET remoting boundaries but only on the
same physical machine. In the example below the usage of an application implementing IPC channel
configuration is demonstrated (see listing 13-43 and listing 13-44).

Listing 13-43. The below code shows the IPC Server implementation using C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;

namespace InsuranceServer
{
public class VehicleDetailsServer : MarshalByRefObject

524
The Complete Reference To Professional SOA with Visual Studio 2005

{
public static void Main(string[] args)
{
// Create an instance of a channel
IpcChannel channel = new IpcChannel("ValidateRegistration");
// register the channel with security disabled
ChannelServices.RegisterChannel(channel, false);

// Register as an available service with the name


// ValidateRegistration
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(InsuranceOperation),
"ValidateRegistration",
WellKnownObjectMode.Singleton);

System.Console.WriteLine
("Press the enter key to exit...");
System.Console.ReadLine();
}
}
}

Listing 13-44. The below code shows the IPC Server implementation using Visual Basic 2005

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Ipc
Imports System.Runtime.Remoting.Activation
Imports VBSampleObject
Namespace InsuranceServer

Public Class VehicleDetailsServer


Inherits MarshalByRefObject

Public Shared Sub Main(ByVal args As String())


Dim channel As IpcChannel = _
New IpcChannel("ValidateRegistration")
‘register the channel with security disabled
ChannelServices.RegisterChannel(channel, False)
RemotingConfiguration.RegisterWellKnownServiceType _
(GetType(InsuranceOperation), "ValidateRegistration", _
WellKnownObjectMode.Singleton)
System.Console.WriteLine("Press the enter key to exit...")
System.Console.ReadLine()
End Sub
End Class
End Namespace

525
The Complete Reference To Professional SOA with Visual Studio 2005

In the listing above in listing 13-43 and listing 13-44 we have demonstrated creating a remoting server using
the IPC protocol by creating an instance of the IpcChannel type that listens for incoming connections on the
named pipe that we have created called “ValidateRegistration”. The IpcChannel is then registered using the
ChannelServices.RegisterChannel() function. The first parameter for the RegisterChannel is the IpcChannel object
that we had created. The second parameter for the RegisterChannel method is a Boolean value which defines
whether we want to enable security for the channel in this case we have specified false to disable.

Listing 13-45. The below code shows the IPC Client implementation using C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;

namespace InsuranceClient
{
class Client
{
public static void Main(string[] args)
{
// Create a channel for communicating with the remote object
IpcChannel chan = new IpcChannel();
ChannelServices.RegisterChannel(chan, false);

// Create an instance of the remote object


InsuranceOperation obj = (InsuranceOperation)
Activator.GetObject(typeof(InsuranceOperation),
"ipc://ValidateRegistration/ValidateRegistration");

// Use the object


if (obj.Equals(null))
{
System.Console.WriteLine
("Error: unable to locate server");
}
else
{
Console.WriteLine(obj.ValidateRegistration("xyz-123"));
}
Console.ReadLine();
}
}
}

Listing 13-46. The below code shows the IPC Client implementation using Visual Basic 2005

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Ipc

526
The Complete Reference To Professional SOA with Visual Studio 2005

Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Activation
Imports VBSampleObject
Namespace InsuranceClient

Class Client

Shared Sub Main(ByVal args As String())


Dim chan As IpcChannel = New IpcChannel
ChannelServices.RegisterChannel(chan, False)
Dim obj As InsuranceOperation = _
CType(Activator.GetObject(GetType(InsuranceOperation), _
"ipc://ValidateRegistration/ValidateRegistration"), _
InsuranceOperation)

If obj.Equals(Nothing) Then
System.Console.WriteLine _
("Error: unable to locate server")
Else
Console.WriteLine(obj.ValidateRegistration("xyz-123"))
End If
Console.ReadLine()
Console.WriteLine()
End Sub
End Class
End Namespace

The above code shows the implementation of the remoting client implementing IPC channel. Notice that we
don’t need to specify a port number for IPC we only need to specify the named pipe as well as the remotable
instance of the remoting server. This is because IPC can only used on the same computer. It is ideal for
application to application communication.

Channel Sinks
The .NET Remoting architecture is very flexible because it possesses a clear separation of object responsibilities.
The channel architecture employs a series of channel sink objects linked together into a sink chain. Each channel
sink within the chain has a clearly defined role in the processing of the message. The channel sink performs
certain functions on the message before the message is forwarded onto the next channel sink in the chain. Within
the channel sink chain we can access the message that is routed to or coming from a Remoting object. This
allows us to perform tasks such as logging, security, custom encryption, applying filters, and imposing other
security restrictions.

527
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 13-8. shows channel sink chains on the client and on the server.

In the above figure the client object makes calls on a transparent proxy, which in turn converts the method call
into a message object. The message object is routed through the context sink chains until it reaches the formatter
sink which is the first sink in the chain. The formatter sink is responsible for serializing the message object to a
byte stream by using a particular wire format. The formatter sink then passes the stream to the next sink in the
chain for further processing. The last sink in the channel sink chain is responsible for transporting the stream
over the wire by using a specific transport protocol.
To implement channel sink providers to create channel sink chains. We need to implement properties and
methods that implement the IClientChannelSinkProvider, IClientFormatterSinkProvider, or
IServerChannelSinkProvider interfaces. So that when we activate a remote object, the remoting system retrieves
the channel sink provider from the current channel and calls the CreateSink method on the channel sink provider
to create the first channel in the chain. When the CreateSink method is invoked, it creates its own channel sink.
The CreateSink call is forwarded to the next sink provider in the chain (if one exists), it ensures that the next sink
and the current one are linked together. The first channel sink on a client must be a formatter sink that serializes
the message into a stream. The last sink on the channel sink chain should be a transport sink that sends the
stream over the network wire.

Remotable Bank Debit Log


Message sinks adds flexibility to the .NET Remoting architecture. These sinks can be chained together to form
message sink chains, which processes .NET Remoting messages and move them through contexts and
application domains.
In this section we will be implementing a simple remotable Bank debit application using message sinks to
monitor the various stages of the incoming request as well as response on both the client and the server.

528
The Complete Reference To Professional SOA with Visual Studio 2005

The Server
We will start with the Server implementation of our remotable Bank debit application which only needs to
perform a simple BankDebit() operation.

Listing 13-47. Shows the server implementation in C#

using System;
using System.Threading;
using System.Security;
using System.Security.Principal;
using System.Runtime.Remoting;

class Calc : MarshalByRefObject, IBank


{
private static double bankbalance = 500.145;
public double BankDebit( double amt )
{
Console.WriteLine("Calling BankDebit method");
Console.WriteLine("Current balance: $" + bankbalance);
Console.WriteLine("Debit amount: $" + amt);
bankbalance -= amt;
Console.WriteLine("Balance after debit: $" + bankbalance);
return (bankbalance);
}
}

class Server
{
static void Main(string[] args)
{
RemotingConfiguration.Configure(
AppDomain.CurrentDomain.BaseDirectory +
"server.config", false);

Console.WriteLine("Press enter to exit the server");


Console.ReadLine();
}
}

Listing 13-48. Shows the server implementation in Visual Basic 2005

Imports System
Imports System.Threading
Imports System.Security
Imports System.Security.Principal
Imports System.Runtime.Remoting
Imports icalc
Imports System.Collections
Imports System.IO
Imports System.Runtime.Remoting.Messaging
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Serialization.Formatters

529
The Complete Reference To Professional SOA with Visual Studio 2005

Class Calc
Inherits MarshalByRefObject
Implements icalc.IBank

Private Shared bankbalance As Double = 500.145

Public Function BankDebit(ByVal amt As Double) As Double Implements IBank.BankDebit


Console.WriteLine("Calling BankDebit method")
Console.WriteLine("Current balance: $" + bankbalance.ToString())
Console.WriteLine("Debit amount: $" + amt.ToString())
bankbalance -= amt
Console.WriteLine("Balance after debit: $" + bankbalance.ToString())
Return (bankbalance)
End Function
End Class

Class Server

Shared Sub Main(ByVal args As String())


RemotingConfiguration.Configure _
(AppDomain.CurrentDomain.BaseDirectory + _
"server.config", False)

Console.WriteLine("Press enter to exit the server")


Console.ReadLine()
End Sub
End Class

In the server implementation we have a Clac class which will be exposed with the BankDebit() function.
This function will perform the debit by the specified amount though we will be closely monitoring the request as
well as the response of the call to the function using remoting sinks. The functionality of BankDebit() is exposed
through our configuration file Server.config.

Listing 13-49. Server.config file

<configuration>
<system.runtime.remoting>
<application name="calcsrv">

<service>
<wellknown mode="Singleton"
type="Calc, server" objectUri="calc" />
</service>

<channels>
<channel ref="http" port="8081">
<serverProviders>
<formatter ref="soap" />
<provider ref="wsdl"/>
<provider type="ServerSinkProvider, Sink"/>
</serverProviders>

530
The Complete Reference To Professional SOA with Visual Studio 2005

</channel>
</channels>

</application>
</system.runtime.remoting>
</configuration>

In the configuration file we have registered the server as a Singleton. Notice that under the channel element,
we added the element serverProviders. The serverProviders element contains three elements. The first element
under serverProviders is formatter. The second element is where we tell the remoting server to add support for
the wsdl document. The third element is the provider element. This is where our sink is added by using the type
attribute. The type attributes defines the class required and the assembly where the class can be found.
We will now look at the implementation of the sink on the server.

Listing 13-50. Shows the implementation of the ServerSinkProvider in C#

public class ServerSinkProvider : IServerChannelSinkProvider


{
private IServerChannelSinkProvider next = null;

public ServerSinkProvider()
{
Console.WriteLine("Entering constructor ServerSinkProvider");
}

public ServerSinkProvider(IDictionary properties,


ICollection providerData)
{
Console.WriteLine("Entering constructor" +
"ServerSinkProvider with parameters");
}

public void GetChannelData(IChannelDataStore channelData)


{
Console.WriteLine("Entering GetChannelData");
}

public IServerChannelSink CreateSink(IChannelReceiver channel)


{
Console.WriteLine("Entering CreateSink");
IServerChannelSink nextSink = null;
if (next != null)
{
nextSink = next.CreateSink(channel);
}
return new ServerSink(nextSink);
}

public IServerChannelSinkProvider Next


{
get

531
The Complete Reference To Professional SOA with Visual Studio 2005

{
Console.WriteLine("Getting Next Server Channel Sink");
return next;
}
set
{
Console.WriteLine("Setting Next Server Channel Sink");
next = value;
}
}

Listing 13-51. Shows the implementation of the ServerSinkProvider in Visual Basic 2005

Public Class ServerSinkProvider


Implements IServerChannelSinkProvider
Private [next] As IServerChannelSinkProvider = Nothing

Public Sub New()


Console.WriteLine("Entering constructor ServerSinkProvider")
End Sub

Public Sub New(ByVal properties As IDictionary, _


ByVal providerData As ICollection)
Console.WriteLine("Entering constructor" + _
" ServerSinkProvider with parameters")
End Sub

Public Sub GetChannelData(ByVal channelData As IChannelDataStore) _


Implements IServerChannelSinkProvider.GetChannelData
Console.WriteLine("Entering GetChannelData")
End Sub

Public Function CreateSink(ByVal channel As IChannelReceiver) _


As IServerChannelSink Implements IServerChannelSinkProvider.CreateSink
Console.WriteLine("Entering CreateSink")
Dim nextSink As IServerChannelSink = Nothing
If Not ([next] Is Nothing) Then
nextSink = [next].CreateSink(channel)
End If
Return New ServerSink(nextSink)
End Function

Public Property Nextx() As IServerChannelSinkProvider _


Implements IServerChannelSinkProvider.Next
Get
Console.WriteLine("Getting Next Server Channel Sink")
Return [next]
End Get
Set(ByVal value As IServerChannelSinkProvider)
Console.WriteLine("Setting Next Server Channel Sink")

532
The Complete Reference To Professional SOA with Visual Studio 2005

[next] = value
End Set
End Property
End Class

The channel sinks are connected to a server channel through implementations of the
IServerChannelSinkProvider interface. Channel sink providers are stored in a chain, this allows us to manipulate
and customize chaining all channel sink providers together IServerChannelSinkProvider provides a property
called Next for this.
When multiple channel sink providers are specified in a configuration file, the remoting infrastructure will
chain them together in the order they were found in the configuration file. During a
RemotingConfiguration.Configure call the channel sink providers are created at the same time as the channel.
In order to create the server provider we need to implement the methods defined by the
IServerChannelSinkProvider interface.

Figure 13-9. The IServerChannelSinkProvider interface

Table 13-4. In order to implement IServerChannelSinkProvider we need to implement the following methods and property.

Name Description

CreateSink Create a sink chain.

GetChannelData Retrieve the channel data for current sink.

Next Get or set the next sink provider in the channel sink provider chain.
There are three members of IServerChannelSinkProvider. The first is a method called CreateSink(). This is
where we can create our own custom channel sinks. CreateSink() creates the new channel sink (ServerSink). But
notice it also forwards the CreateSink call to the next sink provider in the chain (if there is one).

Listing 13-52. Forwarding CreateSink call using C#

if (next != null)
{
nextSink = next.CreateSink(channel);
}

Listing 13-53. Forwarding CreateSink call using Visual Basic 2005

If Not ([next] Is Nothing) Then


nextSink = [next].CreateSink(channel)
End If
In listing 13-52 and listing 13-53 the CreateSink function is responsible for ensuring that the next sink that is
created are linked together.

533
The Complete Reference To Professional SOA with Visual Studio 2005

The second member of IServerChannelSinkProvider is the GetChannelData method. GetChannelData extracts


information from the provider's IChannelDataStore member.
Because GetChannelData is a member of the IServerChannelSinkProvider interfaces, this member is present in all
channel sink providers.
The last member of the IServerChannelSinkProvider is the Next property. This property simply gets or sets
the next sink in the channel sink provider chain. Usually, this would be called before the CreateSink method to
set the next provider in the chain so that the CreateSink method knows which provider to forward the CreateSink
method call to.
Once the provider has been implemented we will need to implement the ServerSink. A server ChannelSink
must implement IServerChannelSink or IClientChannelSink depending on which side of the remoting
infrastructure it is designed to run on.

Listing 13-54. Shows the ServerSink implementation in C#

public class ServerSink : BaseChannelObjectWithProperties,


IServerChannelSink, IChannelSinkBase
{
private IServerChannelSink _next;

public ServerSink(IServerChannelSink next)


{
Console.WriteLine("Entering ServerSink");
_next = next;
}

public void AsyncProcessResponse


(IServerResponseChannelSinkStack sinkStack,
object state, IMessage msg, ITransportHeaders headers,
Stream stream)
{
Console.WriteLine("Entering AsyncProcessResponse");
}

public Stream GetResponseStream


(IServerResponseChannelSinkStack sinkStack, object state,
IMessage msg, ITransportHeaders headers)
{
Console.WriteLine("Entering GetResponseStream");
return null;
}

public ServerProcessing ProcessMessage(


IServerChannelSinkStack sinkStack, IMessage requestMsg,
ITransportHeaders requestHeaders, Stream requestStream,
out System.Runtime.Remoting.Messaging.IMessage responseMsg,
out ITransportHeaders responseHeaders,
out Stream responseStream)
{
Console.WriteLine("Entering ProcessMessage");

ServerProcessing spres = _next.ProcessMessage


(sinkStack, requestMsg, requestHeaders, requestStream,
out responseMsg, out responseHeaders, out responseStream);

534
The Complete Reference To Professional SOA with Visual Studio 2005

return spres;
}

public IServerChannelSink NextChannelSink


{
get
{
Console.WriteLine("Getting NextChannelSink");
return _next;
}
}
}

Listing 13-55. Shows the ServerSink implementation in Visual Basic 2005

Public Class ServerSink


Inherits BaseChannelObjectWithProperties
Implements IServerChannelSink
Implements IChannelSinkBase
Private _next As IServerChannelSink

Public Sub New(ByVal [next] As IServerChannelSink)


Console.WriteLine("Entering ServerSink Constructor")
_next = [next]
End Sub

Public Overrides ReadOnly Property Properties() _


As System.Collections.IDictionary _
Implements IChannelSinkBase.Properties
Get
Dim hashProperties As Hashtable = New Hashtable()
Return hashProperties
End Get
End Property

Public Sub AsyncProcessResponse(ByVal sinkStack _


As IServerResponseChannelSinkStack, ByVal state As Object, _
ByVal msg As IMessage, ByVal headers As ITransportHeaders, _
ByVal stream As Stream) _
Implements IServerChannelSink.AsyncProcessResponse
Console.WriteLine("Entering AsyncProcessResponse")
End Sub

Public Function GetResponseStream _


(ByVal sinkStack As IServerResponseChannelSinkStack, _
ByVal state As Object, ByVal msg As IMessage, _
ByVal headers As ITransportHeaders) As Stream _
Implements IServerChannelSink.GetResponseStream

Console.WriteLine("Entering GetResponseStream")
Return Nothing
End Function

535
The Complete Reference To Professional SOA with Visual Studio 2005

Public Function ProcessMessage _


(ByVal sinkStack As IServerChannelSinkStack, _
ByVal requestMsg As IMessage, _
ByVal requestHeaders As ITransportHeaders, _
ByVal requestStream As Stream, _
ByRef responseMsg As System.Runtime.Remoting.Messaging.IMessage, _
ByRef responseHeaders As ITransportHeaders, _
ByRef responseStream As Stream) _
As ServerProcessing Implements IServerChannelSink.ProcessMessage
Console.WriteLine("Entering ProcessMessage")
Dim spres As ServerProcessing = _next.ProcessMessage _
(sinkStack, requestMsg, requestHeaders, requestStream, _
responseMsg, responseHeaders, responseStream)
Return spres
End Function

Public ReadOnly Property NextChannelSink() As IServerChannelSink _


Implements IServerChannelSink.NextChannelSink
Get
Console.WriteLine("Getting NextChannelSink")
Return _next
End Get
End Property
End Class

In the above listing we have implemented the ServerSink which implements the IServerChannelSink and
IChannelSinkBase interface and inherits from the BaseChannelObjectWithProperties.

Table 13-5. IServerChannelSink methods and properties

Name Description

AsyncProcessResponse Requests Asynchronous processing of the response from a method call.

GetResponseStream Retrieve the stream from which the response message is serialized.

ProcessMessage Requests message processing from the current sink.

NextChannelSink Retrieve the next server channel sink in the server sink channel.

To understand the key method ProcessMessage() in the IServerChannelSink. We need to look back into the
process of how a message is transmitted using the proxy. The job of a proxy is to convert a method call invoked
on it into a message object. This message object, which implements the IMessage interface, is passed from the
client end to the server end by invoking ProcessMessage on message sink objects. Message sinks are chained
together in the sense that every message sink is responsible for calling ProcessMessage on the next message sink
after it has performed its work.
Below shows the parameters that ProcessMessage() requires:

536
The Complete Reference To Professional SOA with Visual Studio 2005

sinkStack - A stack of channel sinks that called the current sink.


requestMsg - The message that contains the request.
requestHeaders - Headers retrieved from the incoming message from the client.

requestStream – The request stream that needs to be processed and passed onto the deserialization sink.
responseMsg - This parameter is passed uninitialized. When this method returns, it contains an IMessage which holds
the response message.

responseHeaders - This parameter is passed uninitialized. When this method returns, it contains an ITransportHeaders
that holds the headers that are to be added to return message heading to the client.
responseStream - This parameter is passed uninitialized. When this method returns, it contains a Stream that is heading
back to the transport sink.

The Client
The client channel sink implementation is not too dissimilar to the server implementations

Listing 13-56. Shows the client implementation in C#

using System;
using System.Threading;
using System.Security;
using System.Security.Principal;
using System.Runtime.Remoting;

class Client
{
static void Main(string[] args)
{
RemotingConfiguration.Configure
(AppDomain.CurrentDomain.BaseDirectory +
"client.config", false);

ICalc c = (ICalc)
RemotingServices.Connect(typeof(ICalc),
"http://localhost:8081/calcsrv/calc");
Console.WriteLine("2 + 3 = {0}", c.Add(2, 3));
Console.WriteLine("4 + 5 = {0}", c.Add(4, 5));
Console.WriteLine("9 + 2 = {0}", c.Add(9, 2));
Console.ReadLine();
}
}

Listing 13-57. Shows the client implementation in Visual Basic 2005


Imports System
Imports System.Threading
Imports System.Security
Imports System.Security.Principal
Imports System.Runtime.Remoting

537
The Complete Reference To Professional SOA with Visual Studio 2005

Class Client

Shared Sub Main(ByVal args As String())


RemotingConfiguration.Configure("client.config", False)
Dim c As icalc.ICalc = _
CType(RemotingServices.Connect(GetType(icalc.ICalc), _
"http://localhost:8081/calcsrv/calc"), icalc.ICalc)

Console.WriteLine("2 + 3 = {0}", c.Add(2, 3))


Console.WriteLine("4 + 5 = {0}", c.Add(4, 5))
Console.WriteLine("9 + 2 = {0}", c.Add(9, 2))
Console.ReadLine()
End Sub

End Class

The above client loads the following configurations from the client.config file.
<configuration>
<system.runtime.remoting>
<application name="client">
<channels>
<channel ref="http" port="0">
<clientProviders>
<provider type="Sink.ClientSinkProvider, Sink"/>
<formatter ref="soap" />
</clientProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>

Notice that under the channel element, similar to the server implementation except we added the element
clientProviders. The clientProviders element contains two elements. The first element is the provider element.
This is where our sink is added by using the type attribute. The type attributes defines the class required and the
assembly where the class can be found. The second element under clientProviders is the SOAP formatter where
we ask the request to be encoded and transported using SOAP.
The client provider doesn't look much different than its server side counterpart.

Listing 13-58. Client sink provider using C#

public class ClientSinkProvider: IClientChannelSinkProvider


{
private IClientChannelSinkProvider next = null;

public ClientSinkProvider ()
{
Console.WriteLine("Entering client ClientSinkProvider");

538
The Complete Reference To Professional SOA with Visual Studio 2005

public ClientSinkProvider(IDictionary properties,


ICollection providerData)
{
Console.WriteLine
("Entering client ClientSinkProvider with parameter");
}

public IClientChannelSink CreateSink(IChannelSender channel,


string url, object remoteChannelData)
{
Console.WriteLine("Entering CreateSink");
return new ClientSink(next.CreateSink(channel,url,
remoteChannelData));
}

public IClientChannelSinkProvider Next


{
get {
Console.WriteLine("Getting Next Sink");
return next; }
set {
Console.WriteLine("Setting Next Sink");
next = value; }
}

Listing 13-59. Client sink provider using Visual Basic 2005

Public Class ClientSinkProvider


Implements IClientChannelSinkProvider
Private [_next] As IClientChannelSinkProvider = Nothing

Public Sub New()


Console.WriteLine("Entering client ClientSinkProvider")
End Sub

Public Sub New(ByVal properties As IDictionary, _


ByVal providerData As ICollection)
Console.WriteLine _
("Entering client ClientSinkProvider with parameter")
End Sub

Public Function CreateSink(ByVal channel As IChannelSender, _


ByVal url As String, ByVal remoteChannelData As Object) _
As IClientChannelSink Implements IClientChannelSinkProvider.CreateSink
Console.WriteLine("Entering CreateSink")

539
The Complete Reference To Professional SOA with Visual Studio 2005

Return New ClientSink([_next].CreateSink(channel, url, _


remoteChannelData))
End Function

Public Property [Next]() As IClientChannelSinkProvider _


Implements IClientChannelSinkProvider.Next
Get
Console.WriteLine("Getting Next Sink")
Return [_next]
End Get
Set(ByVal value As IClientChannelSinkProvider)
Console.WriteLine("Setting Next Sink")
[_next] = value
End Set
End Property
End Class

Figure 13-10. The IClientChannelSinkProvider interface

Table 13-6. In order to implement IClientChannelSinkProvider we need to implement the following methods and property.

Name Description

CreateSink Creates a sink chain.

Next Gets or sets the next sink provider in the channel sink provider chain.
There are two members of IClientChannelSinkProvider. The first is a method called CreateSink(). This is
where we can create our own custom channel sinks. CreateSink() creates the new channel sink (ClientSink).
CreateSink() is also responsible for making sure that the next sink and the one that it creates are linked together
this is how the chain on the client side gets built.
The second member of IServerChannelSinkProvider is the Next property. This property simply gets or sets
the next sink in the channel sink provider chain. Usually, this would be called before CreateSink() to set the next
provider in the chain so our CreateSink() method knows which provider to forward the CreateSink() call to.
Once the provider has been implemented we will need to implement the ClientSink. A client ChannelSink
must implement IMessageSink and IClientChannelSink. It also needs to inherit from
BaseChannelObjectWithProperties.
The listing below shows the ClientSink Implementations:

Listing 13-60. Shows the ClientSink implementation in C#

public class ClientSink : BaseChannelObjectWithProperties,


IMessageSink, IClientChannelSink
{
private IClientChannelSink _nextChnlSink;

540
The Complete Reference To Professional SOA with Visual Studio 2005

private IMessageSink _nextMsgSink;

public IMessageCtrl AsyncProcessMessage


(IMessage msg, IMessageSink replySink)
{
Console.WriteLine("Entering AsyncProcessMessage");
return _nextMsgSink.AsyncProcessMessage(msg, replySink);
}

public IMessage SyncProcessMessage(IMessage msg)


{
Console.WriteLine("Entering SyncProcessMessage");
return _nextMsgSink.SyncProcessMessage(msg);
}

public ClientSink(object next)


{
Console.WriteLine("Entering ClientSink");
_nextMsgSink = next as IMessageSink;
_nextChnlSink = next as IClientChannelSink;
}

public IMessageSink NextSink


{
get
{
Console.WriteLine("Getting NextSink MessageSink");
return _nextMsgSink;
}
}

public IClientChannelSink NextChannelSink


{
get
{
Console.WriteLine("Getting NextSink ChannelSink");
return _nextChnlSink;
}
}

public void AsyncProcessRequest


(IClientChannelSinkStack sinkStack, IMessage msg,
ITransportHeaders headers, Stream stream)
{
throw new Exception("Wrong sequence in config file");
}

public void AsyncProcessResponse


(IClientResponseChannelSinkStack sinkStack, object state,
ITransportHeaders headers, Stream stream)
{
throw new Exception("Wrong sequence in config file");

541
The Complete Reference To Professional SOA with Visual Studio 2005

public Stream GetRequestStream(IMessage msg,


ITransportHeaders headers)
{
throw new Exception("Wrong sequence in config file");
}

public void ProcessMessage(IMessage msg,


ITransportHeaders requestHeaders, Stream requestStream,
out ITransportHeaders responseHeaders, out Stream responseStream)
{
throw new Exception("Wrong sequence in config file");
}
}

Listing 13-61. Shows the ClientSink implementation in Visual Basic 2005

Public Class ClientSink


Inherits BaseChannelObjectWithProperties
Implements IMessageSink, IClientChannelSink
Private _nextChnlSink As IClientChannelSink
Private _nextMsgSink As IMessageSink

Public Overrides ReadOnly Property Properties() _


As System.Collections.IDictionary _
Implements IChannelSinkBase.Properties
Get
Dim hashProperties As Hashtable = New Hashtable()
Return hashProperties
End Get
End Property

Public Function AsyncProcessMessage(ByVal msg As IMessage, _


ByVal replySink As IMessageSink) As IMessageCtrl _
Implements IMessageSink.AsyncProcessMessage
Console.WriteLine("Entering AsyncProcessMessage")
Return _nextMsgSink.AsyncProcessMessage(msg, replySink)
End Function

Public Function SyncProcessMessage(ByVal msg As IMessage) _


As IMessage Implements IMessageSink.SyncProcessMessage
Console.WriteLine("Entering SyncProcessMessage")
Return _nextMsgSink.SyncProcessMessage(msg)
End Function

Public Sub New(ByVal [next] As Object)


Console.WriteLine("Entering ClientSink Constructor")
_nextMsgSink = CType([next], IMessageSink)
_nextChnlSink = CType([next], IClientChannelSink)

542
The Complete Reference To Professional SOA with Visual Studio 2005

End Sub

Public ReadOnly Property NextSink() As IMessageSink _


Implements IMessageSink.NextSink
Get
Console.WriteLine("Getting NextSink MessageSink")
Return _nextMsgSink
End Get
End Property

Public ReadOnly Property NextChannelSink() As IClientChannelSink _


Implements IClientChannelSink.NextChannelSink
Get
Console.WriteLine("Getting NextSink ChannelSink")
Return _nextChnlSink
End Get
End Property

Public Sub AsyncProcessRequest _


(ByVal sinkStack As IClientChannelSinkStack, ByVal msg As IMessage, _
ByVal headers As ITransportHeaders, ByVal stream As Stream) _
Implements IClientChannelSink.AsyncProcessRequest
Throw New Exception("Wrong sequence in config file")
End Sub

Public Sub AsyncProcessResponse _


(ByVal sinkStack As IClientResponseChannelSinkStack, _
ByVal state As Object, ByVal headers As ITransportHeaders, _
ByVal stream As Stream) _
Implements IClientChannelSink.AsyncProcessResponse
Throw New Exception("Wrong sequence in config file")
End Sub

Public Function GetRequestStream(ByVal msg As IMessage, _


ByVal headers As ITransportHeaders) As Stream _
Implements IClientChannelSink.GetRequestStream
Throw New Exception("Wrong sequence in config file")
End Function

Public Sub ProcessMessage(ByVal msg As IMessage, _


ByVal requestHeaders As ITransportHeaders, _
ByVal requestStream As Stream, _
ByRef responseHeaders As ITransportHeaders, _
ByRef responseStream As Stream) _
Implements IClientChannelSink.ProcessMessage
Throw New Exception("Wrong sequence in config file")
End Sub

543
The Complete Reference To Professional SOA with Visual Studio 2005

End Class

In the above listing we have implemented the ClientSink which implements the IClientChannelSink and
IMessageSink interface and inherits from the BaseChannelObjectWithProperties.

Table 13-7. IClientChannelSink methods and properties

Name Description

AsyncProcessRequest Requests for asynchronous processing of a method call on the current sink.
AsyncProcessResponseRequests for asynchronous processing of a response to a method call on the current
sink.
GetRequestStream Returns the request serialized stream.
ProcessMessage Request message processing for the current sink.
NextChannelSink
Retrieve the next channel sink in the client sink chain.

The client implementation of IClientChannelSink is quite similar to that of IServerChannelSink. In the client
implementation each channel sink implements a IClientChannelSink. The first channel sink on the client side
must implement IMessageSink. It typically implements IClientFormatterSink (which inherits from both
IMessageSink, IChannelSinkBase, and IClientChannelSink) and is called a formatter sink because it transforms the
incoming message into a stream (an IMessage object).
The channel sink chain processes any message that is sent to or from an application domain. At this point,
all we have is the message, but we are able to do anything we want with that message, and subsequent
processing will use the message that we return to the system after processing.
The figures below shows the execution result from execution the remotable Calculator application. We can
see the order of sink operation through the output of the result.

Figure 13-11. Shows the execution result on the Server side.

544
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 13-12. Shows the execution result from the Client sides

Summary
In this chapter we have explored .NET remoting. A possible alternative to XML Web services. .NET remoting is
a generic system for different applications to use to communication with one another through a number of
protocols such as HTTP, TCP and IPC.
In .NET remoting much like Web services the proxy within the remoting architecture abstracts a lot of the
complexities involved in cross boundry communication. When we create an instance of the remote object type in
the client application, .NET Remoting creates a proxy object and sends it to the client application. This proxy
object contains references to all the methods and properties of the server object. When we call a method that is
on that proxy object, the remoting system receives the call, routes it to the server process, invokes the server
object, and returns the return value to the client proxy, which returns the result to the client application.
There are two categories of objects in remoting: remotable and nonremotable. Nonremotable objects do not
provide the remoting system with a method to either copy them or use them in another application domain.
Therefore, we can access these objects only in their own application domain. Remotable objects can either be
accessed outside their application domain or context using a proxy or copied and passed outside their application
domain or context.
There’re two types of activation Server Activated Objects (SAOs) and Client-Activated Objects (CAOs).
Server-activated objects are similar to classic stateless Web Services. While client-activated objects can have
states. A client-activated object is instantiated on the server when the client creates it, and not with every method
call.
Lastly in this chapter we have also explored implementing channel sinks with remoting. The remoting
architecture supports a channel architecture which provides flexibility by employing a series of channel sink
objects linked together into a sink chain. Each channel sink in the chain has a clearly defined role in the
processing of the message. The channel sink performs certain functions on the message before forwarding the
message to the next channel sink in the chain.

545
The Complete Reference To Professional SOA with Visual Studio 2005

Chapter 14 Web Service


Security
The first step in implementing security in any application is to authenticate users. Implementing a robust
authentication mechanism is not easy. As a general consensus it is recommended that we use the authentication
services that the platform provides. In this case, the platform we are looking at consists of the Windows
operating system, IIS, and the .NET Framework and common language runtime. The key areas to focus are
authentication and authorization.
Authentication is the process of discovering and verifying the identity of a user by examining the user’s
credentials and then validating those credentials against some authentication authority. Currently, applications
use a variety of authentication mechanisms. With the .NET 2.0 we can now implement some of these
mechanisms with the .NET Framework Membership for user and role-based security.
Authorization is the process of determining whether a user is allowed to perform a requested action.
Authorization occurs after authentication and uses information about a user’s identity and roles to determine the
resources that a user can access. We can also use .NET 2.0’s Membership functionalities to develop role-based
security for authorization.

Windows Authentication
We can use Windows Integrated Security to authenticate our users. In a Web service this works in much the
same way as it does with web pages. The difference is that a web service is always executed by another
application, and not directly by the browser. For that reason, there’s no built-in way to prompt the user for a user
name and password. Instead, the application that is consuming the web service needs to supply the authentication
information. The application might read this information from a configuration file or database, or it might
prompt the user for this information before contacting the web service. The main downside to Windows
Integrated Security is that it does not work well across the Internet, but it is an exceptional intranet solution
because it can use the user’s logon information directly, without necessarily prompting the user to enter a
username and password. Also, the password is never sent across the wire in plaintext.
To require authentication, we need to enable Integrated Windows authentication for our client application
and disable anonymous access in the IIS management console. To allow or deny specific users access to our
service, we can use the ASP.NET’s Web.Config configuration system or set Access Control List (ACL) on the
configuration file itself, as shown in the following example:

Listing 14-1. Configuration within Web.Config

<configuration>

<system.web>
<authentication mode="Windows"/>
</system.web>

546
The Complete Reference To Professional SOA with Visual Studio 2005

<location path="secureservice.asmx">

<system.web>
<authorization>
<allow users="Administrator"/>
<allow users="DOMAIN\Bradley"/>
<deny roles="BUILTIN\Power Users"/>
</authorization>
</system.web>

</location>

</configuration>

The web service can also examine role membership. The example below will examine to see if the user has
been authenticated and also if the role of the user is Administrator.

Listing 14-2. Authenticated in C#

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
[WebMethod()]
public string TestWinAuthentication()
{
string strUserDetails = "";
if (!User.Identity.IsAuthenticated)
{
strUserDetails = "Not an authenticated user.";
}
else
{
strUserDetails = "Authenticated as: " +
User.Identity.Name + "; ";

if (!User.IsInRole("Administrator"))
{
strUserDetails += "User is NOT an Administrator";
}
else
{
strUserDetails += "User IS an Administrator";
}
}

return strUserDetails;
}

547
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 14-3. Authenticated in Visual Basic 2005

Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols

<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class Service
Inherits System.Web.Services.WebService

<WebMethod()> _
Public Function TestWinAuthentication() As String
Dim strUserDetails As String = ""
If Not User.Identity.IsAuthenticated Then
strUserDetails = "Not an authenticated user."
Else
strUserDetails = "Authenticated as: " + _
User.Identity.Name() + "; "
If Not User.IsInRole("Administrator") Then
strUserDetails += "User is NOT an Administrator"
Else
strUserDetails += "User IS an Administrator"
End If
End If
Return strUserDetails
End Function

End Class

The above Web service, which provides a single TestWinAuthentication() method. This method checks to
see if the user has been authenticated. If the user is authenticated, and if the role of the user belongs to the
Administrator group. If the user is authenticated, it returns the user name (which will be a string in the form
DomainName\UserName or Computer-Name\UserName).
Within the listing 14-2 and 14-3 the Web service class provides a User property of type
System.Security.Principal.IPrincipal, which we can use to retrieve information about the client user. We can
authorize access to our Web service using the Authorization section in the ASP.NET Web.Config file. The
User.IsAuthenticated property allows our code to determine if the current user has been authenticated. While the
User.IsInRole method allows our code to determine if the current user is a member of the specified role. This is
where we checked if the user is currently authenticated under the Administrator group.
This works well when we know that the client of the XML Web service will be running as a specific
Windows user. However what if we need a client running as one user, to act on behalf of another. Consider an
ASP.NET page that accesses a secure XML Web service that does not impersonate the client who accesses it. In
such a case, we need to programmatically set the username and password before connecting to the Web service.
To submit user credentials to this service, the client needs to modify the NetworkCredential property of the
proxy class. We have two options:

548
The Complete Reference To Professional SOA with Visual Studio 2005

* One way is to create a new NetworkCredential object and attach this to the NetworkCredential property of the
proxy object. When we create the NetworkCredential object, we will need to specify the user name and
password that we want to access the web service as. This approach works with all forms of Windows
authentication.
* The second way only works if the web service is using Integrated Windows authentication, we can
automatically submit the credentials of the current user by using the static DefaultCredentials property of the
CredentialCache class and applying that to the NetworkCredential property of the proxy object.

Both the CredentialCache and NetworkCredential classes are found in the System.Net namespace. The
NetworkCredential class is a base class that supplies credentials in password-based authentication schemes such
as basic, digest, NTLM, and Kerberos
The CredentialCache class is used when applications need to access multiple resources. These credential
information are stored in a CredentialCache instance. The GetCredentail method can be called to compare the
Uniform Resource Identifier (URI) and authenticate type provided with those stored in cache and return the first
set of credentials that match.
The DefaultCredentials property contains system credentials of the current security context. These represent
user name, password and the domain of the user currently logged in. For ASP.NET applications, the default
credentials are the user credentials of the logged-in user or the user being impersonated.
To enable custom windows authentication for the web service we need to first configure IIS to take our
principle information that web submit under NetworkCredential. To do this use the below steps:

Figure 14-1. Enabling Basic Authentication

Tip: Depending on the version of IIS used the screen may differ slightly.

1. We can open the IIS MMC console by going to the start menu -> then select run and type “inetmgr”.
2. In the left pane, expand the tree to find our virtual directory.

549
The Complete Reference To Professional SOA with Visual Studio 2005

3. In the right pane, right-click service.asmx, and choose Properties.


4. Select the File Security tab. Under Anonymous Access and Authentication Control in Windows XP or
Windows 2000, or Authentication and Access Control under Windows Server 2003, click Edit.
5. Disable anonymous access.
6. Disable integrated Windows authentication.
7. Enable basic authentication. (see figure 14-1.) A dialog window advising you that Basic Authentication
uses clear text when transported across the internet. Click Yes to continue.
8. Click OK to save these settings and exit the MMC console.

The following example uses basic authentication and illustrates a simple WebService (we’re still using the web service
in listing 14-2 and listing 14-3 to illustrate authentication):

Listing 14-4. Implementing NetworkCredential in C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;

namespace CSTestAuthenticationClient
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void buttonUnaunthenticate_Click(object sender, EventArgs e)


{
try
{
WSAuthenticate.Service wsAuthenticate =
new CSTestAuthenticationClient.WSAuthenticate.Service();
this.labelUnauthenticateResult.Text =
wsAuthenticate.TestWinAuthentication();
}
catch (Exception ex)
{
this.labelUnauthenticateResult.Text = ex.Message;
}
}

private void ButtonAuthenticate_Click(object sender, EventArgs e)


{
try

550
The Complete Reference To Professional SOA with Visual Studio 2005

{
WSAuthenticate.Service wsAuthenticate =
new CSTestAuthenticationClient.WSAuthenticate.Service();
// Supply some user credentials for the web service.
NetworkCredential credentials = new NetworkCredential(
this.TextBoxLogin.Text, this.TextBoxPassword.Text);
wsAuthenticate.Credentials = credentials;
this.LabelAuthenticResult.Text =
wsAuthenticate.TestWinAuthentication();
}
catch (Exception ex)
{
this.LabelAuthenticResult.Text = ex.Message;
}
}
}
}

Listing 14-5. Implementing NetworkCredential in Visual Basic 2005

Imports System.Net

Public Class Form1


Private Sub buttonUnaunthenticate_Click _
(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles buttonUnaunthenticate.Click
Try
Dim wsAuthenticate As WSAuthenticate.Service = _
New WSAuthenticate.Service
Me.labelUnauthenticateResult.Text = _
wsAuthenticate.TestWinAuthentication
Catch ex As Exception
Me.labelUnauthenticateResult.Text = ex.Message
End Try
End Sub

Private Sub ButtonAuthenticate_Click _


(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles ButtonAuthenticate.Click
Try
Dim wsAuthenticate As WSAuthenticate.Service = _
New WSAuthenticate.Service
Dim credentials As NetworkCredential = _
New NetworkCredential(Me.TextBoxLogin.Text, Me.TextBoxPassword.Text)
wsAuthenticate.Credentials = credentials
Me.LabelAuthenticResult.Text = wsAuthenticate.TestWinAuthentication
Catch ex As Exception
Me.LabelAuthenticResult.Text = ex.Message
End Try
End Sub
End Class

551
The Complete Reference To Professional SOA with Visual Studio 2005

The above code shows a windows application with two text boxes and two buttons, see figure 14-2. One
button performs an unauthenticated call, while the other submits the user name and password that have been
entered in the text boxes. In this example the unauthenticated call will fail since we have disabled anonymous
users in the section before. This means we must authenticate the client application the authenticated call will
always succeed as long as we submit the correct credentials that correspond to a valid user on our web server.
See figure 14-2.

Figure 14-2. Using unauthenticated and authenticated calls to the Web service.

Since NetworkCredential is found in System.Net. We need to first import the namespace for System.Net.
In order to specify the user that we would like to authenticate ourselves under we would first need to use
NetworkCredential where we pass in the login and password details of the user. This information is then attached
to the Credentials property generated by the Web service proxy. See listing 14-6 and listing 14-7.

Listing 14-6. Implementing NetworkCredential in C#

WSAuthenticate.Service wsAuthenticate =
new CSTestAuthenticationClient.WSAuthenticate.Service();
// Supply some user credentials for the web service.
NetworkCredential credentials = new NetworkCredential(
this.TextBoxLogin.Text, this.TextBoxPassword.Text);
wsAuthenticate.Credentials = credentials;

Listing 14-7. Implementing NetworkCredential in Visual Basic 2005

Dim wsAuthenticate As WSAuthenticate.Service = _


New WSAuthenticate.Service
Dim credentials As NetworkCredential = _
New NetworkCredential(Me.TextBoxLogin.Text, Me.TextBoxPassword.Text)
wsAuthenticate.Credentials = credentials
If we need to use the credentials of the currently logged-in account (if we’re using a windows application or
the account that the web application is running under) to access our web service. We can do so by checking the
Integrated Windows authentication checkbox for the web service in IIS. By using DefaultCredentials we can pass
in the default windows Principle information that we’re using to execute the application with to the Web service.

Listing 14-8. Using default credentials in Visaul C#

WSAuthenticate.Service wsAuthenticate =
new CSTestAuthenticationClient.WSAuthenticate.Service();

552
The Complete Reference To Professional SOA with Visual Studio 2005

wsAuthenticate.Credentials = CredentialCache.DefaultCredentials;
LabelAuthenticResult.Text = wsAuthenticate.TestWinAuthentication();

Listing 14-9. Using default credentials in Visual Basic 2005

Dim wsAuthenticate As WSAuthenticate.Service = _


New CSTestAuthenticationClient.WSAuthenticate.Service
wsAuthenticate.Credentials = CredentialCache.DefaultCredentials
LabelAuthenticResult.Text = wsAuthenticate.TestWinAuthentication

Managing Users by Using Membership


ASP.NET Membership gives us a built-in way to validate and store user credentials. ASP.NET Membership can
help us manage user authentication within a Web site. It is primarily used for ASP.NET web form applications,
but it is also very useful when we need to implement user and role management within Web service.
The ASP.NET membership model supports the following models:

* The ASP.NET membership supports creating new users and passwords.

* Membership can be used to support storing user information these include user names, passwords, and
supporting data in Microsoft SQL Server, Active Directory or other alternative data stores.
* Membership supports password management, this includes creating, changing, and resetting them. Depending
on membership options we choose, the membership system can also provide an automated password-reset
system that takes a user-supplied question and response.

* Membership supports the ability to expose a unique identifier for authenticated users. We can then use this
identifier within our own applications and integrate with the ASP.NET personalization and role-management
(authorization) system.
* Specifying a custom membership provider, which allows us to substitute our own code to manage membership
and maintain membership data in a custom data store.

ASP.NET membership has a set of classes and interfaces that we can use to create and manage users.
Through membership we can authenticate users based on the credentials that they supply. The table below lists
the membership classes and interfaces and also the functions that they provide.

Table 14-1. ASP.NET Membership Classes

Class/Interface Functions

Membership Creates a new user.


Provides general membership Deletes a user.
facilities.
Updates a user with new information.
Returns a list of users.
Finds a user by name or e-mail.
Validates (authenticates) a user.
Gets the number of users online.

553
The Complete Reference To Professional SOA with Visual Studio 2005

Searches for users by username or e-mail address.

MembershipUser Gets the password and password question.


Provides information about a specific Changes the password.
user.
Determines whether the user is online.
Determines whether the user is validated.
Returns the date for last activity, login, and password change.
Unlocks a user.

MembershipProvider The Membership provider defines the methods and properties that a
provider is required to implement.
Defines functionality for data
providers that can be used by the
membership system.

MembershipProviderCollection Returns a collection of all the available providers.

MembershipUserCollection Stores references to MembershipUser objects.

MembershipCreateStatus Provides a description for success or failure when creating a new


membership user.

MembershipCreateUserException Provides the exception thrown if a user cannot be created. The


MembershipCreateStatus enumeration value provides the reason for the
exception available through the StatusCode property.

MembershipPasswordFormat Defines the possible storage format available for password used by the
membership provider. These are Clear, Hashed, Encrypted.
We can perform use the ASP.NET Web Site Administration Tool, which includes a security wizard.
Configuring Membership is straight forward simply go to the Website menu -> ASP.NET Configuration. See
figure 14-3 (below).

554
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 14-3. Start Web Site Administration Tool

If we are using Membership on a machine with SQL Server 2005, we don’t need to configure Membership
provider to set up a database. We can launch the security setup wizard in Web Site Administration Tool to
configure security (see figure 14-4).

Figure 14-4. Web Site Administration Tool security setup wizard

By using the Security wizard we can start adding users to our Membership database immediately. This will
automatically create the database and store it under the App_Data folder when we create the first user, or if we
programmatically access the Membership database. As both options are implemented through the
SqlMembershipProvider.
If required we can also configure Membership to use our own database for user management.

Creating a Membership Database on SQL Server


Sometimes we want to store our database on a database server. Thus letting .NET create our database upon first
use is not what we want. We can use the aspnet_regsql.exe tool that ships with the .NET Framework this tool
will create the tables for us automatically. In the case of a custom provider, we have to prepare and configure the
data store used by the custom provider according to the custom provider’s documentation. We can use the

555
The Complete Reference To Professional SOA with Visual Studio 2005

aspnet_regsql.exe tool in two ways either through a wizard interface or through the command line. If we just
launch the tool without any parameters, it will launch with the wizard interface that will guide us through the
process of creating a database. See figure 14-5.

Figure 14-5. aspnet_regsql.exe wizard

The wizard provides us with the option of either creating the necessary database or removing the tables from
an existing database. See figure 14-6.

Figure 14-6. aspnet_regsql.exe wizard

556
The Complete Reference To Professional SOA with Visual Studio 2005

If we select to configure a new Sql Server or application services. See figure 14-6 (above). The setup
wizard will prompt us for connection properties to our database server. We will also be prompted to select the
database that we wanted to use to store our user membership information into. By selecting the <default> option
for the database, the setup wizard will create a database called aspnetdb and the relevant tables within it on the
server we have specified.

Figure 14-7. aspnet_regsql.exe wizard

We can use the aspnet_regsql.exe tool from the command line as well. The aspnet_regsql.exe tool is located
in C:\<WINDOWS>\Microsoft.NET\Framework\v2.0.50727. This tool is particularly useful when we need to
automate our application during setup. We can call this tool from the command line and automatically set up the
ASP.NET database tables required by our application. For example, to set up the Membership API database
tables, we can execute the following command:

aspnet_regsql.exe -E -S localhost -A mr
In this particular case we are registering an ASP.NET database table by using authentication with the current
windows credentials on the server called localhost and adding support for features for Membership and
RoleManagement.

Table 14-2. The following table shows the most commonly used command switches with the Aspnet_regsql.exe tool.

Option Description

-? Display all tool help options in the command window

-W This is the Wizard mode. This is the default if no command line arguments are specified.

-C connection string Define the connection string to the computer running SQL Server database will be
installed or already installed.

557
The Complete Reference To Professional SOA with Visual Studio 2005

-S server Define the name of the computer running SQL Server where the database will be installed.

-U login id The SQL Server user login id.

-P password The SQL Server password used to log in with.

-E Specifies the authentication using the current Windows credentials that the user is logged-
in as.

-d database Define the name of the database to create or modify. The default name is “aspnetdb”.

-sqlexportonly Create a SQL script file. We can customize this file to modify specific features.
filename

-A all|m|r|p|c|w Adds support for one or more features. The following identifiers are used for ASP.NET
features.
All - All features
m – Membership
r - Role management
p – Profile
w - Web events
Feature identifiers can be specified together or separately, as shown in the following
examples.
aspnet_regsql.exe -E -S localhost -A mp
aspnet_regsql.exe –E -S localhost -A m -A p

-R all|m|r|p|c|w Removes support for one or more features. The following identifiers are used for
ASP.NET features.
Feature identifiers can be specified together or separately, as shown in the following
examples.
aspnet_regsql.exe -E -S localhost -R mp
aspnet_regsql.exe -E -S localhost -R m -R p

-Q Runs the tool in quiet mode and does not confirm before removing a feature.

The aspnet_regsql.exe tool excutes sql scripts that can be found in


C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 directory. As shown in the figure 14-8 below. The
Install<function> script installs whilst the Uninstall<function> removes tables and databases.

558
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 14-8. SQL scripts for Membership

Going through any of the above steps will result in the automated creation of tables within the database. See
figure 14-9.

Figure 14-9. Database tables created

Configuring an Application to Use Membership


By default Membership will use SQL Server 2005 Express Edition however we can configure membership to
use other providers such as other SQL Server 2005 Editions. With the default configuration using SQL Server
2005 Express Edition installed, we don’t have to prepare the data store and configure a Membership provider,
because the ASP.NET runtime uses the file-based SQL Server 2005 provider and automatically creates the
database file for us within App_Data.
However, if we want to use our own SQL Server database, or to custom our Membership Provider, we will
need to configure the provider as well as the connection string to the Membership database appropriately. To do

559
The Complete Reference To Professional SOA with Visual Studio 2005

this we will need to either modify the web.config file directly or edit the configuration properties through the
ASP.NET Configuration Settings if the application is deployed on IIS.

Using Web.Config
We can specify the default membership provider using the defaultProvider attribute of the membership element.
The machine configuration specifies a SqlMembershipProvider instance named "AspNetSqlMembershipProvider"
this is identified as the default provider if we do not specify a default provider explicitly. The
"AspNetSqlMembershipProvider" connects to the aspnetdb database in the local SQL Server. To specify a custom
default provider we can use the below entries either into Web.config or Machine.config files.
We can also specify the default provider instance and options for that provider by configuring a provider in
the membership section. We can use the <providers> element to identify a provider to add to the collection of
providers available for the application. We can then identify this provider instance as the default provider. See
listing 14-10.

Listing 14-10. Configuration either within Web.config or Machine.config file

<connectionStrings>
<add name="ConnString"
connectionString="Database=YOURDBNAME;Data Source=localhost;
User Id=YOURUSERNAME;Password=YOURPWD" />
</connectionStrings>
<system.web>
<membership defaultProvider="MySqlMembershipProvider"
userIsOnlineTimeWindow="15">
<providers>
<clear />
<add
name="MySqlMembershipProvider"
type="Andri.Web.MySqlMembershipProvider"
connectionStringName="ConnString"
applicationName="YOURAPPNAME"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
requiresUniqueEmail="true"
passwordFormat="Hashed"
writeExceptionsToEventLog="true"
/>
</providers>
</membership>
</system.web>

In listing 14-10 we have specified a <providers> element under the membership defaultprovider element.
The <providers> element in the example defines the name for the provider, the type of the provider, the name of
the connection string to use, the password retrieval mode, password reset mode, password format, whether to
eanble question and answreing, whether to enable unique email support, whether to capture exceptions the
eventlog.
Membership has the following properties.

Table 14-3. Membership Properties.

560
The Complete Reference To Professional SOA with Visual Studio 2005

Name Description

ApplicationName Gets or sets the name of the application.

EnablePasswordReset Retrieve the value that signals whether the current membership
provider is configured to allow users to reset passwords.

EnablePasswordRetrieval Retrieve the value that signals whether the current membership
provider allow users to retrieve passwords.

HashAlgorithmType The identifier of the algorithm used to create hash passwords.

MaxInvalidPasswordAttempts Retrieve the max number of invalid passwords or password answer


attempts before the user is locked out.

MinRequiredNonAlphanumericCh Retrieve the minimum number of special charaters that must be used
aracters in a valid password

MinRequiredPasswordLength Retrieve the minimum length for a password.


PasswordAttemptWindow Retrieve the max number of invalid password or password answer
attempts in specified minutes before the user is locked out.
PasswordStrengthRegularExpressi Retrieve the regular expression used to evaluate a password.
on

Provider Retrieves a reference to the default membership provider for the


application.
Providers Retrieve a collection of membership providers that are available
within the ASP.NET application.
RequiresQuestionAndAnswer Retrieve the value indicating whether the membership provider
requires the user to answer a password question for password reset
and retrieval.

UserIsOnlineTimeWindow Retrieve the time window in number of minutes after the last activity
for a user to be online.

Using ASP.NET Configuration Settings


To configure provider details using IIS is straight forward simply open the properties of an Web application that we’re
interested to configure for. Then select ASP.NET tab -> Edit Configuration. See figure 14-10.

561
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 14-10. Edit conifuration properties for ASP.NET

This will display the ASP.NET Configuration Settings diaglog window. The ASP.NET Configuration
Settings diaglog window is quite useful. As it simplifies web.config configurations within a Web application
dramatically. We can configure providers by selecting the Authentication tab -> then select Manage Providers
under the Membership section.

Figure 14-11. ASP.NET Configuration Settings

562
The Complete Reference To Professional SOA with Visual Studio 2005

A provider settings diaglog is shown in figure 14-12. From here we can Add/Remove or modify existing
provider details.

Figure 14-12. ASP.NET Provder Settings diaglog

Implementing Membership
In the previous sections we have looked at setting up a database where user membership details can be stored. As
well as looking at configuring a provider to access the database within the application. Now we will look at how
we can use membership details to perform validations.
Membership comes with a series of public methods that allow us to perform validation and user
management. See table 14-4.

Table 14-4. Membership public methods

Name Description

CreateUser Adds a new user to a data store.

DeleteUser Removes a user from the database.

FindUsersByEmail Retrieves a collection of membership users where the e-mail address contains the specified e-mail
address to match.

FindUsersByName Retrieves a collection of membership matching user name.

563
The Complete Reference To Professional SOA with Visual Studio 2005

GeneratePassword Generates a random password of the specified length.

GetAllUsers Retrieve all users in the database

GetNumberOfUsersOnl Retrieve the number of users currently accessing the application.


ine

GetUser Retrieve the information for a membership user from the database.

GetUserNameByEmail Retrieve the user name by the user name’s email address.

UpdateUser Update the database with user information.

ValidateUser Validate that the user name and password are valid

By using the following configuration in Web.config or Machine.config see listing 14-11. We can access
Membership details within our application. See listing 14-12.

Listing 14-11. Configuration settings for membership

<?xml version="1.0"?>

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<appSettings/>
<connectionStrings>
<add name="ConnString" connectionString="Data Source=localhost;
Initial Catalog=aspnetdb;Integrated Security=True"/>
</connectionStrings>
<system.web>
<membership userIsOnlineTimeWindow="20">
<providers>
<add connectionStringName="ConnString"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
passwordFormat="Hashed" applicationName="MyApplication"
name="SqlProvider" type="System.Web.Security.SqlMembershipProvider"/>
</providers>
</membership>
<compilation debug="true"/></system.web>
</configuration>

Listing 14-12. Implementing Membership using C#

public void VerifyUsername()


{
MembershipUser user = Membership.GetUser(UsernameTextBox.Text, false);

if (user == null)
{

564
The Complete Reference To Professional SOA with Visual Studio 2005

Msg.Text = "The user name " + Server.HtmlEncode(UsernameTextBox.Text) + " was not found. Please check the value and reenter
your user name.";

QuestionLabel.Text = "";
QuestionLabel.Enabled = false;
AnswerTextBox.Enabled = false;
ResetPasswordButton.Enabled = false;
}
else
{
QuestionLabel.Text = user.PasswordQuestion;
QuestionLabel.Enabled = true;
AnswerTextBox.Enabled = true;
ResetPasswordButton.Enabled = true;
}
}

public void ResetPassword_OnClick(object sender, EventArgs args)


{
string newPassword = "";

try
{
newPassword = Membership.Provider.ResetPassword(UsernameTextBox.Text, AnswerTextBox.Text);
}
catch (NotSupportedException e)
{
Msg.Text = "An error has occurred resetting your password: " + e.Message + "." +
"Please check your values and try again.";
}
catch (MembershipPasswordException e)
{
Msg.Text = "Invalid password answer. Please reenter the answer and try again.";
return;
}
catch (System.Configuration.Provider.ProviderException e)
{
Msg.Text = "The specified user name does not exist. Please check your value and try again.";
}

if (newPassword != "")
{
Msg.Text = "Password reset. Your new password is: " + Server.HtmlEncode(newPassword);
}
else
{
Msg.Text = "Password reset failed. Please reenter your values and try again.";
}
}

Listing 14-13. Implementing Membership using Visual Basic 2005

565
The Complete Reference To Professional SOA with Visual Studio 2005

Public Sub VerifyUsername()

Dim user As MembershipUser = Membership.GetUser(UsernameTextBox.Text, False)

If user Is Nothing Then


Msg.Text = "The user name " & Server.HtmlEncode(UsernameTextBox.Text) & " was not found. Please check the value and reenter
your user name."

QuestionLabel.Text = ""
QuestionLabel.Enabled = False
AnswerTextBox.Enabled = False
ResetPasswordButton.Enabled = False
Else
QuestionLabel.Text = user.PasswordQuestion
QuestionLabel.Enabled = True
AnswerTextBox.Enabled = True
ResetPasswordButton.Enabled = True
End If

End Sub

Public Sub ResetPassword_OnClick(sender As Object, args As EventArgs)


Handles ResetPassword.Click

Dim newPassword As String = ""

Try
newPassword = Membership.Provider.ResetPassword(UsernameTextBox.Text, AnswerTextBox.Text)
Catch e As NotSupportedException
Msg.Text = "An error has occurred resetting your password: " & e.Message & "." & _
"Please check your values and try again."
Catch e As MembershipPasswordException
Msg.Text = "Invalid password answer. Please reenter the answer and try again."
Return
Catch e As System.Configuration.Provider.ProviderException
Msg.Text = "The specified user name does not exist. Please check your value and try again."
End Try

If newPassword <> "" Then


Msg.Text = "Password reset. Your new password is: " & Server.HtmlEncode(newPassword)
Else
Msg.Text = "Password reset failed. Please reenter your values and try again."
End If

End Sub
The listings 14-12 and 14-13 above demonstrates using membership to validate a user by username. By
calling the GetUser function under the VerifyUsername method. We can also reset a password by using the
Membership.Provider.ResetPassword function this will generate a new password for the user. Figure 13-13 below
demonstrates the UI for the application.

566
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 13-13. User interface

Custom Authentication and Authorization with SOAP


Headers
In Chapter 1 and Chapter 5 we had briefly explained SOAP header and its structure within SOAP messaging
protocol. Communicating with a Web service method using SOAP follows a standard format. Part of this format
is the data that is encoded in an XML document. The XML document consists of a root Envelope element, which
in turn consists of a required Body element and an optional Header element. The Body element comprises the
data specific to the message. The optional Header element can contain additional information not directly related
to the particular message. Each child element of the Header element is called a SOAP header.
The SOAP specification itself does not strictly define the content of a SOAP header. As such the SOAP
headers can be used to store data related to the message. An example of how a SOAP header can be used is to
store security detail information for the requesting application.

Defining SOAP Headers


Windows authentication works well for intranet scenarios, in which we are authenticating against a user in our
own domain. On the Internet, however, we would really want to perform custom authentication and
authorization, perhaps against a SQL database. In that case, we should pass custom credentials (such as the
username and password) to our service and let it handle the authentication and authorization itself.
A convenient way to deliver additional information with a request to a XML Web service is to include the
information into a SOAP header. To do this we need to define a class that derives from SOAPHeader in our
service and then declare a public field of our service as that type. This is then exposed in the public contract for
our service and made available to the client when the proxy is created from the wsdl.exe tool.
We will start by looking at an example of a Web service implementation security using SOAP header.

Listing 14-14. Web service that implements SOAPHeader using C#

567
The Complete Reference To Professional SOA with Visual Studio 2005

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
public AuthHeader sHeader;

[WebMethod(Description = "This method requires a custom soap" +


"header set by the caller")]
[SoapHeader("sHeader")]
public string SecureMethod()
{

if (sHeader == null)
return "ERROR: Please supply credentials";
else
return "USER: " + sHeader.Username;

}
}

// AuthHeader class extends from SoapHeader


public class AuthHeader : SoapHeader {
public string Username;
public string Password;
}

Listing 14-15. Web service that implements SOAPHeader using Visual Basic 2005

Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols

<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class Service
Inherits System.Web.Services.WebService

Public sHeader As AuthHeader

<WebMethod(Description:="This method requires a custom soap" + _


"header set by the caller")> _
<SoapHeader("sHeader")> _
Public Function SecureMethod() As String
If sHeader Is Nothing Then
Return "ERROR: Please supply credentials"
Else

568
The Complete Reference To Professional SOA with Visual Studio 2005

Return "USER: " + sHeader.Username


End If
End Function

End Class

Public Class AuthHeader


Inherits SoapHeader
Public Username As String
Public Password As String
End Class

To define a class representing a SOAP header. We need to first create a class deriving from the SoapHeader
class with a name matching the root element for the SOAP header.

Listing 14-16. Implementing SoapHeader using C#

public class AuthHeader : SoapHeader

Listing 14-17. Implementing SoapHeader using Visual Basic 2005

Public Class AuthHeader Inherits SoapHeader

Then we need to add public fields or properties, matching the names and their respective data types for each
element that we would want to be in the SOAP header.

Listing 14-18. SOAP Header

<soap:Header>
<AuthHeader xmlns="http://tempuri.org/">
<Username>JohnDoe</Username>
<Password>password</Password>
</AuthHeader>
</soap:Header>

For instance, given the need to create a SOAP header which contains Username and Password details in listing
14-18. We can define the class to represent the SOAP header. See listing 14-19.

Listing 14-19. SOAP Header Class using Visaul C#

public class AuthHeader : SoapHeader {


public string Username;
public string Password;
}

Listing 14-20. SOAP Header Class using Visual Basic 2005

Public Class AuthHeader


Inherits SoapHeader
Public Username As String
Public Password As String
End Class

569
The Complete Reference To Professional SOA with Visual Studio 2005

To process SOAP headers within a Web service. Add a public member to the class implementing the Web
service of the type representing the SOAP header.

Listing 14-21. Setting a public property matching the header type using C#

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
public AuthHeader sHeader;

Listing 14-22. Setting a public property matching the header type using Visual Basic 2005

<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class Service
Inherits System.Web.Services.WebService

Public sHeader As AuthHeader


To apply a SoapHeader attribute to each Web service method that intends to process the SOAP header. Set
the property of the SoapHeader attribute to the name of the member variable created in the previous step. See
listing 14-23.

Listing 14-23. Demonstrates setting SoapHeader Attribute using C#

[WebMethod(Description = "This method requires a custom soap" +


"header set by the caller")]
[SoapLogger]
[SoapHeader("sHeader")]
public string SecureMethod()

Listing 14-24. Demonstrates setting SoapHeader Attribute using Visual Basic 2005

<WebMethod(Description:="This method requires a custom soap" + _


"header set by the caller")> _
<SoapLogger>
<SoapHeader("sHeader")> _
Public Function SecureMethod() As String

Defining a SOAP Header Client


A XML Web services client can send and receive SOAP headers when communicating with a Web service. The
proxy class generated by using the wsdl.exe utility will contain information about the SOAP headers. The proxy
class generated will contain member variables representing the SOAP header details. The proxy class also has
definitions for the corresponding classes representing the SOAP header. For example, proxy classes generated
for the previous Web service will have a member variable of type AuthHeader and a definition for the
AuthHeader class.

Listing 14-25. Client application utilizing SOAP header using C#

using System;
using System.Collections.Generic;

570
The Complete Reference To Professional SOA with Visual Studio 2005

using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace CSSoapHeaderClient
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void ButtonAccess_Click(object sender, EventArgs e)


{
WSSoapHeaderService.Service wsHeaderService =
new WSSoapHeaderService.Service();

WSSoapHeaderService.AuthHeader authHeader =
new WSSoapHeaderService.AuthHeader();
authHeader.Username = "JohnDoe";
authHeader.Password = "password";
wsHeaderService.AuthHeaderValue = authHeader;
this.LabelResult.Text = wsHeaderService.SecureMethod();
}
}
}

Listing 14-26. Client application utilizing SOAP header using Visual Basic 2005

Public Class Form1

Private Sub ButtonAccess_Click(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles ButtonAccess.Click
Dim wsHeaderService As WSSoapHeaderService.Service = _
New WSSoapHeaderService.Service
Dim authHeader As WSSoapHeaderService.AuthHeader = _
New WSSoapHeaderService.AuthHeader
authHeader.Username = "JohnDoe"
authHeader.Password = "password"
wsHeaderService.AuthHeaderValue = authHeader
Me.LabelResult.Text = wsHeaderService.SecureMethod
End Sub
End Class

To process SOAP headers within a Web service client we need to first create a reference to the Web service.
Then we need to create a new instance of the class representing the SOAP header.

Listing 14-27. Creating a new instance of the SOAP header using C#

571
The Complete Reference To Professional SOA with Visual Studio 2005

WSSoapHeaderService.AuthHeader authHeader =
new WSSoapHeaderService.AuthHeader();

Listing 14-28. Creating a new instance of the SOAP header using Visual Basic 2005

Dim authHeader As WSSoapHeaderService.AuthHeader = _


New WSSoapHeaderService.AuthHeader

Then we need to populate the values for the SOAP header.

Listing 14-29. Defining values for the header using C#

authHeader.Username = "JohnDoe";
authHeader.Password = "password";

Listing 14-30. Defining values for the header using Visual Basic 2005

authHeader.Username = "JohnDoe"
authHeader.Password = "password"

Then we create a new instance of the proxy class.

Listing 14-31. Creating an instance of the Web service through our Proxy using C#

WSSoapHeaderService.Service wsHeaderService =
new WSSoapHeaderService.Service();

Listing 14-32. Creating an instance of the Web service through our Proxy using Visual Basic 2005

Dim wsHeaderService As WSSoapHeaderService.Service = _


New WSSoapHeaderService.Service
Then we need to assign the SOAP header object to the member variable of the proxy class representing the
SOAP header. So that when we do make a request the SOAP header along with its values will be sent to the Web
service.

Listing 14-33. Assign SOAP header to the Web service object using C#

wsHeaderService.AuthHeaderValue = authHeader;

Listing 14-34. Assign SOAP header to the Web service object using Visual Basic 2005

wsHeaderService.AuthHeaderValue = authHeader
Lastly we can call the method on the proxy class that communicates with the Web service method.

Listing 14-35. Calling the WebMethod on the service using C#

this.LabelResult.Text = wsHeaderService.SecureMethod();

Listing 14-36. Calling the WebMethod on the service using Visual Basic 2005

Me.LabelResult.Text = wsHeaderService.SecureMethod
Finally when we can call the WebMethod on the Web service. The SOAP header portion of the SOAP
request sent to the Web service will include the contents of the data stored in the SOAP header object. See the
SOAP Request and Response Below.

Listing 14-37. Demonstrates a Request from our SoapHeaderClient Application to the SoapHeaderService.

572
The Complete Reference To Professional SOA with Visual Studio 2005

<?xml version="1.0" encoding="utf-8"?>


<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Header>
<AuthHeader xmlns="http://tempuri.org/">
<Username>JohnDoe</Username>
<Password>password</Password>
</AuthHeader>
</soap:Header>
<soap:Body>
<SecureMethod xmlns="http://tempuri.org/" />
</soap:Body>
</soap:Envelope>

Listing 14-38. Demonstrates a Response from our SoapHeaderClient Application to the SoapHeaderService.

<?xml version="1.0" encoding="utf-8"?>


<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<SecureMethodResponse xmlns="http://tempuri.org/">
<SecureMethodResult>USER: JohnDoe</SecureMethodResult>
</SecureMethodResponse>
</soap:Body>
</soap:Envelope>

Implementing Token Authentication with SOAP


Headers
Security using Windows authentication is great for web services when we only have a small group of users such
as for an internal intranet setup who all have an existing account on the server. However, this method doesn’t
scale well for public web services.
A common solution is to write our own authentication system. In the security model that we will cover in
this section, users will call a specific web method in the web service to login, at which point they will supply
credentials (such as a user name and password combination). The login method will register the user session and
create a new, unique token.
By utilizing SOAP headers we can allow the users to reconnect to the web service by supplying the ticket to
every other method. A token system has a number of benefits. As with forms authentication, it is flexible. It also
optimizes performance and ensures scalability, because we can cache the ticket in memory. On subsequent
requests, we can verify the validity of the token rather easily than authenticating the user against the database.
Finally, it allows us to take advantage of SOAP headers, which make the ticket management and authorization
process transparent to the client.

573
The Complete Reference To Professional SOA with Visual Studio 2005

Implementing Security Token Service


With ASP.NET 2.0, it becomes possible to simplify custom authentication in a web service. Although it’s still up
to us to transfer the user credentials and keep track of who has logged in by issuing and verifying tickets, we can
use the .NET internal implementation of membership and role manager features to handle the authentication and
authorization. In the following sections, we will see how to create a custom ticket-based authentication system
that leverages membership and role management in this way.

Note: This implementation should not be used for high security Web service implementations. The reason is that the TokenID used in this
instance is a GUID and in this instance it poses as a vulnerability. The message is sent as a cleartext through the Web a user can easily
intercept the message and impersonate the GUID user. Please refer to Chapter 15 for Web Service Enhancement (WSE) where we
examine how to implement security using certificate. and Chapter 16 for security with Windows Communication Foundation (WCF).

Below is an implementation of our Web service implementing the Token security system.

Listing 14-39. SoapSecurityService, implementing token security in Web Service using C#

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Security;
using System.Security;
using SecurityLibrary;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : WebService
{
public SecurityLibrary.TokenHeader Token;
public Service () {

//Uncomment the following line if using designed components


//InitializeComponent();
}

[WebMethod]
[SoapHeader("Token", Direction = SoapHeaderDirection.Out)]
public string Login(string username, string password) {
if (Membership.ValidateUser(username, password))
{
SecurityLibrary.Token token =
new SecurityLibrary.Token(username);
Application[token.TokenID] = token;
Token = new SecurityLibrary.TokenHeader(token.TokenID);
return "logged in";
}
else
{
throw new SecurityException("Invalid credentials.");

574
The Complete Reference To Professional SOA with Visual Studio 2005

return "cannot login";


}

[WebMethod]
[SoapHeader("Token", Direction = SoapHeaderDirection.In,
Required=true)]
public string PerformSecuredOperation1()
{
AuthorizeUser(Token.TokenID, "Administrator");
//if user does not belong to a valid role then an security
//exception will be thrown before return is executed
return "Secure operation has been performed 1";
}

[WebMethod]
[SoapHeader("Token", Direction = SoapHeaderDirection.In,
Required = true)]
public string PerformSecuredOperation2()
{
AuthorizeUser(Token.TokenID, "Administrator");
return "Secure operation has been performed 2";
}

[WebMethod]
[SoapHeader("Token", Direction = SoapHeaderDirection.In,
Required = true)]
public string PerformSecuredOperation3()
{
AuthorizeUser(Token.TokenID, "Administrator");
return "Secure operation has been performed 3";
}

private SecurityLibrary.Token AuthorizeUser(string tokenID)


{
SecurityLibrary.Token token =
(SecurityLibrary.Token)Application[tokenID];
if (token != null)
{
return token;
}
else
{
throw new SecurityException("Invalid token.");
}
}

private SecurityLibrary.Token AuthorizeUser(string usertoken,


string role)
{
Token token = AuthorizeUser(usertoken);
if (Roles.IsUserInRole(token.UserName, role)) {

575
The Complete Reference To Professional SOA with Visual Studio 2005

return token;
} else {
throw new SecurityException("Insufficient permissions.");
}
}

[WebMethod]
public void CreateTestUser(string username, string password)
{
if (Membership.GetUser(username) != null)
{
//we can delete the user if it exists
throw new
SecurityException("User already exists in system!");
}

Membership.CreateUser(username, password);

string role = "Administrator";

if (!Roles.RoleExists(role))
{
Roles.CreateRole(role);
}
Roles.AddUsersToRole(new string[] { username }, role);
}
}

Listing 14-40. SoapSecurityService, implementing token security in Web Service using Visual Basic 2005

Imports System
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.Web.Security
Imports System.Security
Imports VBSecurityLibrary

<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
Public Class Service
Inherits System.Web.Services.WebService
Public SHToken As SecurityLibrary.TokenHeader

Public Sub New()


End Sub

<WebMethod()> _
<SoapHeader("SHToken", Direction:=SoapHeaderDirection.Out)> _
Public Function Login(ByVal username As String, _
ByVal password As String) As String
If Membership.ValidateUser(username, password) Then

576
The Complete Reference To Professional SOA with Visual Studio 2005

Dim token As SecurityLibrary.Token = _


New SecurityLibrary.Token(username)
Application(token.TokenID) = token
SHToken = _
New SecurityLibrary.TokenHeader(token.TokenID)
Return "logged in"
Else
Throw New SecurityException("Invalid credentials.")
End If
Return "cannot login"
End Function

<WebMethod()> _
<SoapHeader("SHToken", Direction:=SoapHeaderDirection.In)> _
Public Function PerformSecuredOperation1() As String
AuthorizeUser(SHToken.TokenID, "Administrator")
Return "Secure operation has been performed 1"
End Function

<WebMethod()> _
<SoapHeader("SHToken", Direction:=SoapHeaderDirection.In)> _
Public Function PerformSecuredOperation2() As String
AuthorizeUser(SHToken.TokenID, "Administrator")
Return "Secure operation has been performed 2"
End Function

<WebMethod()> _
<SoapHeader("SHToken", Direction:=SoapHeaderDirection.In)> _
Public Function PerformSecuredOperation3() As String
AuthorizeUser(SHToken.TokenID, "Administrator")
Return "Secure operation has been performed 3"
End Function

Private Function AuthorizeUser(ByVal tokenID As String) _


As SecurityLibrary.Token
Dim token As SecurityLibrary.Token = _
CType(Application(tokenID), SecurityLibrary.Token)
If Not (token Is Nothing) Then
Return token
Else
Throw New SecurityException("Invalid token.")
End If
End Function

Private Function AuthorizeUser(ByVal usertoken As String, _


ByVal role As String) As SecurityLibrary.Token
Dim token As SecurityLibrary.Token = AuthorizeUser(usertoken)
If Roles.IsUserInRole(token.UserName, role) Then
Return token
Else
Throw New SecurityException("Insufficient permissions.")
End If
End Function

577
The Complete Reference To Professional SOA with Visual Studio 2005

<WebMethod()> _
Public Sub CreateTestUser(ByVal username As String, _
ByVal password As String)
If Not (Membership.GetUser(username) Is Nothing) Then
Throw New SecurityException("User already exists in system!")
End If
Membership.CreateUser(username, password)
Dim role As String = "Administrator"
If Not Roles.RoleExists(role) Then
Roles.CreateRole(role)
End If
Roles.AddUsersToRole(New String() {username}, role)
End Sub
End Class

The listing 14-39 and listing 14-40 above shows the Web service implementation of our token security
system. We also need a security token library which is used to derive from SoapHeader and also store relevent
information relating to the token. See listing 14-41 (below)

Listing 14-41. Demonstrates SecurityLibrary using C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

namespace SecurityLibrary
{

public class TokenHeader : SoapHeader


{
public string TokenID;
public TokenHeader(string tokenID)
{
TokenID = tokenID;
}
public TokenHeader()
{}
}

public class Token


{
private string userName;
public string UserName
{
get { return userName; }
}
private string tokenID;
public string TokenID
{

578
The Complete Reference To Professional SOA with Visual Studio 2005

get { return tokenID; }


}
public Token(string userName)
{
this.userName = userName;
// Create the token GUID.
tokenID = Guid.NewGuid().ToString();
}
}
}

Listing 14-42. Demonstrates SecurityLibrary using Visual Basic 2005

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
Namespace SecurityLibrary

Public Class TokenHeader


Inherits SoapHeader
Public TokenID As String

Public Sub New(ByVal ltokenID As String)


TokenID = ltokenID
End Sub

Public Sub New()


End Sub
End Class

Public Class Token


Private luserName As String

Public ReadOnly Property UserName() As String


Get
Return luserName
End Get
End Property
Private ltokenID As String

Public ReadOnly Property TokenID() As String


Get
Return ltokenID
End Get
End Property

Public Sub New(ByVal userName As String)


Me.luserName = userName
ltokenID = Guid.NewGuid.ToString

579
The Complete Reference To Professional SOA with Visual Studio 2005

End Sub
End Class
End Namespace

To use our custom token security, the first step is to decide what user-specific information we want to keep in
our memory. We need to create a custom class that represents this information. This class can include
information about the user (name, e-mail address, and so on) and the user’s permissions. We’re also storing the
token id information along with the token so that the information can be retrieved at a later date. In our
implementation the Token ID is a randomly generated GUID to ensure that the tokens do not overlap. See listing
14-43.

Listing 14-43. Demonstrates token class used to store information relating to the token using C#

public class Token


{
private string userName;
public string UserName
{
get { return userName; }
}
private string tokenID;
public string TokenID
{
get { return tokenID; }
}
public Token(string userName)
{
this.userName = userName;
// Create the token GUID.
tokenID = Guid.NewGuid().ToString();
}
}

Listing 14-44. Demonstrates token class used to store information relating to the token using Visual Basic 2005

Public Class Token


Private luserName As String

Public ReadOnly Property UserName() As String


Get
Return luserName
End Get
End Property
Private ltokenID As String

Public ReadOnly Property TokenID() As String


Get
Return ltokenID
End Get
End Property

Public Sub New(ByVal userName As String)

580
The Complete Reference To Professional SOA with Visual Studio 2005

Me.luserName = userName
ltokenID = Guid.NewGuid.ToString
End Sub
End Class
Once we have the token class, we can store relevant information into it, we need to create a SOAP header.
The header will track the token for us. See listing 14-45. The TokenHeader in our implementation is derived
from SoapHeader. We will be serializing an instance of the TokenHeader object into the SOAPHeader. Thus all
the information it needs to contain is the TokenID information from which we can then later retrieve all the
relevant information back again.

Listing 14-45. Demonstrates TokenHeader class implementing SoapHeader using C#

public class TokenHeader : SoapHeader


{
public string TokenID;
public TokenHeader(string tokenID)
{
TokenID = tokenID;
}
public TokenHeader()
{}
}

Listing 14-46. Demonstrates TokenHeader class implementing SoapHeader using Visual Basic 2005

Public Class TokenHeader


Inherits SoapHeader
Public TokenID As String

Public Sub New(ByVal ltokenID As String)


TokenID = ltokenID
End Sub

Public Sub New()


End Sub
End Class
We must then add a member variable for the TicketHeader to our web service. See listing 14-47.

Listing 14-47. Demonstrates an instance of TokenHeader in our main Web service using C#

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
public SecurityLibrary.TokenHeader Token;

Listing 14-48. Demonstrates an instance of TokenHeader in our main Web service using Visual Basic 2005

<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
Public Class Service
Inherits System.Web.Services.WebService
Public SHToken As SecurityLibrary.TokenHeader

581
The Complete Reference To Professional SOA with Visual Studio 2005

The next step is to create a dedicated web method that logs the user in. User will need to submit user login
and password to this method. The method will then retrieve the user information, create the Token object, and
issue the token. In our example, a Login() web method checks the user credentials using the static
Membership.ValidateUser() method. A new token is constructed with the user information and stored in a user-
specific slot in the Application collection. At the same time, a new SOAP header is issued with the token so that
the user can access other methods with the token information. See listing 14-49.
Here’s the example for the Login() method:

Listing 14-49. Login() method using C#

[WebMethod]
[SoapHeader("Token", Direction = SoapHeaderDirection.Out)]
public string Login(string username, string password) {
if (Membership.ValidateUser(username, password))
{
SecurityLibrary.Token token =
new SecurityLibrary.Token(username);
Application[token.TokenID] = token;
Token = new SecurityLibrary.TokenHeader(token.TokenID);
return "logged in";
}
else
{
throw new SecurityException("Invalid credentials.");
}

return "cannot login";


}

Listing 14-50. Login() method using Visual Basic 2005

<WebMethod()> _
<SoapHeader("SHToken", Direction:=SoapHeaderDirection.Out)> _
Public Function Login(ByVal username As String, _
ByVal password As String) As String
If Membership.ValidateUser(username, password) Then
Dim token As SecurityLibrary.Token = _
New SecurityLibrary.Token(username)
Application(token.TokenID) = token
SHToken = _
New SecurityLibrary.TokenHeader(token.TokenID)
Return "logged in"
Else
Throw New SecurityException("Invalid credentials.")
End If
Return "cannot login"
End Function

In the listing 14-50 above, the Token object is stored in the Application collection, which is global to all users.
The tokens are stored using GUID that was generated to prevent them from overwriting each other. We can then
use the token id information that’s embedded in the Soap header to retrieve the user information. In this way, our
code can check the Application collection first, and if a matching Token is found, no database call is required.
But if the Token isn’t present, the information can still be retrieved from the database.

582
The Complete Reference To Professional SOA with Visual Studio 2005

The next step is to verify the credential information, the following AuthorizeUser() method checks for a
matching token and returns the Token if it’s found. Otherwise an exception is thrown, this exception will be
raised as a SOAP exception which will be returned to the client. See listing 14-51.

Listing 14-51. Login() function using C#

private SecurityLibrary.Token AuthorizeUser(string tokenID)


{
SecurityLibrary.Token token = (SecurityLibrary.Token)Application[tokenID];
if (token != null)
{
return token;
}
else
{
throw new SecurityException("Invalid token.");
}
}

Listing 14-52. Login() function using Visual Basic 2005

Private Function AuthorizeUser(ByVal tokenID As String) _


As SecurityLibrary.Token
Dim token As SecurityLibrary.Token = _
CType(Application(tokenID), SecurityLibrary.Token)
If Not (token Is Nothing) Then
Return token
Else
Throw New SecurityException("Invalid token.")
End If
End Function
We also have an additional AuthorizeUser() which verifies that the user belongs to a specific role. The
ASP.NET role management provider handles the role-checking work.

Listing 14-53. Verifying that the user belongs to a role using C#

private SecurityLibrary.Token AuthorizeUser(string usertoken, string role)


{
Token token = AuthorizeUser(usertoken);
if (Roles.IsUserInRole(token.UserName, role)) {
return token;
} else {
throw new SecurityException("Insufficient permissions.");
}
}

Listing 14-54. Verifying that the user belongs to a role using Visual Basic 2005

Private Function AuthorizeUser(ByVal usertoken As String, _


ByVal role As String) As SecurityLibrary.Token
Dim token As SecurityLibrary.Token = AuthorizeUser(usertoken)
If Roles.IsUserInRole(token.UserName, role) Then
Return token
Else

583
The Complete Reference To Professional SOA with Visual Studio 2005

Throw New SecurityException("Insufficient permissions.")


End If
End Function
Now we create a Web method to use the AuthorizeUser() method to check that the user has the required
permissions. Here’s an example that checks that the client is an administrator before allowing the client to
perform some functionality.

Listing 14-55. Demonstrates PerformSecuredOperation() using C#

[WebMethod]
[SoapHeader("Token", Direction = SoapHeaderDirection.In)]
public string PerformSecuredOperation1()
{
AuthorizeUser(Token.TokenID, "Administrator");
//if user does not belong to a valid role then an security
//exception will be thrown before return is executed
return "Secure operation has been performed 1";
}

Listing 14-56. Demonstrates PerformSecuredOperation() using Visual Basic 2005

<WebMethod()> _
<SoapHeader("SHToken", Direction:=SoapHeaderDirection.In)> _
Public Function PerformSecuredOperation1() As String
AuthorizeUser(SHToken.TokenID, "Administrator")
Return "Secure operation has been performed 1"
End Function
Inorder to create a user account to test the token authentication we have implemented CreateTestUser()
which uses Membership to create a new user for us. We can then use this user to login and then perform some
operation on our PerformSecuredOperation() function.

Listing 14-57. Demonstrates CreateTestUser() used to create an user of the role Administrator in C#

[WebMethod]
public void CreateTestUser(string username, string password)
{
if (Membership.GetUser(username) != null)
{
//we can delete the user if it exists
throw new SecurityException("User already exists in system!");
}

Membership.CreateUser(username, password);

string role = "Administrator";

if (!Roles.RoleExists(role))
{
Roles.CreateRole(role);
}
Roles.AddUsersToRole(new string[] { username }, role);
}

Listing 14-58. Demonstrates CreateTestUser() used to create an user of the role Administrator in Visual Basic 2005

584
The Complete Reference To Professional SOA with Visual Studio 2005

<WebMethod()> _
Public Sub CreateTestUser(ByVal username As String, _
ByVal password As String)
If Not (Membership.GetUser(username) Is Nothing) Then
Throw New SecurityException("User already exists in system!")
End If
Membership.CreateUser(username, password)
Dim role As String = "Administrator"
If Not Roles.RoleExists(role) Then
Roles.CreateRole(role)
End If
Roles.AddUsersToRole(New String() {username}, role)
End Sub
In order to enable the Membership functionalities we also need to make a few entries into our web.config
file.

Listing 14-59. ConnectionString

<connectionStrings>
<add
name="LocalSqlServer1"
connectionString="data source=.\SQLEXPRESS;Integrated
Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;
User Instance=true"
providerName="System.Data.SqlClient"
/>
</connectionStrings>

We need to tell the Membership management where our database is located. In our case it is a default
database created Web Site Administration which is used to manage users.

Listing 14-60. Membership configuration.

<membership>
<providers>
<remove name="AspNetSqlMembershipProvider"/>
<add name="AspNetSqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider, System.Web,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
connectionStringName="LocalSqlServer1"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="false"
applicationName="/"
requiresUniqueEmail="false"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="5"
minRequiredPasswordLength="1"
minRequiredNonalphanumericCharacters="0"
passwordAttemptWindow="10"
passwordStrengthRegularExpression="" />
</providers>
</membership>

585
The Complete Reference To Professional SOA with Visual Studio 2005

In the configuration above we define the properties of the Membership management. We also define password
policies and where the information will be stored.
The last thing we need to define is:
<roleManager enabled="true" />
This will allow ASP.NET Membership to manage roles for us. As in the example we need to assign users to
the Administrator role that we had defined. Thus roleManager must be enabled.

Implement Client for Token Security


Now we can create a client application that will utilize the SOAP token Web service system we had
implemented in the earlier section.

Figure 14-14. Client application using token security to authenticate

In this case, a Windows application provides two text boxes for the user to supply a user name and password
(see figure 14-14). This information is passed to the Login() method, and then the PerformSecuredOperation()
method is called to retrieve the data. This method succeeds for a user with the Administrator role but fails for
everyone else.

Listing 14-61. Demonstrates the token application using C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace CSTokenAuthentication
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private WSTokenService.Service wsts =


new CSTokenAuthentication.WSTokenService.Service();

586
The Complete Reference To Professional SOA with Visual Studio 2005

private void ButtonAccess_Click(object sender, EventArgs e)


{
try
{
wsts.Login(this.textBoxLogin.Text, this.textBoxPass.Text);

this.labelResult.Text = wsts.PerformSecuredOperation1() +
Environment.NewLine + wsts.PerformSecuredOperation2() +
Environment.NewLine + wsts.PerformSecuredOperation3();
} catch (Exception ex) {
this.labelResult.Text = ex.Message;
}
}

private void buttonCreateUser_Click(object sender, EventArgs e)


{
wsts.CreateTestUser(this.textBoxLogin.Text, this.textBoxPass.Text);
}
}
}

Listing 14-62. Demonstrates the token application using Visual Basic 2005

Public Class Form1


Private wsts As WSTokenService.Service = _
New WSTokenService.Service

Private Sub ButtonAccess_Click _


(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles button1.Click
Try
wsts.Login(Me.textBoxLogin.Text, Me.textBoxPass.Text)
Me.labelResult.Text = _
wsts.PerformSecuredOperation1(+Environment.NewLine + _
wsts.PerformSecuredOperation2 + Environment.NewLine + _
wsts.PerformSecuredOperation3)
Catch ex As Exception
Me.labelResult.Text = ex.Message
End Try
End Sub

Private Sub buttonCreateUser_Click _


(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles buttonCreateUser.Click
wsts.CreateTestUser(Me.textBoxLogin.Text, Me.textBoxPass.Text)
End Sub
End Class

In Visual Studio 2005 when we add a Web reference Visual Studio 2005 will automatically generate the
proxy class for us. The proxy class will help us manage the token so as a client we don’t need to be aware of the
header that’s actually being transported to and from the requests. As we can see in the SOAP exchange below.

587
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 14-63. Demonstrates the Login() SOAP request

<?xml version="1.0" encoding="utf-8"?>


<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<Login xmlns="http://tempuri.org/">
<username>JohnDoe</username>
<password>password</password>
</Login>
</soap:Body>
</soap:Envelope>

In the above listing we are making a SOAP request to the Login() method within the security Token Web
service.

Listing 14-64. Demonstrates Login() response with TokenHeader information

<?xml version="1.0" encoding="utf-8"?>


<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Header>
<TokenHeader xmlns="http://tempuri.org/">
<TokenID>5e3f718f-8e92-4305-8e83-7a56c5eced25</TokenID>
</TokenHeader>
</soap:Header>
<soap:Body>
<LoginResponse xmlns="http://tempuri.org/">
<LoginResult>logged in</LoginResult>
</LoginResponse>
</soap:Body>
</soap:Envelope>

In the listing above we can see the response from the login function contains the SOAP header for
TokenHeader. This TokenHeader contains TokenID. The client application that requested the Login() method
does not have to implement anything to handle this. This is handled by our proxy to the Web service.

Listing 14-65. Shows PerformSecuredOperation1() SOAP request with TokenHeader

<?xml version="1.0" encoding="utf-8"?>


<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Header>
<TokenHeader xmlns="http://tempuri.org/">
<TokenID>5e3f718f-8e92-4305-8e83-7a56c5eced25</TokenID>
</TokenHeader>
</soap:Header>
<soap:Body>
<PerformSecuredOperation1 xmlns="http://tempuri.org/" />

588
The Complete Reference To Professional SOA with Visual Studio 2005

</soap:Body>
</soap:Envelope>

In the listing above we are making a request to the PerformSecuredOperation1() operation. However notice
that the request now contains SOAP header information. Which contains the TokenHeader as well as the TokenID
that was issued by our Web service.

Listing 14-66. PerformSecuredOperation1() SOAP response

<?xml version="1.0" encoding="utf-8"?>


<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<PerformSecuredOperation1Response xmlns="http://tempuri.org/">
<PerformSecuredOperation1Result>Secure operation has been
performed 1</PerformSecuredOperation1Result>
</PerformSecuredOperation1Response>
</soap:Body>
</soap:Envelope>

The SOAP response above shows the response from PerformSecuredOperation1().

Listing 14-67. PerformSecuredOperation2() SOAP request

<?xml version="1.0" encoding="utf-8"?>


<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Header>
<TokenHeader xmlns="http://tempuri.org/">
<TokenID>5e3f718f-8e92-4305-8e83-7a56c5eced25</TokenID>
</TokenHeader>
</soap:Header>
<soap:Body>
<PerformSecuredOperation2 xmlns="http://tempuri.org/" />
</soap:Body>
</soap:Envelope>

In the listing above we are making a request to the PerformSecuredOperation2() operation. Notice that the
request also contains SOAP header information. Which contains the TokenHeader as well as the TokenID that
was issued by our Web service even though we did not have to perform anything special again all of it is handled
by the proxy.

Listing 14-68. PerformSecuredOperation2() SOAP response

<?xml version="1.0" encoding="utf-8"?>


<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<PerformSecuredOperation2Response xmlns="http://tempuri.org/">
<PerformSecuredOperation2Result>Secure operation has been

589
The Complete Reference To Professional SOA with Visual Studio 2005

performed 2</PerformSecuredOperation2Result>
</PerformSecuredOperation2Response>
</soap:Body>
</soap:Envelope>

The SOAP response above shows the response from PerformSecuredOperation2().

Listing 14-69. PerformSecuredOperation2() SOAP request

<?xml version="1.0" encoding="utf-8"?>


<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Header>
<TokenHeader xmlns="http://tempuri.org/">
<TokenID>5e3f718f-8e92-4305-8e83-7a56c5eced25</TokenID>
</TokenHeader>
</soap:Header>
<soap:Body>
<PerformSecuredOperation3 xmlns="http://tempuri.org/" />
</soap:Body>
</soap:Envelope>

In the listing above we are making a request to the PerformSecuredOperation3() operation. Notice that the
request also contains SOAP header information.

Listing 14-70. PerformSecuredOperation1() SOAP response

<?xml version="1.0" encoding="utf-8"?>


<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<PerformSecuredOperation3Response xmlns="http://tempuri.org/">
<PerformSecuredOperation3Result>Secure operation has
been performed 3</PerformSecuredOperation3Result>
</PerformSecuredOperation3Response>
</soap:Body>
</soap:Envelope>

The SOAP response above shows the response from PerformSecuredOperation3().


By using SOAP headers to implement tokens the client application does not need to be aware of the token
management. That’s because the Login() method issues the token, and in turn it is managed by the proxy class.
As long as the client uses the same instance of the proxy class, the same ticket value will be submitted
automatically, and the user will be authenticated.

Summary
In this chapter, we have covered:

590
The Complete Reference To Professional SOA with Visual Studio 2005

Windows Authentication - We can use windows authentication to authenticate our users. This is particularly
useful in an intranet environment. In Web service this works in much the same way as it does with web pages.
The difference is that a web service is always executed by another application, and not directly by the browser.
Managing Users by Using Membership - ASP.NET Membership provides us with a built-in way to validate and
store user credentials. ASP.NET Membership is particularly useful when implementing user and role
management within Web services.
Custom Authentication and Authorization with SOAP Headers – The optional Header element
can contain additional information not directly related to the particular message. Each child
element of the Header element is called a SOAP header. We thus use SOAP header to store
security credential details. This is particularly useful as it saves the client from having to
authenticate themselves upon each WebMethod call.

591
The Complete Reference To Professional SOA with Visual Studio 2005

Chapter 15 Web Services


Enhancements 3.0
Web services are evolving rapidly. This is due to a consensus in companies such as Microsoft, IBM, BEA
Systems, and VeriSign, working together with organizations such as the Organization for the Advancement of
Structured Information Standards (OASIS) to formulate new specifications to address rising issues. These
specifications called the Web Service Specifications also refered to as WS-* specifications. These are based on
XML, SOAP, and WSDL extensibility models. Together, these specifications define a set of composable
features to make Web services secure, reliable and interoperable. All of these specifications are composable
which means we can mix and choose the only ones that we need. We do not have to implement any particular
standards but as the industry as a whole slowly adopts these standards we will also need to adopt them in order to
interoperate with other Web services that are governed by the specifications.
The WS-Specifications provide an important framework for Web services to interoperate securely.
Microsoft provides a set of tools for .NET called the Web Services Enhancements (WSE). WSE includes
managed APIs for implementing selected WS-specifications in a composable manner.
The latest WSE release is v3.0. WSE 3 greatly simplifies the development and deployment of secure Web
services using .NET. It allows developers and administrators to apply security policies to the Web services
running on .NET Framework 2.0. Using WSE 3.0 we can sign, encrypt SOAP messages using Kerberos tickets,
X.509 certificates and other custom binary and XML based security tokens. Along with username/password
credentials which can be used for authentication purposes. WSE also provides an enhanced security model which
provides a foundation for policy based security for Web services. It also supports the ability to establish trust
issue services for retrieval and validation of security tokens. It also simplifies the ability to establish more
efficient long running secure communication via secure conversations.
In this chapter, we will be focusing to explore how to develop .NET Web services and client applications by
leveraging WSE functionalities to implement secure Web services. We will explore using WSE 3.0 to provide
supports for secure communication by learning about WSE authentication as well as implementing custom token
management. We will also be looking at implementing SOAP message signing and encryption using X.509
certificates through WS-Security specification. Lastly we will learn to implement binary file transfer through the
use of Message Transmission Optimization Mechanism (MTOM).

Web Services Enhancements Overview


The engine that drives Web Services Enhancements is a separate WSE runtime that’s integrated with the .NET
Framework and can be hosted by ASP.NET (see figure 15-1 below).

592
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 15-1. Demonstrates the WSE layer

This runtime essentially intercepts SOAP request and response messages and invokes a set of filters that
either serialize specification compliant SOAP response message headers (in the case of outbound response
messages) or interpret specification compliant request message headers (in the case of inbound request
messages). These filters can handle SOAP messages transported over both HTTP or TCP.
The filters and the WSE runtime are implemented by the Microsoft.Web.Services assembly
(Microsoft.Web.Services.dll), and WSE provides a set of APIs that allows us to programmatically determine the
behavior of these inputs and output filters in order to implement the desired functionalities described by the
various specifications.
The WSE runtime can also be installed at a Web service client computer and used by client applications that
consume Web services that require the additional support for advanced Web services headers. As on the Web
service provider, the WSE runtime on the client passes SOAP messages through a set of filters that either
serialize supported headers for outgoing messages or abstract the supported headers from incoming messages
into proxy objects that the client application consumes.

WS-Security
The Web service security (WS-Security) specification defines SOAP extensions for message integrity, and
message confidentiality. The WS-Security specification provides message level security end-to-end security
support rather than point-to-point security such as those provided by SSL/HTTPS. WS-Security defines a
method of implementing Web service security using SOAP. It defines rules for authentication, signatures, and
encryption mechanisms.
WS-Security also defines a general mechanism for associating security tokens with messages. The token
support itself is extensible and is not restricted to a specific type of security token. Typically a client will be
required to provide proof of identity and or a business certificate. Additionally, WS-Security describes how to
encode binary security tokens such as X.509 certificates and Kerberos ticket as well as how to include opaque
encrypted keys. We can also extend security mechanisms that can be used to further describe the characteristics
of the credentials.

Security Tokens
WS-Security uses the concept of soft security tokens, which are logical entities generated by the system to
ensure authentication. These refers to Username/Password, Kerberos tickets, or X.509 certificates. A developer
can also build custom binary security tokens if necessary and use them without breaking the specification. For
this purpose, WSE provides the BinarySecurityToken class. Classes that we build that derive from this will be
compatible with the WS-Security soft token specification.

593
The Complete Reference To Professional SOA with Visual Studio 2005

To add a security token to an outbound message using WSE, all that we need to do is to programmatically
define the token using an instance of an appropriate class that overrides the SecurityToken base class then add
this object to the SoapContext of the outbound message. When received by a WSE-enabled application, the WSE
runtime generates security token objects based on contents of the Security header in the incoming message.
These tokens, which belong to the SoapContext object for the incoming message, are then presented to the
appropriate security token manager for authentication and authorization. These security token objects are
accessible to our application for as long as the SoapContext object exists.

Installing Web Services Enhancements


Web Services Enhancements 3.0 is an addon onto Visual Studio 2005. You can either download WSE from
Microsoft or you can find it on the accompanied source CD. Installing WSE is fairly straight forward. Simply
run the install wizard for WSE 3.0.

Figure 15-2. WSE 3.0 install wizard

During setup, we will be prompted to select from several setup type options, including options to install only
the runtime files, runtime plus tools, documentation, Visual Studio tools, and a custom install option. These
setup options help to differentiate between the different types of WSE components that should be installed. We
can also specify Custom option, which allow us to select the various components manually. Most developers
should choose the Visual Studio® Developer option, which installs the WSE 3.0 runtime files, documentation
and samples, standalone tools, and the Visual Studio 2005 tools (see figure 15-13 below).

594
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 15-3. WSE setup types

WSE 3.0 contains several QuickStart sample applications and documentation that demonstrates how to use
various classes in the WSE assembly. But the engine of WSE 3.0 is a single assembly called
Microsoft.Web.Services3.dll, which is installed by default under C:\Program Files\Microsoft WSE\v3.0. In
addition, this assembly gets automatically registered in the Global Assembly Cache (GAC).

Using Web Services Enhancements


In order to use the WSE assembly in our Web services projects, we will need to register it as a SOAP extension
within either the machine.config or web.config configuration files. If we update the machine.config file, then the
assembly will automatically be registered for all future Web services projects. Otherwise, we will need to update
the web.config files for each new project individually.
Fortunately, Microsoft also provides the WSE Settings tool that integrates with Visual Studio 2005 and can
be used to automatically make the needed modifications to the Web.config file. With the WSE Settings tool
installed, it is simple to enable any Web service or client that consumes such a Web service to use the WSE
runtime. To configure WSE settings for a Visual Studio 2005 application, simply right-click on the project that
requires WSE in the Solution Explorer window in Visual Studio 2005 and click WSE Settings. This displays the
WSE Settings tool (see figure 15-4 below).

595
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 15-4. The WSE settings tool

Enabling WSE for an ASP.NET Web service is quite simple with this tool. All that we need to do is select
WSE Settings 3.0 from the context menu in solution explorer for our project. Then select both check boxes on
the General tab. To enable WSE for an application consuming a WSE-enabled Web service, we need only select
the “Enable this project for Web Services Enhancements” check box see figure 15-5 (below). By enabling this
option the necessary assembly reference will be added to the project, and the SOAP extensions configurations
will be automatically entered into our Web.config file.

596
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 15-5. Enabling WSE for a project

Listing 15-1. Demonstrates the Web.config file after WSE has been enabled.

<?xml version="1.0"?>
<configuration>
<configSections>
<section name="microsoft.web.services3"
type=
"Microsoft.Web.Services3.Configuration.WebServicesConfiguration,
Microsoft.Web.Services3, Version=3.0.0.0,Culture=neutral,
PublicKeyToken=31bf3856ad364e35"/>
</configSections>
<system.web>
<webServices>
<soapExtensionImporterTypes>
<add
type="Microsoft.Web.Services3.Description.WseExtensionImporter,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35"/>
</soapExtensionImporterTypes>
<soapServerProtocolFactory
type="Microsoft.Web.Services3.WseProtocolFactory,
Microsoft.Web.Services3, Version=3.0.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</webServices>
<compilation debug="true">
<assemblies>
<add assembly="Microsoft.Web.Services3,
Version=3.0.0.0, Culture=neutral,

597
The Complete Reference To Professional SOA with Visual Studio 2005

PublicKeyToken=31BF3856AD364E35"/>
</assemblies>
</compilation>
</system.web>
</configuration>

The rest of the tabs in this tool allow us to configure various components of WSE that correspond to the
specifications that the Web service needs to use.

WSE Communication Process


There are several stages involved in securing communication between the client and the Web service. Messages
are authenticated to prevent tampering or messages spoofing. The communication channel is secured to prevent
eavesdropping and to ensure confidentiality. The steps below outline the WSE stages to secure client and Web
service communication.

Figure 15-6. Shows the WSE stages in communication

Requesting Process
The communication process starts with the client generating a Web service request. This process involves three
steps: initializing the UsernameToken, establishing message integrity, encrypting sensitive data in the message,
(see figure 15-6 above).

598
The Complete Reference To Professional SOA with Visual Studio 2005

During initialization the UsernameToken implements a token object with a SendPlainText password option
to send the password over the network as plaintext. This is often required because directory services such as
Active Directory require plaintext passwords for credential validation. SendPlainText is the default option of the
UsernameTokenManager which is similar to basic authentication over HTTP. When sending clear text password
we should always secure the communication channel between the client and the server this can be achieved using
Secure Socket Layer (SSL). To add security we can also add message level encryption by using WSE 3.0.
The next stage is establishing message integrity, at this stage data origin authentication is established
between the client and the service, either implicitly or explicitly, depending upon one of the two following
methods that we can choose to secure messages between the client and the service:

The usernameOverTransportSecurity turnkey assertion with HTTPS.


The usernameForCertificateSecurity turnkey assertion.

To ensure security when we use server certificates with HTTPS using the turnkey assertion help to provide
data integrity and data confidentiality at the transport level. If we require message origin authentication from the
client, we would need to install and use a certificate for the client.
Using usernameForCertificateSecurity turnkey assertion WSE 3.0 can provide support for data confidentiality
and message origin authentication. This is achieved when a derived key token is included in the request message
this message is then encrypted with a wrapped symmetric encryption key. Then using the service’s X.509
certificate public key the wrapped symmetric key is encrypted. This derived key token is referred to as an
encrypted key. This key is accompanied with a valid UsernameToken, message origin authentication is provided
when the client uses the derived key token to sign the message.
Encrypting sensitive data in the message, at this stage we should encrypt the message from the client to the
service to ensure that only the service, as the intended recipient of the message, can process it. The method that
we choose to secure the communication channel between the client and the service should also provide data
confidentiality.

Response Process
The response process is a little more complicated in WSE as the service needs to authenticate the client and
return a response. This part of the process has five steps: decrypting the request message, verifying message
integrity, validating the password, establishing the response integrity, encrypting the response.

* The first of these steps is the decryption of the request message. It is at this stage that we choose whether to
secure the communication channel between the client and the service and to determine how to decrypt the
request message. There are two forms of decryption at this stage if transport level encryption had been enabled
using the usernameOverTransportSecurity assertion which relies on SSL to decrypt the message. WSE 3.0 also
provides support for certificate based decryption using the usernameForCertificateSecurity assertion which
decrypts the derived key token that had been encrypted using the wrapped symmetric key. Then using the
derived key token to decrypt the message signature, the UsernameToken, and the rest of the message that the
client had encrypted.
* The second step is to verify the message integrity to ensure that the message had not been altered. The option
that we had selected in step one on how to secure communication between the client and the service determines
how the message integrity will be verified. WSE uses usernameOverTransportSecurity assertion relying on
SSL to verify message integrity. Otherwise if a client certificate is provided then the certificate can be used to
verify the message origin authentication. This is achieved with WSE 3.0 using the
usernameForCertificateSecurity assertion verifies the message integrity using the derived key token that was
sent by the client and was decrypted in step one.

599
The Complete Reference To Professional SOA with Visual Studio 2005

* The third step is to validate the password. After the service receives the message using WSE 3.0 the
UsernameTokenManager class validates the information in the UsernameToken using the AuthenticateToken
method. The UsernameTokenManager can be used to validate credentials against an Active Directory domain
controller. If a directory service or a database is used then we can extend the implementation of the
UsernameTokenManager class.

* The fourth step is to establish response integrity. At this stage the method used to establish the response
message’s integrity depends upon whether communication is secured at the message layer using WSE 3.0 or at
the transport layer using SSL. If the communication is secured at the transport level then message integrity is
provided by using SSL. If communication is secured at the message level then the response message will be
signed with a key derived from the encrypted key which was sent in the request message.

* The last step is the encrypting the response. Encryption is dependent on whether communication is secured at
the message level using WSE 3.0 or at the transport level using SSL. If communication is secured at the
transport level the encryption for the message is left to SSL. If communication is secured at the message layer
then response signature and the message is encrypted with a key derived from the encrypted key sent in the
request message.

Implementing WSE Service


Using WS-Security requires coding on both the client and the server. The server is expecting authentication
information to be packed into the SOAP header. The client has to take steps to create this header with the user’s
credentials. The server needs to validate these credentials against a user data store before executing the service
request.
We will now implement WSE authentication. In order to implement the following example WE 3.0 must be
installed on the computers that we’re going to use to develop WSE-enabled applications. In later sections we will
explore how to use the WSE API to manually attach security tokens to outgoing SOAP messages. This process
can also be automated so that the WSE runtime adds the required tokens for us. In order to do this, us must
configure a policy for outbound messages and define a security token cache that WSE can use to get a valid
token.
In Visual Studio Create a new Web service project by select File -> New -> Web Site. Select ASP.NET
Web Service under templates. Choose the location that we want the project to be in and also the preferred
language to be used.

600
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 15-7. Creating a new Web Service project

To enable a Visual Studio 2005 project to support WSE 3.0. Right mouse click on the project in solution
explorer and select WSE Settings 3.0 (see figure 15-8 below).

Figure 15-8. WSE Settings 3.0

601
The Complete Reference To Professional SOA with Visual Studio 2005

On the General tab, select the “Enable this project for Web Services Enhancements” check box, and also
select the “Enable Microsoft Web Services Enhancements Soap Protocol Factory” then click OK (see figure 15-9
below). this will add reference to the WSE 3 assembly as well configure the necessary settings within the
Web.config configuration file.

Figure 15-9. Enabling WSE

After we enable the service application to support WSE 3.0 SOAP extensions, we must enable policy
support. If our application does not currently have a policy cache file, we can add one and enable policy support
by performing the following steps.

1. In Visual Studio 2005, right-click the application project and select WSE Settings 3.0.
2. On the Policy tab, select the “Enable Policy” check box. Selecting this check box will automatically add the
wse3policyCache.config file as the default name for the policy cache file.

3. Within the Edit Application Policy group, select Add and then type "usernameTokenSecurity" for the new
application policy.

4. Click OK to start the WSE Security Settings Wizard, and then click Next (see figure 15-10. below).

602
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 15-10. WSE Security wizard

5. On the Authentication Settings page, the wizard provides us with options to secure a service or a client. Select
the secure a service application option button to configure the service.

6. The wizard also provides us with authentication method choices on the same page. Select Username and click
Next.

Figure 15-11. WSE Authentication Settings

7. On the Users and Roles section, we can configure authorization based on the user name or roles associated with
the user represented in the UsernameToken. By default, the perform authorization check box is cleared. If we
wanted to perform authorization through the policy assertion, select the perform authorization check box, add
users and roles as appropriate, and then click Next. In this example we will not be using this.

603
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 15-12. WSE Users and Roles

8. On the Message Protection page, we can configure options for message protection. For transport layer security,
select None (to rely on transport protection for example point-to-point security using SSL/HTTPS only) for the
Protection Order this will use the usernameOverTransportSecurity assertion. For this example select None (rely
on transport protection). Click Next. If we select any other protection option, the policy assertion will use
usernameForCertificateSecurity. This is because the other options under Protection Order other than None rely
on transport protection and will require a certificate for signing and encrypting, In this example select the
option for Sign, Encrypt, Encrypt Signature. By default, the Enable WS-Security 1.1 Extensions check box is
selected. This option must be enabled if we are going to use certificate security.

Figure 15-13. WSE Message Protection

9. On the Create Security Settings page, review the settings, and then click Finish (see figure 15-14 below).

604
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 15-14. WSE Summary

10. This will add the usernameTokenSecurity under the Application Policy section. Click ok to complete the
process and save the settings to the configuration file wse3policyCache.config (see figure 15-15 below).

Figure 15-15. WSE Settings

After we have completed the above steps, our server security policy should look similar to the following
code below.

Listing 15-2. Demonstrates the generated wse3policyCache.config

605
The Complete Reference To Professional SOA with Visual Studio 2005

<policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy">
<extensions>
<extension name="usernameOverTransportSecurity"
type="Microsoft.Web.Services3.Design.UsernameOverTransportAssertion,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
<extension name="requireActionHeader"
type="Microsoft.Web.Services3.Design.RequireActionHeaderAssertion,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</extensions>
<policy name="usernameTokenSecurity">
<usernameOverTransportSecurity />
<requireActionHeader />
</policy>
</policies>

We can see that the configuration is set to use usernameOverTransportSecurity as we had specified during the
configuration wizard.

Listing 15-3. Web.config

<?xml version="1.0" encoding="utf-8"?>


<configuration>
<configSections>
<section name="microsoft.web.services3"
type="Microsoft.Web.Services3.Configuration.WebServicesConfiguration,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</configSections>
<system.web>
<webServices>
<soapExtensionImporterTypes>
<add type="Microsoft.Web.Services3.Description.WseExtensionImporter,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</soapExtensionImporterTypes>
</webServices>
<compilation>
<assemblies>
<add assembly="Microsoft.Web.Services3, Version=3.0.0.0,
Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</assemblies>
</compilation>
</system.web>
<microsoft.web.services3>
<policy fileName="wse3policyCache.config" />
</microsoft.web.services3>
</configuration>

The listing above demonstrates the Web.Config file that has been modified by the WSE configuration
wizard. We can see that the wse3policyCache.config policy file has been set in the Web.Config file and also that

606
The Complete Reference To Professional SOA with Visual Studio 2005

SOAP extensions had been set to the WSE 3.0 assembly. This is necessary for WSE to intercept messages in
order to apply the ws-security.

Listing 15-4. Demonstrates the Web service code in Visual C#

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using Microsoft.Web.Services3.Design;
using Microsoft.Web.Services3;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[Policy("usernameTokenSecurity")]
public class Service : System.Web.Services.WebService
{
public Service () {

//Uncomment the following line if using designed components


//InitializeComponent();
}

[WebMethod]
public string EmployeeSalaryDetail(string id) {
if (id == "123")
{
return "Salary for John Doe is $xyz";
}
return "no salary details found";
}

Listing 15-5. Demonstrates the Web service code in Visual Basic .NET

Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports Microsoft.Web.Services3.Design
Imports Microsoft.Web.Services3

<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
<Policy("usernameTokenSecurity")> _
Public Class Service
Inherits System.Web.Services.WebService

<WebMethod()> _
Public Function EmployeeSalaryDetail(ByVal id As String) As String
If id = "123" Then
Return "Salary for John Doe is $xyz"

607
The Complete Reference To Professional SOA with Visual Studio 2005

End If
Return "no salary details found"
End Function

End Class

In the listings 15-4 and listings 15-5 above we have created a standard Web service the only difference is that we
have specified to use Policy("usernameTokenSecurity") this is a way of telling WSE to apply the policy of
usernameTokenSecurity within our class. As in WSE we can specify many different policies. With the policy
that we have selected using username and password token authentication the WSE engine will validate against
the windows user accounts on the server by default.
In the following section we will examine how to create a client application to consume the WSE web
service.

Implementing WSE Client


Creating a client that implements WSE is quite simple. Thanks to the WSE settings configuration tool. We will
start by creating a console application in Visual Studio.
In Visual Studio Create a new console application by selecting File -> New -> Project. Select the preferred
language to be used then select Console Application from under templates. Choose the location that the project
and the name of the project.

Figure 15-16. Create a new console project

Enabling WSE for the console application is the same process as enabling for the web service. To enable a
Visual Studio 2005 project to support WSE 3.0. Right mouse click on the console project in solution explorer
and select WSE Settings 3.0.

608
The Complete Reference To Professional SOA with Visual Studio 2005

On the General tab, select the Enable this project for Web Services Enhancements check box, and then click
OK. This will add reference to the WSE 3 assembly as well configure the necessary settings within the
app.config configuration file for the console application.
After we enable the service application to support WSE 3.0 SOAP extensions, we must enable policy
support. If our application does not currently have a policy cache file, we can add one and enable policy support
by performing the following steps.

1. In Visual Studio 2005, right-click the application project and select WSE Settings 3.0.
2. On the Policy tab, select the “Enable Policy” checkbox. Selecting this setting automatically adds
wse3policyCache.config a policy cache file. (This is the same process as configuring WSE policy for the Web
service).

3. In “Edit Application Policy”, select Add, and then type "usernameTokenSecurity" for the new application
policy.

4. Click OK to start the WSE Security Settings Wizard, and then click Next.

5. In “Authentication Settings” page, we are provided with a choice on how to secure a service or a client. Select
“Secure a client application” to configure the client.

6. The wizard also provides a choice of authentication methods in the same step. Select Username, and then click
Next (see figure 15-17 below).

Figure 15-17. Authentication settings for WSE client

7. In “Optionally Provide Username and Password” page, we are provided with options to define a user name and
password. Select “Specify Username Token in code” checkbox is selected and select Next.

609
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 15-18. Authenticate through Username and Password

8. On the “Message Protection” page, we can define options for message security. To configure for transport layer
security, select None which means that WSE will rely on transport protection using SSL. The Protection Order
will use the usernameOverTransportSecurity assertion. If we select any other protection option, the policy
assertion usernameForCertificateSecurity will be used. By default, the Enable WS-Security 1.1 Extensions
check box is enabled. This setting must be enabled if we are using message layer security.

9. Click Next to bring up the summary window then Finish to confirm.

10. Then OK on the WSE Settings dialog to save settings to the configuration file.

Listing 15-6. Demonstrates the wse3policyCache.config for the console client application.

<policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy">
<extensions>
<extension name="usernameOverTransportSecurity"
type="Microsoft.Web.Services3.Design.UsernameOverTransportAssertion,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
<extension name="requireActionHeader"
type="Microsoft.Web.Services3.Design.RequireActionHeaderAssertion,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</extensions>
<policy name="usernameTokenSecurity">
<usernameOverTransportSecurity />
<requireActionHeader />
</policy>
</policies>

Listing 15-7. Demonstrates the app.config file

610
The Complete Reference To Professional SOA with Visual Studio 2005

<?xml version="1.0" encoding="utf-8"?>


<configuration>
<configSections>
<section name="microsoft.web.services3"
type="Microsoft.Web.Services3.Configuration.WebServicesConfiguration,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</configSections>
<microsoft.web.services3>
<policy fileName="wse3policyCache.config" />
</microsoft.web.services3>
</configuration>

The listing 15-6 above, demonstrates the wse3policyCache.config file that was created by the WSE
configuration wizard. The policy had been converted to use usernameOverTransportSecurity which means that it
will not be signed or encrypted but totally rely on the security of SSL/HTTPS. In the app.config file listing 15-7
above, we can see that the wse3policyCache.config policy file has been set in the configuration file.
To access the WSE Web service from our client application simply create a web reference to our WSE Web
service. Then click Add Reference to complete.

Figure 15-19. Adding web reference to WSE Web service

When we add a Web reference to the service from the client application, two proxies are generated for the
Web service, one is a non-WSE 3.0 proxy and the other is WSE 3.0 enabled. In the WSE enabled proxy
Microsoft uses the naming convention of service name + "Wse". For example, if our Web service is named
"MyService", our WSE 3.0–enabled Web service proxy class name would be "MyServiceWse".

611
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 15-20. Demonstrates two server proxies one WSE enabled the other non-WSE

We can also use the WseWsdl3.exe tool under C:\Program Files\Microsoft WSE\v3.0\Tools to generate the
WSE proxy. The following command creates a client proxy class in C# for a Web service located at the specified
URL. The WSDL to SoapClient tool saves the client proxy class in the file MyProxyClass.cs.
WseWsdl3 http://hostServer/WebServiceRoot/WebServiceName.asmx?WSDL MyProxyClass.cs
The following command creates a client proxy class in Visual Basic for a Web service located at the
specified URL. The WSDL to SoapClient tool saves the client proxy class in the file MyProxyClass.vb.
WseWsdl3 http://hostServer/WebServiceRoot/WebServiceName.asmx?WSDL MyProxyClass.vb VB

Listing 15-8. Demonstrates Client application implementing Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Web.Services3.Security.Tokens;

namespace CSConsoleClient
{
class Program
{
static void Main(string[] args)
{
WSEProxy.ServiceWse proxy = new WSEProxy.ServiceWse();
try
{
UsernameToken token =
new UsernameToken("BookUser", "BookUser",
PasswordOption.SendPlainText);

proxy.SetClientCredential(token);

proxy.SetPolicy("usernameTokenSecurity");

string strDetails = proxy.EmployeeSalaryDetail("123");


Console.WriteLine(strDetails);
Console.ReadLine();
}
catch (Exception ex)
{
String strError = ex.Message;
Console.WriteLine(strError);
Console.ReadLine();
}
}
}
}

612
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 15-9. Demonstrates Client application implementing Visual Basic .NET

Imports Microsoft.Web.Services3.Security.Tokens
Module Module1

Sub Main()
Dim proxy As WSEProxy.ServiceWse = New WSEProxy.ServiceWse
Try
Dim token As UsernameToken = _
New UsernameToken("BookUser", "BookUser", _
PasswordOption.SendPlainText)
proxy.SetClientCredential(token)
proxy.SetPolicy("usernameTokenSecurity")
Dim strDetails As String = proxy.EmployeeSalaryDetail("123")
Console.WriteLine(strDetails)
Console.ReadLine()
Catch ex As Exception
Dim strError As String = ex.Message
Console.WriteLine(strError)
Console.ReadLine()
End Try

End Sub

End Module

In listing 15-8 and listing 15-9 above, we have created a client application that will consume the WSE web
service. In the above listings we have used the ServiceWSE proxy to create an object to the Web service.
Attaching a username token to a request message is as simple as defining a new UsernameToken object and
attaching it to the proxy context using the SetClientCredential function for the outbound message shown below:

Listing 15-10. Using Visual C#

UsernameToken token =
new UsernameToken("BookUser", "BookUser",
PasswordOption.SendPlainText);

proxy.SetClientCredential(token);

Listing 15-11. Using Visual Basic .NET

Dim token As UsernameToken = New UsernameToken("BookUser", "BookUser", _


PasswordOption.SendPlainText)
proxy.SetClientCredential(token)

Note: The Username in this case is BookUser, this is using Windows Integrated Security so we need to ensure that the user BookUser is
added onto the system.

613
The Complete Reference To Professional SOA with Visual Studio 2005

We then need to attach the policy we had configured through the WSE configuration wizard. This policy
contains information about how WSE should handle the security headers. This policy needs to be attached to the
proxy object by using the WSE proxy’s SetPolicy function.

Listing 15-12. Using Visual C#

proxy.SetPolicy("usernameTokenSecurity");

Listing 15-13. Using Visual Basic .NET

proxy.SetPolicy("usernameTokenSecurity")
Once all the necessary information is set in the proxy object. We can make the necessary request to our
webservice through proxy.EmployeeSalaryDetail("123") just as how we would normally make a call to the Web
service. The result is shown below.

Figure 15-21. Shows a successfully authenticated and authorized Web service call

However if an incorrect credential is provided a SOAP fault will be generated. The requesting application
will be denied access to the WebMethod.

Figure 15-22. Shows the exception thrown if an incorrect credential is used

The listing below demonstrates a request message sent to the WSE service we can see that because we had
selected plaintext and to transmit the password is actually not encrypted.

Listing 15-14. Demonstrates the request sent to the WSE Web service

<?xml version="1.0" encoding="utf-8"?>


<outputMessage utc="6/13/2006 7:49:40 AM"

614
The Complete Reference To Professional SOA with Visual Studio 2005

messageId="urn:uuid:cb166956-1202-4f34-bbcb-94c0d4d71572">
<processingStep description="Unprocessed message">
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<EmployeeSalaryDetail xmlns="http://tempuri.org/">
<id>123</id>
</EmployeeSalaryDetail>
</soap:Body>
</soap:Envelope>
</processingStep>
<processingStep
description="Entering SOAP filter Microsoft.Web.Services3
.Design.UsernameOverTransportAssertion+ClientOutputFilter" />
<processingStep description="Exited SOAP filter Microsoft.Web
.Services3.Design.UsernameOverTransportAssertion+ClientOutputFilter" />
<processingStep description="Processed message">
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/
envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/
oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/
oasis-200401-wss-wssecurity-utility-1.0.xsd">
<soap:Header>
<wsa:Action>http://tempuri.org/EmployeeSalaryDetail</wsa:Action>
<wsa:MessageID>urn:uuid:cb166956-1202-4f34-bbcb-94c0d4d71572
</wsa:MessageID>
<wsa:ReplyTo>
<wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/
addressing/role/anonymous</wsa:Address>
</wsa:ReplyTo>
<wsa:To>http://localhost:1704/CSService/Service.asmx</wsa:To>
<wsse:Security soap:mustUnderstand="1">
<wsu:Timestamp wsu:Id="Timestamp-71379091-a431-41d8
-9732-1a363e76d5cf">
<wsu:Created>2006-06-13T07:49:40Z</wsu:Created>
<wsu:Expires>2006-06-13T07:54:40Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/
wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
wsu:Id="SecurityToken-20f9c662-4201-44ea-993a-f11cefb1a485">
<wsse:Username>BookUser</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/
wss/2004/01/oasis-200401-wss-username-token-profile-1.0
#PasswordText">BookUser</wsse:Password>
<wsse:Nonce>1MUXtG6OAAEjBjKQPHchmA==</wsse:Nonce>
<wsu:Created>2006-06-13T07:49:40Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>

615
The Complete Reference To Professional SOA with Visual Studio 2005

</soap:Header>
<soap:Body>
<EmployeeSalaryDetail xmlns="http://tempuri.org/">
<id>123</id>
</EmployeeSalaryDetail>
</soap:Body>
</soap:Envelope>
</processingStep>
</outputMessage>

The listing below demonstrates the response sent by the Web service to the client.

Listing 15-15. Demonstrates the response received from the WSE Web service

<?xml version="1.0" encoding="utf-8"?>


<inputMessage utc="6/13/2006 7:49:40 AM"
messageId="urn:uuid:66faec6b-e9d4-485d-90af-62d3e1def4ee">
<processingStep description="Unprocessed message">
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/
oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/
oasis-200401-wss-wssecurity-utility-1.0.xsd">
<soap:Header>
<wsa:Action>http://tempuri.org/
EmployeeSalaryDetailResponse</wsa:Action>
<wsa:MessageID>urn:uuid:66faec6b-e9d4-485d-90af-62d3e1def4ee
</wsa:MessageID>
<wsa:RelatesTo>urn:uuid:cb166956-1202-4f34-bbcb-94c0d4d71572
</wsa:RelatesTo>
<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/
role/anonymous</wsa:To>
<wsse:Security>
<wsu:Timestamp wsu:Id="Timestamp-9eca1a24-4aeb-4343-bbb7-
b013471f657e">
<wsu:Created>2006-06-13T07:49:40Z</wsu:Created>
<wsu:Expires>2006-06-13T07:54:40Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
</soap:Header>
<soap:Body>
<EmployeeSalaryDetailResponse xmlns="http://tempuri.org/">
<EmployeeSalaryDetailResult>Salary for John Doe is $xyz
</EmployeeSalaryDetailResult>
</EmployeeSalaryDetailResponse>
</soap:Body>
</soap:Envelope>
</processingStep>
<processingStep

616
The Complete Reference To Professional SOA with Visual Studio 2005

description="Entering SOAP filter Microsoft.Web.Services3.Design.


UsernameOverTransportAssertion+ClientInputFilter" />
<processingStep description="Exited SOAP filter Microsoft.Web.
Services3.Design.UsernameOverTransportAssertion+ClientInputFilter" />
<processingStep description="Processed message">
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/
envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/
oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/
oasis-200401-wss-wssecurity-utility-1.0.xsd">
<soap:Header />
<soap:Body>
<EmployeeSalaryDetailResponse
xmlns="http://tempuri.org/">
<EmployeeSalaryDetailResult>
Salary for John Doe is $xyz</EmployeeSalaryDetailResult>
</EmployeeSalaryDetailResponse>
</soap:Body>
</soap:Envelope>
</processingStep>
</inputMessage>

Implementing Custom Username Service


On the server, a SOAP extension runs to process the SOAP header when the message arrives with the
authentication information packed into the Security element. This is done by an instance of a class deriving from
SecurityTokenManager. In the following example we will explore how to use our own user data store to validate
and authenticate. We will need to create an instance of a type that inherits from UsernameTokenManager and look
the credentials up against our own user security datastore whether it’s a flat file, a database or a xml file. The
UserNameTokenManager class derives from SecurityTokenManager.
We can do the work of authentication by overriding the virtual AuthenticateToken method on the base class
of UserNameTokenManager. This method gets passed the user name that the client sent, and our job in
implementing this method is to look up the user’s password and send it back as a return value of the method call.
The WSE code then compares the passwords and decides if the caller should be authenticated or not.
In this example the security policy of the client will be the same as the security policy we had used in the
previous example. The client implementation of the WSE code will still be the same as it really is the server’s
responsibility to authenticate and validate the requesting client. As such switching to a custom Username token
validation will not affect client implementation. The listing below demonstrates the server implementations of
custom username token validation.

Listing 15-16. Demonstrates implementing the Web service in Visual C#

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using Microsoft.Web.Services3;
using Microsoft.Web.Services3.Security.Tokens;

617
The Complete Reference To Professional SOA with Visual Studio 2005

using Microsoft.Web.Services3.Security;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[Policy("usernameTokenSecurity")]
public class Service : System.Web.Services.WebService
{
public Service()
{

//Uncomment the following line if using designed components


//InitializeComponent();
}

[WebMethod]
public string EmployeeSalaryDetail(string id)
{
if (id == "123")
{
return "Salary for John Doe is $xyz";
}
return "no salary details found";
}
}

Listing 15-17. Demonstrates implementing the Web service in Visual Basic .NET

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports Microsoft.Web.Services3.Security.Tokens
Imports Microsoft.Web.Services3
Imports Microsoft.Web.Services3.Security
Imports System.Xml
Imports System.Security.Permissions
Imports System.Web.Security
Imports System.Security.Principal
Namespace AuthenticationManager

Public Class CustomUsernameTokenManager


Inherits UsernameTokenManager

Public Sub New()


End Sub

Public Sub New(ByVal nodes As XmlNodeList)


MyBase.New(nodes)
End Sub

Protected Overloads Overrides Function AuthenticateToken _


(ByVal token As UsernameToken) As String
Dim username As String = token.Username

618
The Complete Reference To Professional SOA with Visual Studio 2005

If username = "john" Then


Return "doe"
Else
Throw New ApplicationException
End If
End Function
End Class
End Namespace

The Web service implementation for custom usertoken authentication is the same as the previous example.
As the configuration is really up to the UsernameTokenManager that we will now implement in the section below.
The WSE engine will look into the Web.config file for any custom token manager details that had been
specified. It will then load the relevant token managers for authentication and authorization.

Listing 15-18. Demonstrates implementing UsernameTokenManager using Visual C#

//AuthenticationManager.cs
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Web.Services3.Security.Tokens;
using Microsoft.Web.Services3;
using Microsoft.Web.Services3.Security;
using System.Xml;
using System.Security.Permissions;
using System.Web.Security;
using System.Security.Principal;

namespace AuthenticationManager
{
[SecurityPermissionAttribute(SecurityAction.Demand,
Flags = SecurityPermissionFlag.UnmanagedCode)]
public class CustomUsernameTokenManager : UsernameTokenManager
{
/// <summary>
/// Constructs an instance of this security token manager.
/// </summary>
public CustomUsernameTokenManager()
{
}

/// <summary>
/// Constructs an instance of this security token manager.
/// </summary>
/// <param name="nodes">
/// An XmlNodeList containing XML elements from a
/// configuration file.</param>
public CustomUsernameTokenManager(XmlNodeList nodes)
: base(nodes)
{
}

619
The Complete Reference To Professional SOA with Visual Studio 2005

/// <summary>
/// Returns the password or password equivalent
/// for the username provided.
/// Adds a principal to the token whith user's roles.
/// </summary>
/// <param name="token">The username token</param>
/// <returns>The password (or password equivalent)
/// for the username</returns>
protected override string AuthenticateToken(UsernameToken token)
{
string username = token.Username;
if (username == "john")
return "doe";
else
throw new ApplicationException();
}

Listing 15-19. Demonstrates implementing UsernameTokenManager using Visual Basic .NET

‘AuthenticationManager.cs
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports Microsoft.Web.Services3.Security.Tokens
Imports Microsoft.Web.Services3
Imports Microsoft.Web.Services3.Security
Imports System.Xml
Imports System.Security.Permissions
Imports System.Web.Security
Imports System.Security.Principal
Namespace AuthenticationManager

Public Class CustomUsernameTokenManager


Inherits UsernameTokenManager

Public Sub New()


End Sub

Public Sub New(ByVal nodes As XmlNodeList)


MyBase.New(nodes)
End Sub

Protected Overloads Overrides Function AuthenticateToken _


(ByVal token As UsernameToken) As String
Dim username As String = token.Username
If username = "john" Then
Return "doe"
Else

620
The Complete Reference To Professional SOA with Visual Studio 2005

Throw New ApplicationException


End If
End Function
End Class
End Namespace

The key in implementing custom username token validation is in inheriting from the
UsernameTokenManager class and then overriding the AuthenticateToken function (see listing 15-18, and listing
15-19). The AuthenticateToken function is the method that is executed when used during validation. The
requesting user token is passed into the function. Here we can perform our custom functions whether it is from a
flat file, database or a XML file. The password once retrieved needs to be returned in which case WSE will
compare with the password that is contained in the token. The advantage of this is sometimes the password that
is passed in might be hashed. We are abstracted from the complexity involved in different client security policy
implementations by WSE.
It is important to note that we will need to throw an exception if password can not be found. As sometimes a
developer simply returns an empty string due to pure habit. This is a risk as the requesting application may also
send a blank string as a password field.
Once the CustomUsernameTokenManager class is created and compiled, it must be registered as a security
token manager using the WSE configuration utility. We would deploy this assembly into the bin directory of our
web service application and fill out the Security tab in the WSE configuration dialog to point to our custom
CustomUsernameTokenManager assembly.

In Visual Studio 2005, right-click the application project and select WSE Settings 3.0.

Figure 5-23. WSE Security Tab

1. On the Security Tab, under Security Tokens Managers select Add

621
The Complete Reference To Professional SOA with Visual Studio 2005

2. Set the Type name as: AuthenticationManager.CustomUsernameTokenManager


3. Set the Namespace to: http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd

4. Set the LocalName as: UsernameToken

The type attribute field requires fully qualified type name, followed by the assembly name. The namespace
declaration and the LocalName attribute must be listed exactly as shown.

Figure 15-24. Add a SecurityToken Manager

5. Click OK to close the SecurityToken Manager and then OK again to close the WSE Settings dialog.

The settings in WSE settings will add the securityTokenManager into the Web.config file see listing 15-20
below.

Listing 15-20. Web.config

<?xml version="1.0" encoding="utf-8"?>


<configuration>
<configSections>
<section name="microsoft.web.services3"
type="Microsoft.Web.Services3.Configuration.WebServicesConfiguration,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</configSections>
<system.web>
<webServices>
<soapExtensionImporterTypes>
<add type="Microsoft.Web.Services3.Description.WseExtensionImporter,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</soapExtensionImporterTypes>
<soapServerProtocolFactory
type="Microsoft.Web.Services3.WseProtocolFactory,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</webServices>
<compilation debug="true">

622
The Complete Reference To Professional SOA with Visual Studio 2005

<assemblies>
<add assembly="Microsoft.Web.Services3, Version=3.0.0.0,
Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Security, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" />
<add assembly="System.Design, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" />
<add assembly="System.Configuration.Install,
Version=2.0.0.0, Culture=neutral,
PublicKeyToken=B03F5F7F11D50A3A" />
</assemblies>
</compilation>
</system.web>
<microsoft.web.services3>
<security>
<securityTokenManager>
<add type="AuthenticationManager.CustomUsernameTokenManager"
namespace="http://docs.oasis-open.org/wss/2004/01/
oasis-200401-wss-wssecurity-secext-1.0.xsd"
localName="UsernameToken" />
</securityTokenManager>
<x509 allowTestRoot="true" revocationMode="Offline"
verificationMode="TrustedPeopleOnly" />
</security>
<policy fileName="wse3policyCache.config" />
<diagnostics>
<trace enabled="true" input="InputTrace.webinfo"
output="OutputTrace.webinfo" />
<detailedErrors enabled="true" />
</diagnostics>
</microsoft.web.services3>
</configuration>

Our custom usernameTokeManager is added as a type in the Web.config configuration file, the type of the
SecurityTokenManager is comprised of the namespace and class implementing the handler and the name of the
assembly containing the class, without extension.
In the listing below we will be adding a Web Reference to the WSE enabled Web Service the reference will
be named as WSEProxy.

Listing 15-21. Demonstrates the client code required to access the Web service in Visual C#

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Microsoft.Web.Services3.Security.Tokens;
using Microsoft.Web.Services3;

623
The Complete Reference To Professional SOA with Visual Studio 2005

public partial class _Default : System.Web.UI.Page


{
protected void Page_Load(object sender, EventArgs e)
{
WSEProxy.ServiceWse proxy = new WSEProxy.ServiceWse();
try
{

UsernameToken token =
new UsernameToken("john", "doe",
PasswordOption.SendPlainText);

proxy.SetClientCredential(token);

proxy.SetPolicy("usernameTokenSecurity");

string strReturn = proxy.HelloWorld();


Response.Write(strReturn);
}
catch (Exception ex)
{
String strError = ex.Message;
Response.Write(strError);
}
}
}

Listing 15-22. Demonstrates the client code required to access the Web service in Visual Basic .NET

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports Microsoft.Web.Services3.Security.Tokens
Namespace CSConsoleClient

Public Class Program

Shared Sub Main()


Dim proxy As WSEProxy.ServiceWse = New WSEProxy.ServiceWse
Try
Dim token As UsernameToken = _
New UsernameToken("john", "doe", _
PasswordOption.SendPlainText)
proxy.SetClientCredential(token)
proxy.SetPolicy("usernameTokenSecurity")
Dim strReturn As String = proxy.EmployeeSalaryDetail("123")
Console.WriteLine(strReturn)
Console.ReadLine()
Catch ex As Exception
Dim strError As String = ex.Message
Console.WriteLine(strError)
Console.ReadLine()
End Try
End Sub

624
The Complete Reference To Professional SOA with Visual Studio 2005

End Class
End Namespace

The client code used to access the Web service is the same as that from the previous example.

Figure 15-25. Shows the result from the execution.

X. 509 Certificate
X.509 is used in cryptography. It is an International Telecommunication Union (ITU-T) standard which is used
for Public Key Infrastructure (PKI). X.509 most known for specifying standard formats for public key
certificates and a certification path for validation algorithm.
X.509 replaces user IDs and passwords with digital certificates. A trusted third party Certificate Authority
(CA) is an entity which issues digital certificates for use by other parties. X.509 refers to an authentication
scheme built around public key encryption. With X.509, a trusted, third-party CA assigns each user a signed
digital certificate and a pair of encryption keys, a public key and a private key.
X.509 digital certificates are widely used as a basis for securing communications between separate
endpoints. For example, they are used to support the HTTP Secure Sockets Layer (SSL) protocol, otherwise
known as HTTPS. We will be working directly with the X.509 certificates. We can obtain a test certificate in
several ways, making a certificate using the makecert.exe command-line tool to generate a test certificate or
obtaining a test certificate from VeriSign, WSE 3.0 also comes with test certificates that we can use.

The X.509 Certificate Management Tool


In order to manage our certificates we need to be able to install them and remove them when necessary. The
Microsoft Management Console (MMC) Certificates snap-in tool can be used to manage certificates. The X.509
Certificate tool allows us to display details about X.509 certificates stored on the local computer and to set
permissions on the files containing the keys for an X.509 certificate. The Certificates snap-in also allows us to,
among other tasks, import and export X.509 certificates on a local computer.
In the following examples we will be using the WSE test certificates, these certificates are installed with
WSE 3.0 quickstart (the WSE 3.0 quickstart is included on the source for download from the book Web site).

1. Open a new MMC console by clicking Start -> Run


2. In the Run box, type mmc, and then click OK.

3. The MMC console window should now appear on the File menu, click Add/Remove Snap-in, and then click
Add.

4. The Add Standalone Snap-in Under Snap-in, double-click Certificates.

625
The Complete Reference To Professional SOA with Visual Studio 2005

5. Click My user account, and then click Finish. This allows us to manage certificates for the current user.
Certificates – Current User appears on the list of selected snap-ins for the new console.

6. While the Add Standalone snap-in is still open under Snap-in, add another Certificates snap-in by double-
clicking on the Certificates.

7. Add the computer Computer Management snap in, by selecting Add and then selecting Computer Management
from the list of possible snap ins. Click Add, click Local computer, and then click Finish.

8. Click Close to close the Add Standalone Snap-in and OK to close the Add/Remove Snap-in dialog windows.
This will allows us to manage local computer certificates.

9. To save this console, on the File menu, click Save.

Figure 15-26. Shows using the certificates tool in MMC

TIP: The certificates that are displayed are installed by default when you install WSE 3.0

WSECertificate3.exe
WSE also comes with a X.509 certificate tool (WSECertificate3.exe). The X.509 Certificate tool displays details
about X.509 certificates stored on the local computer. This information helps us diagnose configuration issues
related to X.509 certificates. The WSECertificate3.exe tool allows us to View details about an X.509 certificate
and view the attributes of the file containing the private key for an X.509 certificate.
To run the X.509 Certificate tool

1. Click Start, point to All Programs, point to Microsoft WSE 2.0, and then click X.509 Certificate Tool.

626
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 15-27. Shows the WSE X.509 Certificate Tool.

To view details about an X.509 certificate

2. Enter the Certificate Location and Store Name for the X.509 certificate.
3. Click Open Certificate.

4. Choose the X.509 certificate, and then click OK.

To view the attributes of the file containing the private key for an X.509 certificate

5. Enter the Certificate Location and Store Name for the X.509 certificate.
6. Click Open Certificate.

7. Choose the X.509 certificate, and then click OK.

8. Click View Private Key File Properties.

A dialog box appears with file properties for the file containing the private key associated with the X.509
certificate. We can use this dialog box to give permission to the user account that the WSE is running under by
doing the following:
1. Click the Security tab.

2. If the user account that the WSE is running under is not listed in the Group or user names list, click Add.

3. The Select Users, Computers, or Groups dialog box appears.

627
The Complete Reference To Professional SOA with Visual Studio 2005

4. In the Enter the object names to select box, type the name for the user account that the WSE is running under,
and then click OK.

5. Select the Allow check box for the Read permission.

6. Click OK.

Sign and Encrypt a SOAP Message (End-To-End Security)

WSE allows us to add encryption and signatures to outgoing messages. Signatures are generated using a
specified security token object. All security token types supported by WSE can be used to sign a SOAP message.
Though, not all instances of a token object support signing.
Securing the communication channel between the client and the service is very important. We can enable
security through the use of certificates by using the usernameForCertificateSecurity WSE 3.0 turnkey assertions.
This will enable message level security or End-To-End security by providing data confidentiality to prevent
eavesdropping. Message origin authentication can also be validated to prevent tampering or message spoofing.
Message level security is implemented by using the service’s X.509 certificate. The
usernameForCertificateSecurity turnkey assertion can be used to secure the communication channel. However this
is not compatible with client computers that have implemented WS-Security 1.0. This is because the
usernameForCertificateSecurity turnkey assertion depends on the ability to reference <EncryptedKey> elements
as security tokens, and enables the option for signature confirmation to correlate a response message with the
request that prompted it. Both of these features are only available in WS-Security 1.1. If we need to implement
security at message level between client and service with a solution that is compatible with WS-Security 1.0 we
will need to implement this by creating a custom policy assertion.
We can configure both the Web service implementing WSE as well as the WSE client application to
implement Sign and Encrypt simply by modifying the policy we had created earlier by using the WSE
configuration tool. Because we have selected to Sign and Encrypt our messages WSE will prompt us to enter our
X.509 certificate.
To configure policy support to use Sign and Encrypt in WSE 3.0-enabled Visual Studio 2005 project we will
be using the example we had created earlier with token authentication.

Configuring WSE Web service to Sign and Encrypt

1. In Visual Studio 2005, right-click the application project and select WSE Settings 3.0.

2. On the Policy tab, select the Enable Policy checkbox. Selecting this setting adds a policy cache file with the
default name wse3policyCache.config.

3. Under Edit Application Policy, click Add, and then type a policy friendly name for the new application policy,
such as "usernameTokenSecurity."

4. Click OK to start the WSE Security Settings Wizard, and then click Next.

5. On the Authentication Settings page, the wizard provides a choice to secure a service application.

6. The wizard also provides a choice of authentication methods in the same step. Select Username, and then click
Next.

628
The Complete Reference To Professional SOA with Visual Studio 2005

7. On the Optionally Provide Users and Roles page, click Next to continue.

8. On the Message Protection page, we can configure options for message protection. We will select “Sign and
Encrypt”. This will automatically use the usernameForCertificateSecurity policy assertion.

Figure 15-28. WSE Message Protection

9. Click Next.

10. We will now come to a Server Certificate configuration page. On the Store Location choose LocalMachine.
And Click on Select Certificate.

Figure 15-29. Selecting a X.509 Certificate

11. Select the WSE2QuickStartServer certificate then click OK. Then Next.

629
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 15-30. WSE Server Certificate configuration

12. On the Create Security Settings page, review the settings, and then click Finish.

13. Click OK to close the WSE Settings dialog window.

Configuring WSE Client Application to Sign and Encrypt


In order to implement secure communication we must implement security on both sides. Using the WSE settings
tool the steps are the same as that of configuring for WSE service. The only difference is we need to select Client
during the Authentication Settings step in the policy configuration. Here are the steps to implementing security
on the client side.

1. In Visual Studio 2005, right-click the application project and select WSE Settings 3.0.

2. On the Policy tab, select the Enable Policy checkbox. Selecting this setting adds a policy cache file with the
default name wse3policyCache.config.
3. Under Edit Application Policy, click Add, and then type a policy friendly name for the new application policy,
such as "usernameTokenSecurity."

4. Click OK to start the WSE Security Settings Wizard, and then click Next.

5. On the Authentication Settings page, the wizard provides a choice to secure a Client.

6. The wizard also provides a choice of authentication methods in the same step. Select Username, and then click
Next.

7. On the Optionally Provide Username and Password page, click Next to continue.

8. On the Message Protection page, we can configure options for message protection. We will select “Sign and
Encrypt”. This will automatically use the usernameForCertificateSecurity policy assertion.

9. Click Next.

630
The Complete Reference To Professional SOA with Visual Studio 2005

10. We will now come to a Server Certificate configuration page. On the Store Location choose LocalMachine.
And Click on Select Certificate.

11. Select the WSE2QuickStartServer certificate then click OK. Then Next.

12. On the Create Security Settings page, review the settings, and then click Finish.

13. Click OK to close the WSE Settings dialog window.

Listing 15-23. Demonstrates the signed and encrypted request SOAP Message

<soap:Envelope
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/
oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/
oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
.
.
.
<wsu:Timestamp
wsu:Id="Timestamp-3e7d40d1-0060-40a5-a711-528d4ac6f25e">
<wsu:Created>2006-06-14T06:47:07Z</wsu:Created>
<wsu:Expires>2006-06-14T06:52:07Z</wsu:Expires>
</wsu:Timestamp>
<xenc:EncryptedKey
Id="SecurityToken-f4b7b281-7193-4b37-a960-5a592bbbe6de"
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
<xenc:EncryptionMethod
Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p">
<ds:DigestMethod
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
</xenc:EncryptionMethod>
.
.
.
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<ds:CanonicalizationMethod
Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#" />
<SignatureMethod
Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1" />
<Reference
URI="#SecurityToken-efd24129-fa1f-4ca0-bbfd-d76ef62c6f47">
<Transforms>
<Transform
Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod

631
The Complete Reference To Professional SOA with Visual Studio 2005

Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>fHa41bEoBYaCAV/QUp7bNFJtOJM=</DigestValue>
</Reference>
.
.
.
<soap:Body wsu:Id="Id-0e59d56d-d309-46e0-85f1-50ecaaf14b9d">
<xenc:EncryptedData
Id="Enc-05209377-c7a0-464a-ab7b-e59f91c2df89"
Type="http://www.w3.org/2001/04/xmlenc#Content"
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
<xenc:EncryptionMethod
Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">

Listing 15-24. Demonstrates the signed and encrypted response SOAP Message

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<ds:CanonicalizationMethod
Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#" />
<SignatureMethod
Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1" />
<Reference URI="#Id-94e2b69b-4db1-4520-897a-335db2a07a0d">
<Transforms>
<Transform
Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod
Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>/7vTIR7+xHJb+TvPrmohsg3pPos=</DigestValue>
</Reference>

.
.
.
.

<Reference URI="#Id-7e1aacb9-5342-40dd-b6aa-a9c3f47d3d76">
<Transforms>
<Transform
Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod
Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>l1EsdLhBi2jilH9iy0uzfZsT0+w=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>cVOlLPE71rdX7y8+x4affGu+YXQ=</SignatureValue>
<KeyInfo>
<wsse:SecurityTokenReference>
<wsse:Reference
URI="#SecurityToken-e18fe938-10d9-444c-915a-b9d14acbccd3"

632
The Complete Reference To Professional SOA with Visual Studio 2005

ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/dk" />
</wsse:SecurityTokenReference>
</KeyInfo>
</Signature>

Best Security Practice


The securest method of transmitting message is setting message protection level to Sign, Encrypt, Encrypt
Signature. This means that we will sign the message to ensure integrity, as well as encrypt the SOAP message
but WSE will also encrypt the signature themselves to provide additional level of security.

Figure 15-31. Message Protection, Signing, Encrypting, Encrypt Signature

While when sending user token details across the wire. Instead of specifying to send the Password as a plain
text we can also specify to send the password as a Hashed value.
UsernameToken token = new UsernameToken("BookUser", "BookUser",
PasswordOption.SendHashed);
To add wired security we can specify IIS to implement SSL/HTTPS. All of these options when combined provide the optimum security
solution when sending data across the wire in a service-oriented environment.

Note: Using Signing and Encryption will have an impact on the performance as it takes resource to encrypted and signed SOAP message.
As the amount of data that we send to the Web service increase so too does the time it takes to encrypt and decrypt.

Binary Exchange with Message Transmission


Optimization Mechanism (MTOM)

In spite of the flexibility and acceptance of XML in application architecture, there are certain limitations
associated with XML. These limitations are for example media data and data that includes digital signatures are

633
The Complete Reference To Professional SOA with Visual Studio 2005

two of the most common examples. The reason is with media data there are highly standardized formats where
compression plays a major part. While for digital signatures, the binary integrity required would not be preserved
if it were serialized into a structured XML format. At the same time serializing binary data proved to be
extremely resource intensive. As a result there are various methods for sending binary data through the use of
Web services. These are:

* XML Representation: Replace any non-Xml data with a structured XML representation and include it in our
message. The problem here is that it bloats the data tremendously. However, if we are sending something like
Microsoft Word documents, we might want to consider saving them in XML format.
* SOAP with Attachments (SwA): Use SOAP with Attachments to send binary data with SOAP in a MIME
Multipart message. SOAP with Attachments was the first attempt by Microsoft (along with Hewlett Packard) at
solving the opaque data/attachments problem. Unfortunately SwA had poor composability and it did not work
well with the WS-* specifications.
* WS-Attachments with DIME: Compared to SOAP with attachments this is a faster and more efficient solution
to sending binary data. However it also has the same composability issues as SwA. As in the case with SwA, it
does not use a SOAP envelope approach to messaging. This limits DIME’s ability of the higher-level Web
service specifications to properly work upon a message.

* Base 64 Encoding: This method of encoding has been used for quite sometime and is well known for its binary
data problem. Although base-64-encoded data is usually more efficient from a message-size perspective than
using XML Representation, it still increases the data size by about 33% even when only single byte characters
are used.

* Message Transmission and Optimization Mechanism (MTOM): MTOM is widely accepted today in binary
transport. The MTOM approach take advantage of the SOAP infrastructure, but gain the transport efficiencies
provided by a SOAP with Attachments solution. MTOM is supported in WSE 3.0 and it will also be supported
by the future Windows Communication Foundation (WCF) see chapter 16.

MTOM implementation combines the benefits of composability of Base 64 encoding with the transport
efficiency of SwA. The binary data is dealt with just like it is with SwA it is simply streamed as binary data as
one of the Multipurpose Internet Mail Extensions (MIME) message parts. MTOM utilizes what is called an
XML Information Set (Infoset). Infoset allows for easy serialization/deserialization of the entire message into
XML form. At the Infoset level, immediately before the message is serialized, the binary data is accessed, it is
temporarily treated as base-64-encoded text.
By using the Infoset, we can implement WS-Security for binary attachments. In MTOM the WS-Security
layer create a digital signature for message level security. The binary data is streamed through a layer in which it
is temporarily encoded to base-64. During the streaming the signature of the message is calculated. The encoded
base-64 data is not transferred or held in memory. On deserialization, the same concepts apply. The raw binary is
transferred directly to the higher layer, but any processing layers that access it would do so through a temporary
base-64-encoding layer (see figure 15-32 below).

634
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 15-32. MTOM process

Implementing MTOM Service


Implementing MTOM with WSE is quite simple. We can configure it from the WSE Settings tool.

1. Open the Web service project in Visual Studio 2005.

2. In Solution Explorer, right-click the project name, and then click WSE Settings 3.0….

3. Select the General tab.

635
The Complete Reference To Professional SOA with Visual Studio 2005

4. Select Enable this project for Web Services Enhancements and Enable Microsoft Web Services Enhancements
SOAP Protocol Factory.

5. To enable our Web service to use MTOM select the Messaging tab.

6. Choose always for the Server Mode (see figure 15-32).

Figure 15-32. Enabling MTOM

There are several options under the Server Mode drop down list. Optional, Alaways and Never. The optional
MTOM Mode specifies that WSE processes all incoming SOAP messages whether or not they are MTOM
encoded and that all SOAP responses and SOAP faults are MTOM encoded.
The Sever Mode for the option always specifies MTOM encoding will be applied to all incoming and
outgoing SOAP messages. And if a SOAP request is received that is not encoded using MTOM, a SOAP fault is
returned to the sender.
Select Off for Client Mode and leave MaxMimeParts at 64 and check Require Soap Evelope First

Click OK to close the WSE settings Dialog

This adds an <mtom> Element to the Web service's Web.config file.


Having done the above steps we can start utilizing MTOM immediately. All that we need to do is add a Web
service method that has a parameter or return value with a type that is either a byte array or a type that contains a
byte array. MTOM will be used automatically as the byte data is sent across the wire.
The following code example shows a Web service method that returns a byte array using the contents from a
file on disk and then returns it in the SOAP message.

Listing 15-25. Demonstrates the service using Visual C#

636
The Complete Reference To Professional SOA with Visual Studio 2005

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.IO;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
public Service () {

//Uncomment the following line if using designed components


//InitializeComponent();
}

[WebMethod]
public byte[] GetFile(string fileName)
{
byte[] response;
String filePath = AppDomain.CurrentDomain.BaseDirectory +
@"App_Data\" + fileName;
response = File.ReadAllBytes(filePath);
return response;
}
}

Listing 15-26. Demonstrates the service using Visual Basic .NET

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.IO;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
public Service () {

//Uncomment the following line if using designed components


//InitializeComponent();
}

[WebMethod]
public byte[] GetFile(string fileName)
{
byte[] response;
String filePath = AppDomain.CurrentDomain.BaseDirectory +
@"App_Data\" + fileName;
response = File.ReadAllBytes(filePath);

637
The Complete Reference To Professional SOA with Visual Studio 2005

return response;
}
}

By default the amount of data sent or received by the Web service is set at a limit of 4 MB to exceed 4 MB,
configure the Web server to handle the larger amount of data by modifying the Web.config file.
We can increase the ASP.NET limits on the maximum size of SOAP messages and the maximum number of
seconds that a request is allowed to execute by adding the <httpRuntime> configuration element to the
application's web.config file.
The following code example will set the ASP.NET limit for the maximum size of an incoming request to
400MB, and the maximum amount of time a request is allowed to execute to 5 minutes (300 seconds).
<configuration>
<system.web>
<httpRuntime maxRequestLength="409600" executionTimeout="300" />
</system.web>
</configuration>

To cater for large files we will also need to increase the WSE limit on the maximum size of SOAP messages using the
<maxMessageLength> Element. To send and receive the largest possible SOAP messages, set the value of the <maxMessageLength>
element to -1.
The following code example disables the limit on the maximum size of SOAP messages by WSE.
<configuration>
<microsoft.web.services3>
<messaging>
<maxMessageLength value="-1" />
</messaging>
</microsoft.web.services3>
</configuration>

Listing 15-27. Demonstrates a complete Web.config

<?xml version="1.0" encoding="utf-8"?>


<configuration>
<configSections>
<section name="microsoft.web.services3"
type="Microsoft.Web.Services3.Configuration
.WebServicesConfiguration, Microsoft.Web.Services3,
Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</configSections>
<appSettings />
<connectionStrings />
<system.web>
<compilation debug="true">
<assemblies>
<add assembly="Microsoft.Web.Services3, Version=3.0.0.0,
Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</assemblies>
</compilation>
<authentication mode="Windows" />
<webServices>
<soapExtensionImporterTypes>

638
The Complete Reference To Professional SOA with Visual Studio 2005

<add type="Microsoft.Web.Services3.Description
.WseExtensionImporter, Microsoft.Web.Services3,
Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</soapExtensionImporterTypes>
<soapServerProtocolFactory
type="Microsoft.Web.Services3.WseProtocolFactory,
Microsoft.Web.Services3, Version=3.0.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</webServices>
<httpRuntime maxRequestLength="409600" executionTimeout="300" />
</system.web>
<microsoft.web.services3>
<messaging>
<mtom serverMode="always" />
<maxMessageLength value="-1" />
</messaging>
</microsoft.web.services3>
</configuration>

Implementing MTOM Client


Implementing MTOM for a client is quite straight forward. As all of the real hard work is taken care of by WSE. We
do not need to do anything special aside from using the WSE proxy to facilitate communication between the Client and
the Server.

1. Open the Web service project in Visual Studio 2005.


2. In Solution Explorer, right-click the project name, and then click WSE Settings 3.0….

3. Select the General tab.

4. Select Enable this project for Web Services Enhancements.

5. To enable our Web service to use MTOM select the Messaging tab.

6. Choose always for the Server Mode.

7. Select On for Client Mode and leave MaxMimeParts at 64 and check Require Soap Evelope First

8. Click OK to close the WSE settings Dialog

This adds an <mtom> Element to the client application’s app.config file. The following settings are added to
the App.config file.
Listing 15-28. The client appliaction’s App.config after configuration
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="microsoft.web.services3"
type="Microsoft.Web.Services3.Configuration
.WebServicesConfiguration, Microsoft.Web.Services3,

639
The Complete Reference To Professional SOA with Visual Studio 2005

Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
<sectionGroup name="applicationSettings"
type="System.Configuration.ApplicationSettingsGroup,
System, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089">
<section name="MTOMClient.Properties.Settings"
type="System.Configuration.ClientSettingsSection,
System, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089"
requirePermission="false" />
</sectionGroup>
</configSections>
<microsoft.web.services3>
<messaging>
<mtom clientMode="On" serverMode="always" />
</messaging>
</microsoft.web.services3>
<applicationSettings>
<MTOMClient.Properties.Settings>
<setting name="MTOMClient_WSEProxy_Service" serializeAs="String">
<value>http://localhost:4529/MTOMService/Service.asmx</value>
</setting>
</MTOMClient.Properties.Settings>
</applicationSettings>
</configuration>
Having done the above steps we can start utilizing MTOM immediately. The following code example shows
a client application requesting for the GetFile WebMethod. Because we are using MTOM WSE will manage the
retrival of the byte array automatically. The byte array will be retrieved from the Web service and written to hard
disk on the client side.
Here’s the client implementing below.

Listing 15-29. Demonstrates MTOM client using Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace MTOMClient
{
class Program
{
static void Main(string[] args)
{
WSEProxy.ServiceWse wseproxy =
new MTOMClient.WSEProxy.ServiceWse();
byte [] content = wseproxy.GetFile("test.txt");
File.WriteAllBytes("test.txt", content);
}
}
}

640
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 15-30. Demonstrates MTOM client using Visual Basic .NET

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.IO

Module Module1

Sub Main()
Dim wseproxy As WSEProxy.ServiceWse = _
New VBMTOMClient.WSEProxy.ServiceWse()
Dim content As Byte() = wseproxy.GetFile("test.txt")
File.WriteAllBytes("test.txt", content)
End Sub
End Module

Summary
In this chapter we have explored using WSE to implement WS-Security. The WS-Security specification defines
SOAP extensions for message integrity, message confidentiality, and single message authentication. These
mechanisms can be used to accommodate a wide variety of security models and encryption technologies. WS-
Security is implemented at the message level rather than transport.
Using WSE we have implemented message authentication using security tokens based on username and
password. We have also implemented digital signature and encryption using X.509 certificates.
The best method of security is through a combination of security over transport using SSL/HTTPS (poing-
to-point security) as well as SOAP message signing and encryption (end-to-end security).
In this chapter we have also examined Message Transmission Optimization Mechanism (MTOM). MTOM
combines the composability of Base 64 encoding with the transport efficiency of SOAP with Attachment (SwA).
MTOM is the new binary standard that will be supported by Windows Communication Foundation (WCF).
Using WSE 3.0 will give us a lot more communication security options. WSE 3.0 supports the latest WS-*
specifications. The same ones will be supported by Windows Communication Foundation. This makes WSE 3.0
and WCF wire-compatible and thus allow WCF clients to interoperate with WSE 3.0 services and vice versa.

641
The Complete Reference To Professional SOA with Visual Studio 2005

Chapter 16. Windows


Communication Foundation
(WCF)
Windows Communication Foundation (formerly code-named "Indigo") is a new set of .NET technologies that
revolutionizes building and running connected systems. WCF provides a new breed of communications
infrastructure that views all distributed components as a service. The heart of WCF is built around the Web
services architecture. Advanced Web services support in Windows Communication Foundation provides secure,
reliable, and transacted messaging along with interoperability. Microsoft endeavored to improve the service-
oriented landscape and with the aim to improve programming model and development efficiency of distributed
service development through the use of WCF. WCF is built on the .NET Framework and unifies a broad array of
distributed systems capabilities in a composable and extensible architecture, spanning transports, security
systems, messaging patterns, encodings, network topologies, and hosting models.
Windows Communication Foundation is an exciting technology because it removes the need to explicitly
choose the technology that we need to use up-front. In the past developers are required to contend with a variety
of different technology choices for building distributed applications. These include XML Web services (ASMX),
Web Services Enhancements (WSE), .NET Remoting, Microsoft Message Queue (MSMQ) and Enterprises
Services (COM+). All of these different technologies complement each other in different ways. As a result
developers and architects are faced with the daunting task of balancing the pros and cons of each technology
before development. Making the wrong choice in technology at the beginning could have a significant impact
later on. Developing with WCF however is different. WCF is very robust because it has a programming model
which combines different technologies into a single Service-oriented programming model for distributed
computing.
WCF also unifies a wide range of transports (HTTP, TCP, UDP, IPC), security mechanisms (public and symmetric
keys, certificates), topologies (point-to-point, end-to-end, peer-to-peer, publish-and-subscribe), and assurances
(transacted, reliable, durable) all of this provide WCF with rich connectivity to many existing systems.
In this chapter we will cover the fundamentals of WCF. We will also learn to develop secure, reliable WCF
service as well as WCF Client. Some of the things that we will cover includes:

* Implementing WCF Service

* Implementing A WCF Service Client


* Developing a hosting environment from which WCF service can be launched.
* Implementing Custom Binding, Reliable Mesasging and Security

* Implementing WCF with Microsoft Message Queue


* WCF Sessions
* WCF Transactions

* Duplex Communication

642
The Complete Reference To Professional SOA with Visual Studio 2005

Note: In order to compile the examples in this chapter you will need to download “WinFx Runtime” which can be found when you search at
http://www.microsoft.com/download/. Once the runtime has been installed “Orcas” which contains the Development Tools for WinFX
should also be installed. Orcas can also be found at http://www.microsoft.com/download/.

WCF Foundamentals
A WCF Service is a program that exposes a collection of Endpoints. Each Endpoint is a portal for
communicating with the world. A WCF endpoint is composed of three parts, address, binding and contracts.
These are also referred to as the ABCs of WCF see figure 16-1.

Figure 16-1. ABCs of Windows Communication Foundation

* "A" stands for Address - Refers to where is the the service located? The Address is a network address where
the Endpoint resides. It can be a URI, an Identity or a collection of headers. The headers are used to provide
additional addressing information beyond the Endpoint's URI. For example, address headers are useful for
differentiating between multiple Endpoints that share the same address URI.

643
The Complete Reference To Professional SOA with Visual Studio 2005

* "B" stands for Binding – Refers to how do we communicate with the service? The Binding specifies how the
Endpoint communicates with the world including things like transport protocol (TCP, HTTP), encoding (text,
binary), and security requirements (SSL, SOAP message security). A Binding has a name, a namespace, and a
collection of composable binding elements. The Binding's name and namespace uniquely identify it in the
service's metadata. Each binding element describes an aspect of how the Endpoint communicates with the
world. Each BindingElement defines how to communicate with the Endpoint. The
TcpTransportBindingElement indicates that the Endpoint will communicate with the world using TCP as the
transport protocol. ReliableSessionBindingElement indicates that the Endpoint uses reliable messaging to
provide message delivery assurances. SecurityBindingElement indicates that the Endpoint uses SOAP message
security. Each binding element usually has properties that further describe the specifics of the how to
communicating with the Endpoint.
* "C" stands for Contract – Refers to what can the service do for us? The Contract specifies what the Endpoint
communicates to the outside world. Each operation is a simple message exchange, for example one-way or
request/response message exchange. The ContractDescription class is used to describe WCF Contracts and
their operations. Inside a ContractDescription, exist a Contract operation has a corresponding
OperationDescription. This describes aspects of the operation such as whether the operation is one-way or
request/ response. Each OperationDescription also describes the messages that make up the operation using a
collection of MessageDescriptions.

Contracts
In WCF we can define several different types of contracts.

* ServiceContract - A service contract resides on the service side to specify which of the service’s endpoint
should be exposed to callers. It is also used on the client side to specify the contract of the endpoint with which
the client communicates and, in the case of duplex contracts, to specify the callback contract that the client
must implement in order to participate in a duplex conversation.

* OperationContract - The OperationContract declares that a method is an operation in a service contract. In the
WCF model we must explicitly mark all operations that we want to expose. Only methods decorated with the
OperationContract attribute are exposed as service operations. A service contract without any methods marked
with the OperationContract attribute exposes no operations.
* DataContract – The data contract provide information about the items that flow across service boundaries.

* FaultContract - The FaultContract attribute is used to declare one or more specific exception conditions that are
added to the Web Service Description Language (WSDL) description of the method as explicit SOAP fault
messages returned by the method.

* MessageContract- MessageContract attribute defines the structure of the message types our service uses.

Defining Service Contracts


A ServiceContract defines what application interface will be exposed as a WCF service. WCF follows the
service-orientation of "explicit boundaries". Which means unless we explicitly tell the runtime to do so nothing
is exposed through WCF. WCF implements the model which strictly distinguishes between elements that are
made visible and accessible to the outside world (all publicly accessible elements must be explicitly specified)
and those without decorated explicit attributes to expose functionalities are private to the application. The
"public", "private" and "protected" keywords of C# and Visual Basic and the underlying access protection
mechanisms are meaningful to the code inside an application, but whether an interface or method that's public

644
The Complete Reference To Professional SOA with Visual Studio 2005

within the scope of an application shall indeed be publicly visible to the outside world is an entirely different
matter altogether. However, there might cases where it is desirable to enforce that a method that's designed
exclusively for accessing the application from the outside is not accidentally invoked from within the
application. Under such circumstances, a method might be best declared as "private" towards the inside of the
application, but is indeed made accessible to outside callers.

Listing 16-1. Demonstrates an example of implementing Service Contract using Visual C#

using System.ServiceModel;

[ServiceContract]
public interface ICalculate
{
[OperationContract]
double Add( double a, double b);
[OperationContract]
double Subtract( double a, double b);
}

Listing 16-2. Demonstrates an example of implementing Service Contract using Visual Basic .NET

Imports System.ServiceModel

<ServiceContract()> _
Public Interface ICalculate

<OperationContract()> _
Function Add(ByVal a As Double, ByVal b As Double) As Double

<OperationContract()> _
Function Subtract(ByVal a As Double, ByVal b As Double) As Double
End Interface

Here the interface has been labeled with the [ServiceContract] attribute. That attribute explicitly marks a
CLR interface as to carry contract metadata for WCF. Each method is explicitly labeled with the
[OperationContract] attribute, which is the WCF equivalent to a "public" method. Based on the existence and the
additional, optional parameters that can be supplied to these metadata attributes, the WCF runtime can, whenever
required, turn the [ServiceContract] into an equivalent WSDL portType declaration. Each [OperationContract]
declaration is then mapped to an equivalent WSDL operation definition whereby the parameter lists and return
values are turned into XML schema declarations reference by the WSDL types section and the respective WSDL
message mappings.

Defining Data Contracts


The data contract defines the shape and rules for the data that is exchanged through operation's input and output
messages. The split between the data contract and the service contract is important. Service contracts define the
logic and semantic related set of operations grouped on an interface and these are about how a service behaves.
The data contract defined information items that flow across service boundaries and that are handled with
additional logic on the provider and consumer side.

645
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 16-3. Demonstrates implementing DataContract using C#

[DataContract]
public class Person
{
[DataMember]
public int Id;
[DataMember]
public string FirstName;
[DataMember]
public string LastName;
}

Listing 16-4. Demonstrates implementing DataContract using VB

<DataContract()> _
Public Class Person
<DataMember()> _
Public Id As Integer
<DataMember()> _
Public FirstName As String
<DataMember()> _
Public LastName As String
End Class

Above is a data contract for a person. The attributes stem from the System.Runtime.Serialization namespace
that is the home of the new XmlFormatter infrastructure. The XmlFormatter is similar to the XmlSerializer (as
well as the BinaryFormatter and SoapFormatter) in purpose, but there are quite few differences.
The most significant difference between the XmlFormatter and the XmlSerializer is that the new
infrastructure intentionally provide less control for developers over the XML schema and the way how data is
serialized to and deserialized from XML. That may seem strange at first consideration we typically get increased
control and flexibility. But this was the result of a trade off decision. We are now trading detail control for
automatic versioning support of messages in the new versioning in WCF model. WCF’s versioning model
provide an easier way of implementing loosely coupled, evolvable data structures. To take advantage of this new
functionality, we will have to surrender some control over the schema details to the formatter infrastructure. The
new XmlFormatter does not allow a data contract to be defined as XML attributes and elements. All data is
always serialized into XML elements.
Changes to a data contract can be breaking or nonbreaking. When a data contract is changed in a
nonbreaking way, an application using the older version of the contract is able to communicate with an
application using the newer version, and an application using the newer version of the contract is able to
communicate with an application using the older version. On the other hand, a breaking change prevents
communication in one or both directions.
Any changes to a type that do not affect how it is transmitted and received are nonbreaking. Such changes
do not change the data contract, only the underlying type. For example, we can change the name of a field in a
nonbreaking way if we then set the Name property of the DataMember to the older version name. The following
code shows version 1 of a data contract.

Listing 16-5. Demonstrates implementing Versioning in Visual C#

// Version 1

646
The Complete Reference To Professional SOA with Visual Studio 2005

[DataContract]
public class Person
{
[DataMember]
private string Phone;
}

Listing 16-6. Demonstrates implementing Versioning in Visual Basic

' Version 1
<DataContract()> _
Public Class Person
<DataMember()> _
Private Phone As String
End Class

The following code shows a nonbreaking change:

Listing 16-7. Demonstrates implementing Versioning in Visual C#

// Version 2. This is a non-breaking change because the data contract


// has not changed, even though the type has.
[DataContract]
public class Person
{
[DataMember(Name = "Phone")]
private string Telephone;
}

Listing 16-8. Demonstrates implementing Versioning in Visual Basic .NET

' Version 2. This is a non-breaking change because the data contract


' has not changed, even though the type has.
<DataContract()> _
Public Class Person
<DataMember(Name := "Phone")> _
Private Telephone As String
End Class

In versioning we can also force a check for a particular DataMember by using the IsRequired attribute.

Listing 16-9. Demonstrates implementing Versioning in Visual C#

[DataContract]
public class Person
{
[DataMember]
public int Id;
[DataMember]
public string FirstName;
[DataMember]
public string LastName;

647
The Complete Reference To Professional SOA with Visual Studio 2005

[DataMember(IsRequired = true)]
public string MiddleName;
}

Listing 16-10. Demonstrates implementing Versioning in Visual Basic .NET

<DataContract()> _
Public Class Person
<DataMember()> _
Public Id As Integer
<DataMember()> _
Public FirstName As String
<DataMember()> _
Public LastName As String
<DataMember(IsRequired :=True)> _
Public MiddleName As String
End Class
We can tell the XmlFormatter infrastructure to treat the newly introduced member as an optional member by
labeling the new member with the IsRequired property on the [DataMember] attribute set to false. That means
that if we receive data serialized by an older version of the contract (which might be embedded in a client
proxy), the member will remain with its value upon deserialization and the newer version will gracefully accept
an older version's input where this element is missing. If IsRequired is set to true and the respective element is
missing in the deserialization input, an exception is raised.

RPC/Messaging
WCF was created to improve on the existing model of service-orientation. As such WCF focuses on the service-
orientation idea that services exchange messages rather than procedure calls. Unlike the ASMX “stateless”
service model WCF also support sessions which allows detailed control over the lifetime of a service instance.
As such we can build services where instances are created and released for each call or a defined sequence of
calls, where instances exist for the duration of a session, or we can even build singletons where one service
instance is shared by all callers.
What we cannot do, is to pass objects by reference or pass callback delegates this contrasts Remoting. The
reason for this restriction is that a service-oriented technology cannot make as many assumptions about the
network as the local area network technologies such as Remoting. In an environment where services can be
easily separated across platforms, trust boundaries and wide area networks we can not assume that bi-directional
connectivity is possible. Clients can also reside behind firewalls, or networks that utilize network address
translation (NAT) or simply do not actively listen for messages or security restrictions may restrict the sending
of calls. Therefore, implicit backchannels such as those established by callbacks and object references simply
don't work in a services world. Instead, such backchannels must be explicitly established using so-called
"duplex" conversations.
In WCF we can implement a "typed message". A typed message is essentially like a typed DataSet. It is an
explicitly composed message structure that is labeled with a [MessageContract] attribute as shown in listing 16-9
and listing 16-10 has zero or more [MessageHeader] members and zero or more [MessageBody] members. The
[MessageHeader] members are mapped to headers in the SOAP envelope while [MessageBody] members are
represented as elements within the SOAP envelope's body section see listing 16-9 and listing 16-10 below.

Listing 16-9. Demonstrates implementing MessageContract and MessageBody in Visual C#

public enum UpdateConcurrency

648
The Complete Reference To Professional SOA with Visual Studio 2005

{
UpdateIfModified,
FailIfModified
}

[DataContract]
public class UpdateBehavior
{
[DataMember]
public UpdateConcurrency UpdateConcurrencyMode;
}

[MessageContract]
public class StorePersonMessage
{
[MessageHeader]
public UpdateBehavior UpdateBehavior;
[MessageBody]
public Person Person;
}

[ServiceContract]
public interface IPeople
{
[OperationContract]
void StorePerson(StorePersonMessage storePersonMessage);
}

Listing 16-10. Demonstrates implementing MessageContract and MessageBody in Visual Basic .NET

Public Enum UpdateConcurrency


UpdateIfModified
FailIfModified
End Enum

<DataContract()> _
Public Class UpdateBehavior
<DataMember()> _
Public UpdateConcurrencyMode As UpdateConcurrency
End Class

<MessageContract()> _
Public Class StorePersonMessage
<MessageHeader()> _
Public UpdateBehavior As UpdateBehavior
<MessageBody()> _
Public Person As Person
End Class

<ServiceContract()> _
Public Interface IPeople
<OperationContract()> _

649
The Complete Reference To Professional SOA with Visual Studio 2005

Sub StorePerson(ByVal storePersonMessage As StorePersonMessage)


End Interface

We can also define message contract in an “inline” manner by specifying the operation’s parameter list. This
is useful if we want to add some additional information in the SOAP header but we don’t want to define an
explicit message class. Any parameter that has been labeled with MessageHeader attribute will be mapped to the
envelope’s header section. We can similarly specify other parameters to be added to the SOAP body by
decorating parameters with the MessageBody attribute. See listing 16-11 and listing 16-12.

Listing 16-11. Demonstrates implementing inline message contract using Visual C#

[OperationContract]
void StorePerson(
[MessageHeader] UpdateBehavior UpdateBehavior1,
[MessageBody] Person Person1);

Listing 16-12. Demonstrates implementing inline message contract using Visual Basic .NET

<OperationContract()> _
Sub StorePerson(<MessageHeader()> ByVal UpdateBehavior1 As UpdateBehavior, _
<MessageBody()> ByVal Person1 As Person)

If we need additional control over the Message’s content. We can use the System.ServiceModel.Message
argument with our operation. This provides us with immediate access to the WCF Message see listing 16-13 and
listing 16-14 below. The Message class exposes all headers in a collection where we can examine the content of
a range of special headers such as those relevant for security and addressing. The body of the content is
represented as an XmlReader.

Listing 16-13. Demonstrates implementing Message argument using Visual C#

[ServiceContract]
public interface IPeople
{
[OperationContract]
public void StorePerson(Message msg);
}

Listing 16-14. Demonstrates implementing Message argument using Visual Basic .NET

<ServiceContract()> _
Public Interface IPeople
<OperationContract()> _
Sub StorePerson(msg As Message)
End Interface

WCF is responsible for dispatching the messages to the correct operation. Messages that are received that do
not have a matching Action header to the contract’s OperationContract Attribute are rejected. If we would like to
accept all messages regardless of their Action header we can set a wildcard indicator which is represented by a
single asterisk (“*”). If this operation is present, all messages that cannot be matched are sent to this operation.
Which results in more flexibility to the SOAP messaging endpoint.

650
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 16-15. Demonstrates using Action wildcard attribute using Visual C#

[ServiceContract]
public interface IMyMessageHandler
{
[OperationContract(Action="*")]
public void HandleAnyMessage(Message message);
}

Listing 16-16. Demonstrates using Action wildcard attribute using Visual Basic .NET

<ServiceContract()> _
Public Interface IMyMessageHandler
Public<OperationContract(Action := "*")> _
Sub HandleAnyMessage(message As Message)
End Interface

Binding and Address (Endpoint)


The endpoint binding defines what protocols, transport, and encoding the endpoint will use for all its
communication and defines how securities work. WCF provides several predefined binding models. These are a
combination of transports, encodings and behaviors. These predefined models allow us in most cases to simply
select one of these predefined bindings. If required we can also implement custom binding. See table 16-1 below
which shows several predefined binding models that we can use.

Table 16-1. Binding Models

Class Description

BasicHttpBinding The BasicHttpBinding transports messages using HTTP

CustomBinding Custom binding allows us to tailor our need to define a new binding from a set of binding elements.

MsmqIntegrationBinding The MsmqIntegrationBinding binding can be used to map Microsoft Message Queuing Service
(MSMQ) messages to Windows Communication Foundation (WCF) messages.

NetMsmqBinding The NetMsmqBinding binding provides support for loosely coupled applications for queuing with
Microsoft Message Queue (MSMQ). This allows services to scale with failure isolation, load leveling and
disconnected operations.

NetNamedPipeBinding This binding provides a secure and reliable binding for same machine communication.

NetPeerTcpBinding The NetPeerTcpBinding binding provides support for TCP transport. This is used to support peer-to-
peer or multiparty applications.

NetTcpBinding The NetTcpBinding creates a run-time communication stack by default. NetTcpBinding utilizes WS-
ReliableMessaging for reliability. It also ensures message security and authentication by using Windows

651
The Complete Reference To Professional SOA with Visual Studio 2005

Security. NetTcpBinding uses TCP for message delivery, and a binary message encoding.

WSDualHttpBinding This binding uses HTTP for message delivery. The WSDualHttpBinding create a runtime stack
implementing WS-ReliableMessaging for reliability, WS-Security for message security and authentication.
This binding requires that the client has a public URI that provides a callback endpoint for the service.

WSHttpBinding This binding uses HTTP for message delivery. The WSHttpBinding is used for non-duplex service
contracts and provides support for securing with WS-Federation protocol.

Each of the predefined bindings supports some degree of customization of their respective features. If we
examine the configuration file required when specifying a particular binding there exists a <bindings> section
under this section where the binding used by WCF is defined. We can add a number of named customizations to
these subsections. The concrete binding that is used for an endpoint is selected by specifying the
bindingSectionName and the respective bindingConfigurationName within the definition for the endpoint.
Below shows an example of binding configuration in WCF.
<bindings>
<!-- configure a WSDualHttpBinding that supports duplex
communication -->
<wsDualHttpBinding>
<binding name="Binding1"
clientBaseAddress="http://localhost:8000/myClient/"
useDefaultWebProxy="true"
bypassProxyOnLocal="false">
<security mode="None">
<message algorithmSuite="Default"
clientCredentialType="Windows"
negotiateServiceCredential="true" />

</security>
</binding>
</wsDualHttpBinding>
</bindings>

In WCF an endpoint is defined with an <endpoint> element beneath the <service> element. The address of
the endpoint specifies the network address of the service. The bindingConfiguration refers to the predefined or
custom binding to be used and the contractType points to the interface class that hold the WCF [ServiceContract]
for the endpoint contract. If a class implements multiple service contracts, we will need to configure an endpoint
for each contract and all contracts must reside at distinct network addresses. A contract implementation for
which no endpoint is configured is not reachable everything must be explicit.
<endpoint address="http://localhost:10433/service/Service.svc"
binding="wsDualHttpBinding" bindingConfiguration="Binding1"
contract="Client.ICalculatorDuplex" />
A service can define any number of endpoints for each contract it implements. If we want a service to listen
to messages on HTTPS using the BasicHttpBinding with transport-level authentication, and on HTTP using the
WSHttpBinding with WS-Security in-message authentication, alongside the secure-by-default NetTcpBinding
for binary TCP transport, we can easily do so by adding the respective endpoints to the configuration and clients
can subsequently talk to the service through any endpoint they prefer. The service will listen to all these
endpoints in parallel.

652
The Complete Reference To Professional SOA with Visual Studio 2005

Implementing WCF Services


At the time of writing WCF is still at Beta 2 thus the installation process may differ at a later date. In order to
install WCF three things needs to be done.

1. As WCF is part of the WinFX now also known as .NET Framework 3.0. The WinFX runtime components will
need to be installed.

2. Next the Windows SDK will need to be installed the Window SDK is about 1 GB in size. It contains new
Visual Studio templates, code samples and documentations for Visual Studio 2005.

3. Lastly Visual Studio Development Tools codenamed ‘Orcas’ for WinFX development will need to be installed.
It includes the ‘Cider’ designer for XAML in Visual Studio.

Implementing WCF Service


Once .NET Framework 3.0 is installed Open Visual Studio 2005, create a new WCF service by selecting File-
>New->Web Site.

Figure 16-2. Implementing WinFX Service

Select WinFX Service under Templates, then select Location and choose the preferred programming language.

Notice immediately that the template for WinFX is different to that of the standard Web service.

Listing 16-17. Demonstrates the WinFX Service default template using Visual C#

using System;
using System.ServiceModel;
using System.Runtime.Serialization;

653
The Complete Reference To Professional SOA with Visual Studio 2005

[ServiceContract()]
public interface IMyService
{
[OperationContract]
string MyOperation1(string myValue1);
[OperationContract]
string MyOperation2(DataContract1 dataContractValue);
}

public class MyService : IMyService


{
public string MyOperation1(string myValue1)
{
return "Hello: " + myValue1;
}
public string MyOperation2(DataContract1 dataContractValue)
{
return "Hello: " + dataContractValue.FirstName;
}
}

[DataContract]
public class DataContract1
{
string firstName;
string lastName;

[DataMember]
public string FirstName
{
get { return firstName;}
set { firstName = value;}
}
[DataMember]
public string LastName
{
get { return lastName;}
set { lastName = value;}
}
}

Listing 16-18. Demonstrates the WinFX Service Template using Visual Basic .NET

Imports System
Imports System.ServiceModel
Imports System.Runtime.Serialization

<ServiceContract()> _
Public Interface IMyService

<OperationContract()> _
Function MyOperation1 _

654
The Complete Reference To Professional SOA with Visual Studio 2005

(ByVal myValue1 As String) As String

<OperationContract()> _
Function MyOperation2 _
(ByVal dataContractValue1 As DataContract1) As String

End Interface

Public Class MyService


Implements IMyService

Public Function MyOperation1 _


(ByVal myValue1 As String) As String Implements IMyService.MyOperation1
Return "Hello: " + myValue1
End Function

Public Function MyOperation2 _


(ByVal dataContractValue1 As DataContract1) _
As String Implements IMyService.MyOperation2
Return "Hello: " + dataContractValue1.FirstName
End Function

End Class

<DataContract()> _
Public Class DataContract1
Private m_firstName As String
Private m_lastName As String

Public Property FirstName() As String


Get
Return m_firstName
End Get
Set(ByVal value As String)
m_firstName = value
End Set
End Property

Public Property LastName() As String


Get
Return m_lastName
End Get
Set(ByVal value As String)
m_lastName = value
End Set
End Property

End Class

The listings above shows the default template when a new WinFX Service is first created.
In the following example we will create a WCF Service that will retrieve as well as update contact information that is
stored within the Adventureworks SQL server database.

655
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 16-19. Demonstrates the content of the WCF service using Visual C#

using System;
using System.ServiceModel;
using System.Runtime.Serialization;
using System.Data.SqlClient;
using System.Configuration;
using System.Data;

[ServiceContract()]
public interface IMyService
{
[OperationContract]
EmployeeContactDataContract RetrieveEmployeeContact(int EmployeeID);
[OperationContract]
void UpdateEmployeeContact(EmployeeContactDataContract dataContractValue);
}

public class MyService : IMyService


{
SqlConnection sqlcon =
new SqlConnection
(ConfigurationManager.AppSettings["ConnectionString"].ToString());

public EmployeeContactDataContract
RetrieveEmployeeContact(int ContactID)
{
// retrieve employee contact details
string sql = String.Format
("select ContactID, Title, FirstName, MiddleName, LastName" +
" from Person.Contact where ContactID = {0}", ContactID);
SqlCommand sqlcmd = new SqlCommand(sql, sqlcon);

sqlcon.Open();
SqlDataReader dreader = sqlcmd.ExecuteReader();
dreader.Read();

EmployeeContactDataContract contactDC =
new EmployeeContactDataContract();
contactDC.ContactID = (int)dreader["ContactID"];
contactDC.Title = dreader["Title"].ToString();
contactDC.FirstName = dreader["FirstName"].ToString();
contactDC.MiddleName = dreader["MiddleName"].ToString();
contactDC.LastName = dreader["LastName"].ToString();
sqlcon.Close();
return contactDC;
}

public void UpdateEmployeeContact(EmployeeContactDataContract ContactDC)


{
sqlcon.Open();
SqlTransaction transaction =
this.sqlcon.BeginTransaction("ContactTran");

656
The Complete Reference To Professional SOA with Visual Studio 2005

SqlCommand sqlcmdEmployee = new SqlCommand(


@"update Person.Contact set
FirstName = @FirstName,
MiddleName = @MiddleName,
LastName = @LastName
where Person.Contact.ContactID = @ContactID;", sqlcon);
sqlcmdEmployee.Transaction = transaction;
sqlcmdEmployee.Parameters.Add
("@ContactID", SqlDbType.Int, sizeof(int)).Value =
ContactDC.ContactID;
sqlcmdEmployee.Parameters.Add
("@FirstName", SqlDbType.VarChar, 50).Value =
ContactDC.FirstName;
sqlcmdEmployee.Parameters.Add
("@MiddleName", SqlDbType.VarChar, 50)
.Value = ContactDC.MiddleName;
sqlcmdEmployee.Parameters.Add
("@LastName", SqlDbType.VarChar, 50).Value = ContactDC.LastName;

sqlcmdEmployee.ExecuteNonQuery();
transaction.Commit();
sqlcon.Close();
}
}

[DataContract]
public class EmployeeContactDataContract
{
private string title;
private string firstName;
private string middleName;
private string lastName;
private int contactID;

[DataMember]
public int ContactID
{
get { return contactID; }
set { contactID = value; }
}

[DataMember]
public string Title
{
get { return title; }
set { title = value; }
}

[DataMember]
public string FirstName
{
get { return firstName;}

657
The Complete Reference To Professional SOA with Visual Studio 2005

set { firstName = value;}


}

[DataMember]
public string MiddleName
{
get { return middleName; }
set { middleName = value; }
}

[DataMember]
public string LastName
{
get { return lastName;}
set { lastName = value;}
}
}

Listing 16-20. Demonstrates the content of the WCF service using Visual Basic .NET

Imports System
Imports System.ServiceModel
Imports System.Runtime.Serialization
Imports System.Data.SqlClient
Imports System.Configuration
Imports System.Data

<ServiceContract()> _
Public Interface IMyService

<OperationContract()> _
Function RetrieveEmployeeContact(ByVal EmployeeID As Integer) _
As EmployeeContactDataContract

<OperationContract()> _
Sub UpdateEmployeeContact _
(ByVal dataContractValue As EmployeeContactDataContract)

End Interface

Public Class MyService


Implements IMyService
Private sqlcon As SqlConnection = _
New SqlConnection(ConfigurationManager.AppSettings _
("ConnectionString").ToString)

Public Function RetrieveEmployeeContact(ByVal ContactID As Integer) _


As EmployeeContactDataContract _
Implements IMyService.RetrieveEmployeeContact

Dim sql As String = String.Format( _


"select ContactID, Title, FirstName, MiddleName, LastName" + _

658
The Complete Reference To Professional SOA with Visual Studio 2005

" from Person.Contact where ContactID = {0}", ContactID)


Dim sqlcmd As SqlCommand = New SqlCommand(sql, sqlcon)
sqlcon.Open()
Dim dreader As SqlDataReader = sqlcmd.ExecuteReader
dreader.Read()
Dim contactDC As EmployeeContactDataContract = _
New EmployeeContactDataContract
contactDC.ContactID = CType(dreader("ContactID"), Integer)
contactDC.Title = dreader("Title").ToString
contactDC.FirstName = dreader("FirstName").ToString
contactDC.MiddleName = dreader("MiddleName").ToString
contactDC.LastName = dreader("LastName").ToString
sqlcon.Close()
Return contactDC
End Function

Public Sub UpdateEmployeeContact _


(ByVal ContactDC As EmployeeContactDataContract) _
Implements IMyService.UpdateEmployeeContact
sqlcon.Open()
Dim transaction As SqlTransaction = _
Me.sqlcon.BeginTransaction("ContactTran")
Dim sqlcmdEmployee As SqlCommand = _
New SqlCommand("update Person.Contact set FirstName = @FirstName," + _
" MiddleName = @MiddleName, LastName = @LastName " + _
" where Person.Contact.ContactID = @ContactID;", sqlcon)
sqlcmdEmployee.Transaction = transaction
sqlcmdEmployee.Parameters.Add("@ContactID", _
SqlDbType.Int).Value = ContactDC.ContactID
sqlcmdEmployee.Parameters.Add("@FirstName", _
SqlDbType.VarChar, 50).Value = ContactDC.FirstName
sqlcmdEmployee.Parameters.Add("@MiddleName", _
SqlDbType.VarChar, 50).Value = ContactDC.MiddleName
sqlcmdEmployee.Parameters.Add("@LastName", _
SqlDbType.VarChar, 50).Value = ContactDC.LastName
sqlcmdEmployee.ExecuteNonQuery()
transaction.Commit()
sqlcon.Close()
End Sub

End Class

<DataContract()> _
Public Class EmployeeContactDataContract
Private _title As String
Private _firstName As String
Private _middleName As String
Private _lastName As String
Private _contactID As Integer

<DataMember()> _
Public Property ContactID() As Integer

659
The Complete Reference To Professional SOA with Visual Studio 2005

Get
Return _contactID
End Get
Set(ByVal value As Integer)
_contactID = value
End Set
End Property

<DataMember()> _
Public Property Title() As String
Get
Return _title
End Get
Set(ByVal value As String)
_title = value
End Set
End Property

<DataMember()> _
Public Property FirstName() As String
Get
Return _firstName
End Get
Set(ByVal value As String)
_firstName = value
End Set
End Property

<DataMember()> _
Public Property MiddleName() As String
Get
Return _middleName
End Get
Set(ByVal value As String)
_middleName = value
End Set
End Property

<DataMember()> _
Public Property LastName() As String
Get
Return _lastName
End Get
Set(ByVal value As String)
_lastName = value
End Set
End Property
End Class

In the above service we have implemented two methods RetrieveEmployeeContact and


UpdateEmployeeContact. We have also created an interface for the service and have decorated it with the
ServiceContract attribute. This is important as it marks the interface as being accessible from the outside. We

660
The Complete Reference To Professional SOA with Visual Studio 2005

have also decorated the two methods with the OperationContract attribute. This is similar to the WebMethod
attribute in that each attribute defines the attached method as an exposed operation.
We have also created a Class called EmployeeContactDataContract. This class is decorated with the
DataContract attribute, the DataContract attributes declares the class as a structural contract type in WCF. The
DataContract declaration specifies how a .NET type is represented in an XML Schema. Within the DataContract
we have also specified DataMembers. DataMembers are needed to specify exactly which properties are needed so
that when the DataContract is serialized over the wire only those that have been marked with DataMember will
be sent.
In the EmployeeContactDataContract method we are taking a ContactID as a parameter and returning an
EmployeeContactDataContract object.
In the UpdateEmployeeContact method we are receiving an EmployeeContactDataContract object and
updating the values within the object to the database.
Build the project if the project builds without error press F5 to Start Debugging.

Figure 16-3. Shows the service running

Implementing A WCF Service Client


Start by creating a new console application within Visual Studio. Also add reference to the
System.ServiceModel.dll within the client project. The System.ServiceModel is used by WCF.

661
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 16-4. Add reference

To implement the Client side application we need to create a proxy for the WCF service. We can do this
through the use of the Service Metadata Utility Tool (SvcUtil.exe). It is used to retrieve metadata from a WCF
service and generate proxy code to allow access to the service. Using svcutil is very similar to the Add Web
Reference functionality in Visual Studio where you connect to a XML Web Service to generate the proxy. The
following example retrieves the metadata from the WCF service using the Svcutil and creates a C# output file
called MyService.cs and also a output.config file:
svcutil http://localhost:27771/EmployeeDetailService/Service.svc?wsdl
alternatively we could
svcutil http://localhost:27771/EmployeeDetailService/Service.svc?wsdl /out:serviceproxy.cs /config:app.config

Figure 16-5. Shows using svcutil.exe

SvcUtil.exe will create both code and configuration information. We can add the addresses and bindings
into the configuration file (or incorporate it in code). The contract proxy classes should be added in our own
custom code. SvcUtil will create the contract proxies, contract interfaces, endpoint configuration information,
and more. Here is an example of source code output from Svcutil:

662
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 16-21. Shows the generated proxy code from Svcutil using Visual C#

using System.Runtime.Serialization;
[System.CodeDom.Compiler.GeneratedCodeAttribute
("System.Runtime.Serialization", "3.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute()]
public partial class EmployeeContactDataContract : object,
System.Runtime.Serialization.IExtensibleDataObject
{

private System.Runtime.Serialization.ExtensionDataObject
extensionDataField;

private int ContactIDField;

private string FirstNameField;


.
.
.
public System.Runtime.Serialization.ExtensionDataObject
ExtensionData
{
get
{
return this.extensionDataField;
}
set
{
this.extensionDataField = value;
}
}

[System.Runtime.Serialization.DataMemberAttribute()]
public int ContactID
{
get
{
return this.ContactIDField;
}
set
{
this.ContactIDField = value;
}
}

[System.Runtime.Serialization.DataMemberAttribute()]
public string FirstName
{
get
{
return this.FirstNameField;
}
set
{

663
The Complete Reference To Professional SOA with Visual Studio 2005

this.FirstNameField = value;
}
}
.
.
.
[System.CodeDom.Compiler.GeneratedCodeAttribute
("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute()]
public interface IMyService
{

[System.ServiceModel.OperationContractAttribute
(ProtectionLevel=System.Net.Security.ProtectionLevel
.EncryptAndSign,
Action="http://tempuri.org/IMyService/RetrieveEmployeeContact",
ReplyAction="http://tempuri.org/IMyService/
RetrieveEmployeeContactResponse")]
EmployeeContactDataContract RetrieveEmployeeContact(int EmployeeID);

[System.ServiceModel.OperationContractAttribute
(ProtectionLevel=System.Net.Security.ProtectionLevel
.EncryptAndSign,
Action="http://tempuri.org/IMyService/UpdateEmployeeContact",
ReplyAction="http://tempuri.org/IMyService/
UpdateEmployeeContactResponse")]
void UpdateEmployeeContact(EmployeeContactDataContract
dataContractValue);
}

[System.CodeDom.Compiler.GeneratedCodeAttribute
("System.ServiceModel", "3.0.0.0")]
public interface IMyServiceChannel : IMyService,
System.ServiceModel.IClientChannel
{
}

[System.CodeDom.Compiler.GeneratedCodeAttribute
("System.ServiceModel", "3.0.0.0")]
public partial class MyServiceProxy :
System.ServiceModel.ClientBase<IMyService>, IMyService
{

public MyServiceProxy()
{
}

public MyServiceProxy(string endpointConfigurationName) :


base(endpointConfigurationName)
{
}

public MyServiceProxy(string endpointConfigurationName,

664
The Complete Reference To Professional SOA with Visual Studio 2005

string remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}

.
.
.
public void UpdateEmployeeContact(EmployeeContactDataContract
dataContractValue)
{
base.InnerProxy.UpdateEmployeeContact(dataContractValue);
}
}

In order to generate VB code using SvcUtil use /language:vb for example


svcutil http://localhost:27771/EmployeeDetailService/Service.svc?wsdl /language:vb

Listing 16-22. Shows the generated proxy code from Svcutil using Visual Basic .NET

Option Strict Off


Option Explicit On

Imports System.Runtime.Serialization

<System.CodeDom.Compiler.GeneratedCodeAttribute
("System.Runtime.Serialization", "3.0.0.0"), _
System.Runtime.Serialization.DataContractAttribute()> _
Partial Public Class EmployeeContactDataContract
Inherits Object
Implements System.Runtime.Serialization.IExtensibleDataObject

Private extensionDataField As
System.Runtime.Serialization.ExtensionDataObject

Private ContactIDField As Integer


.
.
.
Public Property ExtensionData() As
System.Runtime.Serialization.ExtensionDataObject
Implements System.Runtime.Serialization
.IExtensibleDataObject.ExtensionData
Get
Return Me.extensionDataField
End Get
Set
Me.extensionDataField = value
End Set
End Property

665
The Complete Reference To Professional SOA with Visual Studio 2005

<System.Runtime.Serialization.DataMemberAttribute()> _
Public Property ContactID() As Integer
Get
Return Me.ContactIDField
End Get
Set
Me.ContactIDField = value
End Set
End Property

<System.Runtime.Serialization.DataMemberAttribute()> _
Public Property FirstName() As String
Get
Return Me.FirstNameField
End Get
Set
Me.FirstNameField = value
End Set
End Property
.
.
.
End Class

<System.CodeDom.Compiler.GeneratedCodeAttribute
("System.ServiceModel", "3.0.0.0"), _
System.ServiceModel.ServiceContractAttribute()> _
Public Interface IMyService

<System.ServiceModel.OperationContractAttribute
(ProtectionLevel:=System.Net.Security.ProtectionLevel
.EncryptAndSign,
Action:="http://tempuri.org/IMyService/RetrieveEmployeeContact",
ReplyAction:="http://tempuri.org/IMyService/
RetrieveEmployeeContactResponse")> _
Function RetrieveEmployeeContact
(ByVal EmployeeID As Integer) As EmployeeContactDataContract

<System.ServiceModel.OperationContractAttribute
(ProtectionLevel:=System.Net.Security.ProtectionLevel
.EncryptAndSign,
Action:="http://tempuri.org/IMyService/UpdateEmployeeContact",
ReplyAction:="http://tempuri.org/IMyService/
UpdateEmployeeContactResponse")> _
Sub UpdateEmployeeContact(ByVal dataContractValue As
EmployeeContactDataContract)
End Interface

<System.CodeDom.Compiler.GeneratedCodeAttribute
("System.ServiceModel", "3.0.0.0")> _
Public Interface IMyServiceChannel
Inherits IMyService, System.ServiceModel.IClientChannel
End Interface

666
The Complete Reference To Professional SOA with Visual Studio 2005

<System.CodeDom.Compiler.GeneratedCodeAttribute
("System.ServiceModel", "3.0.0.0")> _
Partial Public Class MyServiceProxy
Inherits System.ServiceModel.ClientBase(Of IMyService)
Implements IMyService

Public Sub New()


MyBase.New
End Sub

Public Sub New(ByVal endpointConfigurationName As String)


MyBase.New(endpointConfigurationName)
End Sub

Public Sub New(ByVal endpointConfigurationName As String,


ByVal remoteAddress As String)
MyBase.New(endpointConfigurationName, remoteAddress)
End Sub
.
.
.
End Class

In listing 16-21 and listing 16-22, the proxy created above contains the EmployeeContactDataContract
datacontract we had specified in our WCF service. We can store the values within the properties of the proxy so
that when the EmployeeContactDataContract is sent back across the wire System.Runtime.Serialization will take
care of serializing the object for us.
Using SvcUtil will also produce an output.config file see listing 16-23 below which we can later rename to
app.config. This configuration specifies the WCF service’s binding requirements. These include things like
transaction, buffersize, encoding type, max message size, reliable session and security.
The configuration also contains an endpoint element which specifies the address and the binding of the
WCF service that we need to access. Note that each endpoint is given a name so that we can programmatically
assign each endpoint to a client application to use. The svcutil has automatically assigned the name of
WSHttpBinding_IMyService to our endpoint we will specify this name within our client code later to invoke the
service.
<endpoint address="http://localhost:27771/EmployeeDetailService/Service.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IMyService"
contract="IMyService" name="WSHttpBinding_IMyService" />

Listing 16-23. Shows the full out.config file that is generated from svcutil

<?xml version="1.0" encoding="utf-8"?>


<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IMyService"
bypassProxyOnLocal="false"
transactionFlow="false"
hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288"

667
The Complete Reference To Professional SOA with Visual Studio 2005

maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32"
maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096"
maxNameTableCharCount="16384" />
<reliableSession ordered="true"
inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Message">
<transport clientCredentialType="None"
proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows"
negotiateServiceCredential="true"
algorithmSuite="Default"
establishSecurityContext="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:27771/
EmployeeDetailService/Service.svc"
binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IMyService"
contract="IMyService"
name="WSHttpBinding_IMyService" />
</client>
</system.serviceModel>
</configuration>

Once the MyService.cs file and the output.config file have been generated be sure to rename output.config
to app.config and include the two files into the client project.

Listing 16-24. Demonstrates implementing the WCF client using Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
namespace ContactClient
{
class Program
{
static void Main(string[] args)
{
MyServiceProxy proxy =
new MyServiceProxy("WSHttpBinding_IMyService");
EmployeeContactDataContract contactDC =
proxy.RetrieveEmployeeContact(1);

668
The Complete Reference To Professional SOA with Visual Studio 2005

//retrieve Contact details


Console.WriteLine("############***Retrieved Contact***######");
DisplayContact(contactDC);

//update Contact details


contactDC.FirstName = "John";
contactDC.MiddleName = "Smith";
contactDC.LastName = "Doe";
proxy.UpdateEmployeeContact(contactDC);
Console.WriteLine("############***Updated Contact***######");
DisplayContact(contactDC);
Console.ReadLine();
}

private static void DisplayContact


(EmployeeContactDataContract contactDC)
{
Console.WriteLine("ContactID: " + contactDC.ContactID);
Console.WriteLine("Title: " + contactDC.Title);
Console.WriteLine("FirstName: " + contactDC.FirstName);
Console.WriteLine("MiddleName: " + contactDC.MiddleName);
Console.WriteLine("LastName: " + contactDC.LastName);
}
}
}

Listing 16-25. Demonstrates implementing the WCF client using Visual Basic

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.ServiceModel

Namespace VBContactClient
Module Module1

Sub Main()
Dim proxy As MyServiceProxy = _
New MyServiceProxy("WSHttpBinding_IMyService")
Dim contactDC As EmployeeContactDataContract _
= proxy.RetrieveEmployeeContact(1)
Console.WriteLine("############***Retrieved Contact***######")
DisplayContact(contactDC)
contactDC.FirstName = "John"
contactDC.MiddleName = "Smith"
contactDC.LastName = "Doe"
proxy.UpdateEmployeeContact(contactDC)
Console.WriteLine("############***Updated Contact***######")
DisplayContact(contactDC)
Console.ReadLine()

669
The Complete Reference To Professional SOA with Visual Studio 2005

End Sub

Private Sub DisplayContact _


(ByVal contactDC As EmployeeContactDataContract)
Console.WriteLine("ContactID: " + contactDC.ContactID.ToString())
Console.WriteLine("Title: " + contactDC.Title)
Console.WriteLine("FirstName: " + contactDC.FirstName)
Console.WriteLine("MiddleName: " + contactDC.MiddleName)
Console.WriteLine("LastName: " + contactDC.LastName)
End Sub

End Module
End Namespace

Tip: The WCF service is ran through using the ASP.NET Development Server. As a result the port number may vary. If you’re using the
sourcecode with this book you might need to adjust the port number for the client application to work.

VB.NET requires fully qualified name for contract.


<endpoint address="http://localhost:27771/
EmployeeDetailService/Service.svc"
binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IMyService"
contract="IMyService"
name="WSHttpBinding_IMyService" />
We will need to change the contract to contract="VBContactClient.IMyService" in order to for VB.NET client
to work. Where VBContactClient is the name of our VB Client Project.
We also need to add reference to System.Runtime.Serialization. This is part of the .NET Framework 3.0 and
is required by the proxy to serialize data to and from the servce.

Figure 16-6. Add reference to System.Runtime.Serialization

670
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 16-7. Shows the result from the client execution

Implementing Hosting
Windows Communication Foundation supports self-hosting and web hosting. Self hosting refers to the
application being able to be hosted within any of the .NET applications without the reliance on IIS this is very
similar to .NET Remoting. While Web hosting refers to hosting the WCF service application in Internet
Information Services (IIS). The onus is on the developer to pick the right hosting model for the right application.
It is important to note that WCF services aren’t tied to a specific application model and can support self-hosted
to remotely hosted scenarios.
In order to implement hosting we need to develop our service in a class library instead of using WinFX
Service. Create a new console application by File-> New->Project chose the preferred language and then select
Class Library from under Templates.

671
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 16-8. Create a new Class Library

Add a reference to the System.ServiceModel .NET assembly as well as the System.Runtime.Serialization


assembly to the project. For this example we will be using similar service code to what we had used in the
previous example.

Listing 16-26. Demonstrates service code within the class library using Visual C#

using System;
using System.ServiceModel;
using System.Runtime.Serialization;
using System.Data.SqlClient;
using System.Configuration;
using System.Data;

[ServiceContract()]
public interface IMyService
{
[OperationContract]
EmployeeContactDataContract RetrieveEmployeeContact(int EmployeeID);
[OperationContract]
void UpdateEmployeeContact(EmployeeContactDataContract dataContractValue);
}

public class MyService : IMyService


{
SqlConnection sqlcon =
new SqlConnection ("Data Source=localhost;" +
"Initial Catalog=AdventureWorks;Persist Security Info=True;" +
"User ID=Book;Password=Book");

public EmployeeContactDataContract
RetrieveEmployeeContact(int ContactID)
{
// retrieve employee contact details
string sql = String.Format
("select ContactID, Title, FirstName, MiddleName, LastName" +
" from Person.Contact where ContactID = {0}", ContactID);
SqlCommand sqlcmd = new SqlCommand(sql, sqlcon);

sqlcon.Open();
SqlDataReader dreader = sqlcmd.ExecuteReader();
dreader.Read();

EmployeeContactDataContract contactDC =
new EmployeeContactDataContract();
contactDC.ContactID = (int)dreader["ContactID"];
contactDC.Title = dreader["Title"].ToString();
contactDC.FirstName = dreader["FirstName"].ToString();
contactDC.MiddleName = dreader["MiddleName"].ToString();
contactDC.LastName = dreader["LastName"].ToString();
sqlcon.Close();
return contactDC;

672
The Complete Reference To Professional SOA with Visual Studio 2005

public void UpdateEmployeeContact(EmployeeContactDataContract ContactDC)


{
sqlcon.Open();
SqlTransaction transaction =
this.sqlcon.BeginTransaction("ContactTran");

SqlCommand sqlcmdEmployee = new SqlCommand(


@"update Person.Contact set
FirstName = @FirstName,
MiddleName = @MiddleName,
LastName = @LastName
where Person.Contact.ContactID = @ContactID;", sqlcon);
sqlcmdEmployee.Transaction = transaction;
sqlcmdEmployee.Parameters.Add
("@ContactID", SqlDbType.Int, sizeof(int)).Value =
ContactDC.ContactID;
sqlcmdEmployee.Parameters.Add
("@FirstName", SqlDbType.VarChar, 50).Value =
ContactDC.FirstName;
sqlcmdEmployee.Parameters.Add
("@MiddleName", SqlDbType.VarChar, 50)
.Value = ContactDC.MiddleName;
sqlcmdEmployee.Parameters.Add
("@LastName", SqlDbType.VarChar, 50).Value = ContactDC.LastName;

sqlcmdEmployee.ExecuteNonQuery();
transaction.Commit();
sqlcon.Close();
}
}

[DataContract]
public class EmployeeContactDataContract
{
private string title;
private string firstName;
private string middleName;
private string lastName;
private int contactID;

[DataMember]
public int ContactID
{
get { return contactID; }
set { contactID = value; }
}

[DataMember]
public string Title
{

673
The Complete Reference To Professional SOA with Visual Studio 2005

get { return title; }


set { title = value; }
}

[DataMember]
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}

[DataMember]
public string MiddleName
{
get { return middleName; }
set { middleName = value; }
}

[DataMember]
public string LastName
{
get { return lastName; }
set { lastName = value; }
}
}

Listing 16-27. Demonstrates service code within the class library using Visual Basic .NET

Imports System
Imports System.ServiceModel
Imports System.Runtime.Serialization
Imports System.Data.SqlClient
Imports System.Configuration
Imports System.Data

<ServiceContract()> _
Public Interface IMyService

<OperationContract()> _
Function RetrieveEmployeeContact _
(ByVal EmployeeID As Integer) As EmployeeContactDataContract

<OperationContract()> _
Sub UpdateEmployeeContact _
(ByVal dataContractValue As EmployeeContactDataContract)
End Interface

Public Class MyService


Implements IMyService
Private sqlcon As SqlConnection = New SqlConnection _
("Data Source=localhost;Initial Catalog=AdventureWorks;" + _
"Persist Security Info=True;" + "User ID=Book;Password=Book")

674
The Complete Reference To Professional SOA with Visual Studio 2005

Public Function RetrieveEmployeeContact _


(ByVal ContactID As Integer) As EmployeeContactDataContract _
Implements IMyService.RetrieveEmployeeContact
Dim sql As String = _
String.Format("select ContactID, Title, FirstName," + _
" MiddleName, LastName from Person.Contact " + _
"where ContactID = {0}", ContactID)
Dim sqlcmd As SqlCommand = New SqlCommand(sql, sqlcon)
sqlcon.Open()
Dim dreader As SqlDataReader = sqlcmd.ExecuteReader
dreader.Read()
Dim contactDC As EmployeeContactDataContract = _
New EmployeeContactDataContract
contactDC.ContactID = CType(dreader("ContactID"), Integer)
contactDC.Title = dreader("Title").ToString
contactDC.FirstName = dreader("FirstName").ToString
contactDC.MiddleName = dreader("MiddleName").ToString
contactDC.LastName = dreader("LastName").ToString
sqlcon.Close()
Return contactDC
End Function

Public Sub UpdateEmployeeContact _


(ByVal ContactDC As EmployeeContactDataContract) _
Implements IMyService.UpdateEmployeeContact
sqlcon.Open()
Dim transaction As SqlTransaction = _
Me.sqlcon.BeginTransaction("ContactTran")
Dim sqlcmdEmployee As SqlCommand = _
New SqlCommand("update Person.Contact set FirstName = " + _
"@FirstName, MiddleName = @MiddleName, LastName = @LastName " + _
" where Person.Contact.ContactID = @ContactID;", sqlcon)
sqlcmdEmployee.Transaction = transaction
sqlcmdEmployee.Parameters.Add("@ContactID", _
SqlDbType.Int).Value = ContactDC.ContactID
sqlcmdEmployee.Parameters.Add("@FirstName", _
SqlDbType.VarChar, 50).Value = ContactDC.FirstName
sqlcmdEmployee.Parameters.Add("@MiddleName", _
SqlDbType.VarChar, 50).Value = ContactDC.MiddleName
sqlcmdEmployee.Parameters.Add("@LastName", _
SqlDbType.VarChar, 50).Value = ContactDC.LastName
sqlcmdEmployee.ExecuteNonQuery()
transaction.Commit()
sqlcon.Close()
End Sub
End Class

<DataContract()> _
Public Class EmployeeContactDataContract
Private _title As String
Private _firstName As String
Private _middleName As String

675
The Complete Reference To Professional SOA with Visual Studio 2005

Private _lastName As String


Private _contactID As Integer

<DataMember()> _
Public Property ContactID() As Integer
Get
Return _contactID
End Get
Set(ByVal value As Integer)
_contactID = value
End Set
End Property

<DataMember()> _
Public Property Title() As String
Get
Return _title
End Get
Set(ByVal value As String)
_title = value
End Set
End Property

<DataMember()> _
Public Property FirstName() As String
Get
Return _firstName
End Get
Set(ByVal value As String)
_firstName = value
End Set
End Property

<DataMember()> _
Public Property MiddleName() As String
Get
Return _middleName
End Get
Set(ByVal value As String)
_middleName = value
End Set
End Property

<DataMember()> _
Public Property LastName() As String
Get
Return _lastName
End Get
Set(ByVal value As String)
_lastName = value
End Set
End Property
End Class

676
The Complete Reference To Professional SOA with Visual Studio 2005

Once complete build the class library to ensure that it builds without error. Now we will add a console
application project to the solution. Add a VB Console Application to the current project. File->Add->New
Project Select the language then Console Application under templates. We will call this new project Host.

Tip: we’re not limited to only console applications; we can host the WCF service in any windows application.

Also add the reference to the System.ServiceModel .NET assembly as well as the
System.Runtime.Serialization assembly to the project.
Once the .NET references have been added, add another reference to the service library we had just created
above.

Figure 16-9. Add reference to ServiceLibrary project

In the console application we have just created we will create a host environment so that every time the
console application is run our WCF service will also start running.

Listing 16-28. Demonstrates host implementation in Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;

namespace Host
{
class Program
{
static void Main(string[] args)
{
Type serviceType = typeof(MyService);
string httpBaseAddress = "http://localhost:8020/Contact";
string tcpBaseAddress = "net.tcp://localhost:8021/Contact";
Uri httpBaseAddressUri = new Uri(httpBaseAddress);

677
The Complete Reference To Professional SOA with Visual Studio 2005

Uri tcpBaseAddressUri = new Uri(tcpBaseAddress);

Uri[] baseAddresses = new Uri[] {


httpBaseAddressUri,
tcpBaseAddressUri
};

using (ServiceHost host = new ServiceHost(


serviceType, baseAddresses))
{
BasicHttpBinding httpbinding = new BasicHttpBinding();
NetTcpBinding tcpbinding = new NetTcpBinding();
host.AddServiceEndpoint(typeof(IMyService), httpbinding,
httpBaseAddress);
host.AddServiceEndpoint(typeof(IMyService), tcpbinding,
tcpBaseAddress);
host.Open();
Console.WriteLine("WCF service start");
Console.ReadLine();
host.Close();
}
}
}
}

Listing 16-29. Demonstrates host implementation in Visual Basic .NET

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.ServiceModel
Imports VBHost
Namespace Host

Class Program

Shared Sub Main(ByVal args As String())


Dim serviceType As Type = GetType(VBServiceLibrary.MyService)
Dim httpBaseAddress As String = "http://localhost:8020/Contact"
Dim tcpBaseAddress As String = "net.tcp://localhost:8021/Contact"
Dim httpBaseAddressUri As Uri = New Uri(httpBaseAddress)
Dim tcpBaseAddressUri As Uri = New Uri(tcpBaseAddress)
Dim baseAddresses As Uri() = New Uri() {httpBaseAddressUri, _
tcpBaseAddressUri}
' Using
Dim host As ServiceHost = New ServiceHost(serviceType, _
baseAddresses)
Try
Dim httpbinding As BasicHttpBinding = New BasicHttpBinding
Dim tcpbinding As NetTcpBinding = New NetTcpBinding
host.AddServiceEndpoint _
(GetType(VBServiceLibrary.IMyService), _

678
The Complete Reference To Professional SOA with Visual Studio 2005

httpbinding, httpBaseAddress)
host.AddServiceEndpoint _
(GetType(VBServiceLibrary.IMyService), _
tcpbinding, tcpBaseAddress)
host.Open()
Console.WriteLine("WCF service start")
Console.ReadLine()
host.Close()
Finally
CType(host, IDisposable).Dispose()
End Try
End Sub
End Class
End Namespace

In the above listing the hosting code is placed inside the Main method of the console application. Whenever
the console application runs the WCF service will startup with the application. We first create an array of Uris
these are what we intend to use as the end point addresses. We have specified both a HTTP location as well as a
TCP location.
string tcpBaseAddress = "net.tcp://localhost:8021/Contact";

or for Visual Basic .NET


Dim tcpBaseAddress As String = "net.tcp://localhost:8021/Contact"
Therefore, this service allows consumers to communicate with it over either HTTP or TCP using different
WS-* protocols, as defined by each binding.
We then create the hosting environment by specifying the bindings that are required. In this example we will
be opening both a HTTP binding and a TCP binding this is achieved through the code below.

Listing 16-30. binding the service using Visual C#

BasicHttpBinding httpbinding = new BasicHttpBinding();


NetTcpBinding tcpbinding = new NetTcpBinding();
host.AddServiceEndpoint(typeof(IMyService), httpbinding,
httpBaseAddress);
host.AddServiceEndpoint(typeof(IMyService), tcpbinding,
tcpBaseAddress);

Listing 16-31. binding the service using Visual Basic .NET

Dim httpbinding As BasicHttpBinding = New BasicHttpBinding


Dim tcpbinding As NetTcpBinding = New NetTcpBinding
host.AddServiceEndpoint(GetType(VBServiceLibrary.IMyService), _
httpbinding, httpBaseAddress)
host.AddServiceEndpoint(GetType(VBServiceLibrary.IMyService), _
tcpbinding, tcpBaseAddress)
Finally we open the WCF service using host.Open() this will open the connection on both the HTTP port
8020 as well as the TCP port 8021.

679
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 16-10. Viewing the service.

By browsing to the location of our HTTP binded endpoint we can view the service running (see figure 16-
10. above). We can also view the WSDL generated by this service simply by adding the traditional “?wsdl” at
the end of the service name. For example:
http://localhost:8020/contact?wsdl

680
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 16-11. WSDL document generated by theWCF service

Similarly we can also view the discovery document by adding a “?disco” at the end of the service name. For
example: http://localhost:8020/contact?disco

Figure 16-12. Discovery document

The ability to host a WCF application within any windows application adds a great deal of flexibility. We
can create a windows service application that will start running every windows starts up.

681
The Complete Reference To Professional SOA with Visual Studio 2005

Implementing Secure Reliabable Messaging


One of the biggest challenges in developing for Service-Oriented Architecture is maintaining reliability for
mission-critical applications. This is because of the nature of unreliable network transports, such as HTTP, and
the lack of reliable message delivery.Actually no matter what protocol is used there is some chance that
something will go down with a network cable or intermediary while a message is en-route. The only way around
this is to re-send the message after the network is back up. If the network problem occurs while the sender is the
middle of sending the message then it knows it was not received and it can re-send it. But if it occurs while the
responder is replying (or before it starts replying) then there is some ambiguity about whether the responder was
about to report successful acceptance or failure, or whether the responder got the message properly at all.
However by adopting a reliable messaging specification for Web services and adding reliability headers into
SOAP messages, Web services can be used for a broader range of applications, and application development can
be dramatically simplified. See Chapter 2 for theories behind reliability.
Reliability for Web services is defined independently of the transport as a series of SOAP messages
exchanged within a group or sequence and some processing rules governing the use of acknowledgements and
message numbers to ensure that all the messages are received, duplicates are eliminated, and that message
ordering is preserved. Of course, Web service reliability does only refer to messaging. Security, transactions and
execution environments such as clustering and redundant storage all have an impact on reliability.
Reliable messaging technology requires a piece of software infrastructure deployed on both ends of
connections. The reliability-messaging agent handles errors in the transmission of messages from one computer
to another over a potentially unreliable network. Typically the agents are symmetrical implementations so that
mutual handshakes can be implemented.
By implementing Windows Communication Foundation we can implement Web service reliability
seamlessly. We can achieve this fairly easily by specifying ReliableSessionEnabled in our binding configuraion.
WCF comes with Microsoft Service Configuration Editor (SvcConfigEditor.exe) this tool helps to simplify WCF
configurations (see figure 16-13 below).

Figure 16-13. Microsoft Service Configuration Editor

682
The Complete Reference To Professional SOA with Visual Studio 2005

In the following example we will specify reliableSession using the WCF Contact Service example we had
created earlier.
Open the EmployeeDetailService, simply select the configuration file in the solution explorer in our case the
Web.config file. Right mouse click and there is a new menu selection Edit WCF Configuration this is a menu
option that is added after installing the WinFX windows SDK. Click on the selection.

Figure 16-14. Microsoft Service Configuration Editor

This will bring up the Microsoft Service Configuration Editor, expand the Advanced section and right click
on Binding to bring up the “Create a New Binding…” context menu.

Figure 16-15. Creating a new binding.

683
The Complete Reference To Professional SOA with Visual Studio 2005

Selecting the Create a New Binding will bring up a “Create a New Binding” dialog window. Select
wsHttpBinding, since we will be communicating via HTTP and we also want to specify reliable messaging this
is required.
Click OK once complete

Figure 16-16. Select a New Binding

This will add a new wsHttpBinding node under Bindings. Select the name attribute under configuration and
change the name from NewBinding to reliableBinding. Then under ReliableSession Properties change Enabled
from False to True.

684
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 16-17. Enabling Reliable Session.

Then select the endpoint node which by default has the (Empty Name) change the name element under
General from blank to reliableEndpoint and under the BindingConfiguration use the dropdown list to specify
reliableBinding.

Figure 16-18. Specifying reliableEndpoint

685
The Complete Reference To Professional SOA with Visual Studio 2005

Select the File menu -> Save to commit the changes to Web.config file.

Listing 16-32. Web.config file

<?xml version="1.0"?>

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<appSettings>
<add key="ConnectionString"
value="Data Source=localhost;Initial Catalog=AdventureWorks;
Persist Security Info=True;User ID=Book;Password=Book" />
</appSettings>

<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="reliableBinding">
<reliableSession enabled="true" />
</binding>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="returnFaults" name="MyService">
<endpoint binding="wsHttpBinding"
bindingConfiguration="reliableBinding"
name="reliableEndpoint" contract="IMyService" />
</service>
</services>
<behaviors>
<behavior name="returnFaults" returnUnknownExceptionsAsFaults="true" />
</behaviors>
</system.serviceModel>

<system.web>
<compilation debug="true"/>
</system.web>

</configuration>

By completing the above steps we have created a service which uses reliable session. As reliability is a two
way operation we will also need to do the same for the client side application. Open the ContactClient
application in Visual Studio. Select app.config in the solution explorer right mouse click to bring the “Edit WCF
Configuration” menu. Select it. The difference between client and server configuration is that the binding and
endpoint for the client has already been specified. This is because when we generated the client proxy using
SvcUtil.exe the utility has already automatically created the binding and endpoint configuration for us. So it is
just a simple matter of selecting the existing binding and under ReliableSession Properties change the Enabled
attribute from False to True.

686
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 16-19. Enable reliableSession on client

Select File->Save to commit the changes to app.config file.

Listing 16-33. The App.config file

<?xml version="1.0" encoding="utf-8"?>


<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IMyService">
<readerQuotas maxDepth="32"
maxStringContentLength="8192"
maxArrayLength="16384"
maxBytesPerRead="4096"
maxNameTableCharCount="16384" />
<reliableSession enabled="true" />
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint
address="http://localhost:27771/
EmployeeDetailService/Service.svc"
binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IMyService"

687
The Complete Reference To Professional SOA with Visual Studio 2005

contract="IMyService"
name="WSHttpBinding_IMyService" />
</client>
</system.serviceModel>
</configuration>

Implementing Custom Binding, Reliable Messaging and Security


Usually it is quite difficult to implement security and reliability together. One of the issues we face is that we
may have very little control over how the messages are handled at each endpoint. We generally need to create a
lot of custom code to implement a custom encryption scheme to make it work. Cross-platform security adds
another layer of complexity. WCF provides solid tools to implement reliable secure communication. And even
more surprising, it’s dead easy to set up. We will be using the Microsoft Service Configuration Editor
(SvcConfigEditor.exe) to help us with the configuration.
In the following example we will specify Custom binding with security and reliableSession using the WCF
Contact Service example we had created earlier.
Open the EmployeeDetailService, simply select the configuration file in the solution explorer in our case the
Web.config file. Right mouse click and there is a new menu selection “Edit WCF Configuration” this is a menu
option that is added after installing the WinFX windows SDK. Click on the selection.
This will bring up the Microsoft Service Configuration Editor, expand the Advanced section and right click
on Binding to bring up the “Create a New Binding…” context menu.

Figure 16-20. Creating a new binding.

Selecting the Create a New Binding will bring up a “Create a New Binding” dialog window. Select
customBinding, this is required as we need to select reliable session.

688
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 16-21. customBinding.

Selecting this the customBinding will create a new node under Bindings called NewBinding. Right mouse
click this new binding and select the “Add Binding Element Extension(s)…” option.

689
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 16-22. Add a Binding Element

Selecting the option will bring up the “Adding Binding Element Extensions Sections” simply select
reliableSession and click Add.

Figure 16-23. Adding Binding Element Extension

By adding the reliableSession element to the binding we now have a new node under NewBinding called
reliableSession.

690
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 16-24. reliableSession

The default values for reliableSession are shown below in the table.

Table 16-2. Default values


Attributes Value
AcknowledgementInterval
00:00:00.2000000
EnableFlowControl
True
MaxTransferWindowSize
32
InactivityTimeout
00:10:00
MaxPendingChannels
128
MaxRetryCount
8
Ordered
True

We will leave the default values as they are. This will create the reliableSession element. Because the values
are default the element that will be created will only be a single element of <reliableSession /> however
alternatively we could also specify each attribute as shown below:
<reliableSession acknowledgementInterval="00:00:00.2000000"
enableFlowControl="true" maxTransferWindowSize="32"
inactivityTimeout="00:10:00" maxPendingChannels="128"
maxRetryCount="8" ordered="true" />
We also need to adjust the customBinding as by default the transport mode is set to tcpTransport. To change
this right mouse click on the tcpTransport select Remove Extension.

691
The Complete Reference To Professional SOA with Visual Studio 2005

Select the NewBinding(customBinding) node and change the Name to reliableBinding. Then right mouse
click on reliableBinding select “Add Binding Element…” and select httpTransport. This will add httpTransport
as our selected mode for communication.

Figure 16-25. Select httpTransport

Click Add to add the httpTransport Binding.

Now that we have established a new binding we need to attach the binding to our endpoint specified in the
configuration. We will start by renaming our Binding. To do this simply select the NewBinding node and change
the Name element to reliableBinding.

Figure 16-26. Renaming the binding.

692
The Complete Reference To Professional SOA with Visual Studio 2005

We also need to add security to this customBinding. To do this right click on reliableBinding click on “Add
Binding Element Extension(s)”. Select security and click Add.

Figure 16-27. Adding Security Extension

By adding the security extension. A new node under customBinding will appear. Security properties can be
easily configured through the Service Configuration Editor. For the purpose of this example we will leave them
as they are.

693
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 16-28. Illustrates security properties

Now we need to attach the binding to our endpoint. By default there is an end point specified under
MyServie without a name. Give it the name of reliableEndpoint. The binding element for reliableEndpoint
defaults to wsHttpBinding simply select customBinding from the drop down list see figure below.

Figure 16-29. Selecting Binding Type

Selecting the customBinding option will result in the BindingConfiguration being automatically filled in.

694
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 16-30. Setting Binding Configuration

Select File-> Save to commit the changes to the Web.config file.

Listing 16-34. Web.config file

<?xml version="1.0"?>

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<appSettings>
<add key="ConnectionString"
value="Data Source=localhost;Initial Catalog=AdventureWorks;
Persist Security Info=True;User ID=Book;Password=Book" />
</appSettings>

<system.serviceModel>
<bindings>
<customBinding>
<binding name="reliableBinding">
<textMessageEncoding />
<reliableSession />
<security>
<issuedTokenParameters>
<issuer address="" />
<issuerMetadata address="" />
</issuedTokenParameters>
<secureConversationBootstrap />
</security>
<httpTransport />

695
The Complete Reference To Professional SOA with Visual Studio 2005

</binding>
</customBinding>
</bindings>
<services>
<service behaviorConfiguration="returnFaults" name="MyService">
<endpoint binding="customBinding"
bindingConfiguration="reliableBinding"
name="reliableEndpoint" contract="IMyService" />
</service>
</services>
<behaviors>
<behavior name="returnFaults"
returnUnknownExceptionsAsFaults="true" />
</behaviors>
</system.serviceModel>

<system.web>
<compilation debug="true"/>
</system.web>

</configuration>

Now we will have successfully enabled a reliable session for our service. Reliability needs to be
implemented on both ends so we will need to do the same for our client application. The only exception being
that instead of specifying the endpoint under Services specify it under Client.

Figure 16-31. Client configuration.

696
The Complete Reference To Professional SOA with Visual Studio 2005

Listing 16-35. Demonstrates the App.config file

<?xml version="1.0" encoding="utf-8"?>


<configuration>
<system.serviceModel>
<bindings>
<customBinding>
<binding name="reliableBinding">
<textMessageEncoding />
<reliableSession />
<security>
<issuedTokenParameters>
<issuer address="" />
<issuerMetadata address="" />
</issuedTokenParameters>
<secureConversationBootstrap />
</security>
<httpTransport />
</binding>
</customBinding>
<wsHttpBinding>
<binding name="WSHttpBinding_IMyService">
<readerQuotas maxDepth="32"
maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096"
maxNameTableCharCount="16384" />
<reliableSession enabled="true" />
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint
address="http://localhost:2304/EmployeeDetailService/Service.svc"
binding="customBinding"
bindingConfiguration="reliableBinding"
contract="IMyService" name="WSHttpBinding_IMyService" />
</client>
</system.serviceModel>
</configuration>

One thing to note is that the order of which the Extensions are executed are important. With Service
Configuration Editor its quite easy to change the ordering of these extensions. If any extensions are out of sync
between the client and the server then the two can not communicate. We should also always move security
towards the lower end position of execution so that security can include higher level operations.

697
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 16-32. Illustrates Binding Extension Position

Implementing WCF with Microsoft Message Queue


Microsoft Message Queue (MSMQ) is a service that allows applications to send messages to one another
asynchronously. The benefit of using MSMQ is that the message does not have to be immediately processed.
The message can reside on the queue until the receiving service is free and the message is then retrieved from the
queue for processing. MSMQ is thus ideal for situations where response is not time critical. A message can be
anything from an array of bytes, to strings, to binary data, and so on. We should be aware that an asynchronous
message is not the same thing as an asynchronous method call. MSMQ is a really collection of COM objects that
developers can use to send information, in the form of a message, from point A to point B asynchronously with a
guarantee of delivery. MSMQ is regarded by many developers as middleware because it acts as a middle-tier
message delivery mechanism that developers can leverage to send information from one application to another.
MSMQ has the following benefits over traditional HTTP or TCP messaging:

* Guaranteed message delivery (if requested).

* Asynchronous message delivery. The sender and recipient do not need to be running at the same time.
* Message logging services. A journal of all messages sent can be recorded and stored for later review.

* Security. Access permission can be set on queues and the message bodies themselves can automatically be
encrypted.

WCF has the ability to bind with Microsoft Message Queue. This allows us to develop infrastructures to
create queued channels. Using queues can be particularly important in distributed systems where services can get
bogged down with one-way requests. Rather than rejecting requests it is a good idea to store them away so that
they can be processed at a later time.

698
The Complete Reference To Professional SOA with Visual Studio 2005

In this section we will be implementing a client purchase ordering system using Microsoft Message Queue.
To support implementing MSMQ we need to first install it on our system. This can be done by choosing “Add or
Remove Programs from the Windows Control panel”. Then click “Add/Remove Windows Components”.
Browse to “Application Server” in the Windows Components Wizard window as shown below and click on the
details button.

TIP: Under Windows XP Simply browse to Message Queuing

Figure 16-33. The Windows Components Wizard

If the Message Queuing is not checked in the Application Server window, as shown below. Then check it,
and click on the OK button and then on the Next button in the Windows Components Wizard and follow the
instruction son the subsequent screens to install MSMQ.

699
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 16-34. Application Server Components

Now to create the order processing service first create a Console application called MSMQ. The
implementation is shown below:

Listing 16-36. Server implementation using Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Messaging;
using System.Configuration;

namespace MSMQ
{
class Program
{
static void Main(string[] args)
{
if (!MessageQueue.Exists
(ConfigurationManager.AppSettings["queueName"]))
MessageQueue.Create
(ConfigurationManager.AppSettings["queueName"], true);

//Connect to the queue


MessageQueue Queue = new MessageQueue
(ConfigurationManager.AppSettings["queueName"]);

Queue.ReceiveCompleted +=
new ReceiveCompletedEventHandler(ProcessOrder);
Queue.BeginReceive();
Console.WriteLine("Order Service is running");
Console.ReadLine();
}

public static void ProcessOrder


(Object source, ReceiveCompletedEventArgs asyncResult)
{
try
{
// Connect to the queue.
MessageQueue Queue = (MessageQueue)source;
// End the asynchronous receive operation.
System.Messaging.Message msg =
Queue.EndReceive(asyncResult.AsyncResult);
msg.Formatter = new System.Messaging.XmlMessageFormatter
(new Type[] { typeof(PurchaseOrder) });
PurchaseOrder po = (PurchaseOrder)msg.Body;
Random statusIndexer = new Random();
po.Status = (OrderStates)statusIndexer.Next(3);
Console.WriteLine("Processing {0} ", po);

700
The Complete Reference To Professional SOA with Visual Studio 2005

Queue.BeginReceive();
}
catch (System.Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}

Listing 16-37. Server implementation using Visual Basic .NET

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Messaging
Imports System.Configuration

Imports Order.MSMQ

Namespace MSMQ

Class Program

Shared Sub Main(ByVal args As String())


If Not MessageQueue.Exists _
(ConfigurationManager.AppSettings("queueName")) Then
MessageQueue.Create _
(ConfigurationManager.AppSettings("queueName"), True)
End If
Dim Queue As MessageQueue = New MessageQueue _
(ConfigurationManager.AppSettings("queueName"))
AddHandler Queue.ReceiveCompleted, AddressOf ProcessOrder
Queue.BeginReceive()
Console.WriteLine("Order Service is running")
Console.ReadLine()
End Sub

Public Shared Sub ProcessOrder(ByVal source As Object, _


ByVal asyncResult As ReceiveCompletedEventArgs)
Try
Dim Queue As MessageQueue = CType(source, MessageQueue)
Dim msg As System.Messaging.Message = _
Queue.EndReceive(asyncResult.AsyncResult)
msg.Formatter = New System.Messaging.XmlMessageFormatter _
(New Type() {GetType(PurchaseOrder)})
Dim po As PurchaseOrder = CType(msg.Body, PurchaseOrder)
Dim statusIndexer As Random = New Random
po.Status = CType(statusIndexer.Next(3), __
MSMQ.OrderStates)
Console.WriteLine("Processing {0} ", po)
Queue.BeginReceive()

701
The Complete Reference To Professional SOA with Visual Studio 2005

Catch ex As System.Exception
Console.WriteLine(ex.Message)
End Try
End Sub
End Class
End Namespace

Listing 16-38. App.config

<?xml version="1.0" encoding="utf-8" ?>


<configuration>
<appSettings>
<!-- use appSetting to configure MSMQ queue name -->
<add key="queueName" value=".\private$\Orders" />
</appSettings>

</configuration>

Figure 16-35. Example architecture

Figure 16-35 demonstrates a disconnected architecture. Messages arrive at the message queue regardless of
whether the Server side services are up or down. As each Order Processing Service becomes available. The order
processing service application will receive orders as they come in to the queue. The orders will be processed
immediately but if the order processing service is down then the queue will hold the order until the service is up
again.
In listing 16-36 and listing 16-37 we first check to see if the Microsoft Message Queue exists using the
MessageQueue class within the System.Messaging namespace. If it does not exist then we will create a mesasge
queue on the server.

Listing 16-39. Creating queue in Visual C#

if (!MessageQueue.Exists

702
The Complete Reference To Professional SOA with Visual Studio 2005

(ConfigurationManager.AppSettings["queueName"]))
MessageQueue.Create
(ConfigurationManager.AppSettings["queueName"], true);

Listing 16-40. Creating queue in Visual Basic .NET

If Not MessageQueue.Exists _
(ConfigurationManager.AppSettings("queueName")) Then
MessageQueue.Create _
(ConfigurationManager.AppSettings("queueName"), True)
Once we have established that the queue on the server exists then we can connect to it. We need to add an
event to the ReceiveCompleted event. This is so that when MSMQ has completed receiving a message into the
queue we want to be notified and we want the method ProcessOrder to be executed.

Listing 16-41. Implementing ReceiveCompleted event in Visual C#

MessageQueue Queue = new MessageQueue


(ConfigurationManager.AppSettings["queueName"]);

Queue.ReceiveCompleted += new ReceiveCompletedEventHandler(ProcessOrder);


Queue.BeginReceive();

Listing 16-42. Implementing ReceiveCompleted event in Visual Basic .NET

Dim Queue As MessageQueue = New MessageQueue _


(ConfigurationManager.AppSettings("queueName"))
AddHandler Queue.ReceiveCompleted, AddressOf ProcessOrder
Queue.BeginReceive()
The ProcessOrder function is called whenever the message queue receives a new message. To retrieve the
message we can use the EndReceive function to receive the message asynchronously. Not surprisingly, the
message itself is represented by an object on the queue. As such we need to cast the message back to
PurchaseOrder.

Listing 16-43. ProcessOrder using Visual C#

MessageQueue Queue = (MessageQueue)source;


// End the asynchronous receive operation.
System.Messaging.Message msg =
Queue.EndReceive(asyncResult.AsyncResult);
msg.Formatter = new System.Messaging.XmlMessageFormatter
(new Type[] { typeof(PurchaseOrder) });
PurchaseOrder po = (PurchaseOrder)msg.Body;
Random statusIndexer = new Random();
po.Status = (OrderStates)statusIndexer.Next(3);
Console.WriteLine("Processing {0} ", po);
Queue.BeginReceive();

Listing 16-43. ProcessOrder using Visual Basic .NET

Dim Queue As MessageQueue = CType(source, MessageQueue)


Dim msg As System.Messaging.Message = _
Queue.EndReceive(asyncResult.AsyncResult)
msg.Formatter = New System.Messaging.XmlMessageFormatter _
(New Type() {GetType(PurchaseOrder)})

703
The Complete Reference To Professional SOA with Visual Studio 2005

Dim po As PurchaseOrder = CType(msg.Body, PurchaseOrder)


Dim statusIndexer As Random = New Random
po.Status = CType(statusIndexer.Next(3), _
Order.MSMQ.OrderStates)
Console.WriteLine("Processing {0} ", po)
Queue.BeginReceive()
The service also uses an Order class library. This library is used to display information regarding the order.
The client uses the same library to send data to the message queue. The class is marked as serializable and such
the values contained in the class can be serialized and sent to the queue.

Listing 16-44. Shows implementing the order class using Visual C#

using System;
using System.Text;

namespace MSMQ
{
// Define the Purchase Order Line Item
[Serializable]
public class PurchaseOrderLineItem
{

public string productId;


public float unitCost;
public int quantity;

public override string ToString()


{
String displayString = "Order LineItem: " + quantity +
" of " + productId + " @unit price: $" +
unitCost + "\n";
return displayString;
}

public float TotalCost


{
get { return unitCost * quantity; }
}
}

public enum OrderStates


{
Pending,
Processed,
Shipped
}

// Define Purchase Order


[Serializable]
public class PurchaseOrder
{
public string poNumber;

704
The Complete Reference To Professional SOA with Visual Studio 2005

public string customerId;


public PurchaseOrderLineItem[] orderLineItems;
public OrderStates orderStatus;

public float TotalCost


{
get
{
float totalCost = 0;
foreach (PurchaseOrderLineItem lineItem in orderLineItems)
totalCost += lineItem.TotalCost;
return totalCost;
}
}

public OrderStates Status


{
get
{
return orderStatus;
}
set
{
orderStatus = value;
}
}

public override string ToString()


{
StringBuilder strbuf =
new StringBuilder("Purchase Order: " + poNumber + "\n");
strbuf.Append("\tCustomer: " + customerId + "\n");
strbuf.Append("\tOrderDetails\n");

foreach (PurchaseOrderLineItem lineItem in orderLineItems)


{
strbuf.Append("\t\t" + lineItem.ToString());
}

strbuf.Append("\tTotal cost of this order: $" +


TotalCost + "\n");
strbuf.Append("\tOrder status: " + Status + "\n");
return strbuf.ToString();
}
}
}

Listing 16-45. Shows implementing the order class using Visual Basic .NET

Imports System
Imports System.Text
Namespace MSMQ

705
The Complete Reference To Professional SOA with Visual Studio 2005

<Serializable()> _
Public Class PurchaseOrderLineItem
Public productId As String
Public unitCost As Single
Public quantity As Integer

Public Overloads Overrides Function ToString() As String


Dim displayString As String = "Order LineItem: " & _
quantity.ToString() & " of " & productId & _
" @unit price: $" & unitCost.ToString()
Return displayString
End Function

Public ReadOnly Property TotalCost() As Single


Get
Return unitCost * quantity
End Get
End Property
End Class

Public Enum OrderStates


Pending
Processed
Shipped
End Enum

<Serializable()> _
Public Class PurchaseOrder
Public poNumber As String
Public customerId As String
Public orderLineItems As PurchaseOrderLineItem()
Public orderStatus As OrderStates

Public ReadOnly Property TotalCost() As Single


Get
Dim _totalCost As Single = 0
For Each lineItem As PurchaseOrderLineItem In orderLineItems
_totalCost += lineItem.TotalCost
Next
Return _totalCost
End Get
End Property

Public Property Status() As OrderStates


Get
Return orderStatus
End Get
Set(ByVal value As OrderStates)
orderStatus = value
End Set
End Property

706
The Complete Reference To Professional SOA with Visual Studio 2005

Public Overloads Overrides Function ToString() As String


Dim strbuf As StringBuilder = New StringBuilder _
("Purchase Order: " & poNumber & Environment.NewLine)
strbuf.Append(ControlChars.Tab & "Customer: " & customerId _
& Environment.NewLine)
strbuf.Append(ControlChars.Tab & "OrderDetails" & _
Environment.NewLine)
For Each lineItem As PurchaseOrderLineItem In orderLineItems
strbuf.Append(ControlChars.Tab & ControlChars.Tab & _
lineItem.ToString())
Next
strbuf.Append(ControlChars.Tab & _
"Total cost of this order: $" & TotalCost & Environment.NewLine)
strbuf.Append(ControlChars.Tab & "Order status: " & _
Status & Environment.NewLine)
Return strbuf.ToString()
End Function
End Class
End Namespace

The client implementation is shown below.

Listing 16-46. Demonstrates client side implementation using Visual C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Transactions;
using System.ServiceModel.MsmqIntegration;
using System.ServiceModel;
using System.Messaging;

namespace MSMQ
{
class Program
{
static void Main(string[] args)
{
// Create the purchase order
PurchaseOrder po = new PurchaseOrder();
po.customerId = "xyz customer id";
po.poNumber = Guid.NewGuid().ToString();

PurchaseOrderLineItem lineItem1 =
new PurchaseOrderLineItem();
lineItem1.productId = "Blue Widget";
lineItem1.quantity = 10;
lineItem1.unitCost = 15.58F;

PurchaseOrderLineItem lineItem2 =
new PurchaseOrderLineItem();
lineItem2.productId = "Red Widget";

707
The Complete Reference To Professional SOA with Visual Studio 2005

lineItem2.quantity = 890;
lineItem2.unitCost = 45.89F;

po.orderLineItems = new PurchaseOrderLineItem[2];


po.orderLineItems[0] = lineItem1;
po.orderLineItems[1] = lineItem2;

using (OrderProcessorProxy orderProcessor =


new OrderProcessorProxy("OrderResponseEndpoint"))
{
//Set the correlation ID such that the client can
//correlate the response to the order
MsmqMessage<PurchaseOrder> ordermsg =
new MsmqMessage<PurchaseOrder>(po);
using (TransactionScope scope =
new TransactionScope(TransactionScopeOption.Required))
{
orderProcessor.SubmitPurchaseOrder(ordermsg);
scope.Complete();
}
Console.WriteLine("Order has been submitted:{0}", po);
}
Console.WriteLine();
Console.WriteLine("Press <ENTER> to terminate client.");
Console.ReadLine();
}
}
}

Listing 16-47. Demonstrates client side implementation using Visual Basic .NET

Imports System
Imports System.Text
Namespace MSMQ

<Serializable()> _
Public Class PurchaseOrderLineItem
Public productId As String
Public unitCost As Single
Public quantity As Integer

Public Overloads Overrides Function ToString() As String


Dim displayString As String = "Order LineItem: " & _
quantity.ToString() & " of " & productId & _
" @unit price: $" & unitCost.ToString()
Return displayString
End Function

Public ReadOnly Property TotalCost() As Single


Get
Return unitCost * quantity
End Get
End Property
End Class

708
The Complete Reference To Professional SOA with Visual Studio 2005

Public Enum OrderStates


Pending
Processed
Shipped
End Enum

<Serializable()> _
Public Class PurchaseOrder
Public poNumber As String
Public customerId As String
Public orderLineItems As PurchaseOrderLineItem()
Public orderStatus As OrderStates

Public ReadOnly Property TotalCost() As Single


Get
Dim _totalCost As Single = 0
For Each lineItem As PurchaseOrderLineItem In orderLineItems
_totalCost += lineItem.TotalCost
Next
Return _totalCost
End Get
End Property

Public Property Status() As OrderStates


Get
Return orderStatus
End Get
Set(ByVal value As OrderStates)
orderStatus = value
End Set
End Property

Public Overloads Overrides Function ToString() As String


Dim strbuf As StringBuilder = New StringBuilder _
("Purchase Order: " & poNumber & Environment.NewLine)
strbuf.Append(ControlChars.Tab & "Customer: " & customerId _
& Environment.NewLine)
strbuf.Append(ControlChars.Tab & "OrderDetails" & _
Environment.NewLine)
For Each lineItem As PurchaseOrderLineItem In orderLineItems
strbuf.Append(ControlChars.Tab & ControlChars.Tab & _
lineItem.ToString())
Next
strbuf.Append(ControlChars.Tab & _
"Total cost of this order: $" & TotalCost & Environment.NewLine)
strbuf.Append(ControlChars.Tab & "Order status: " & _
Status & Environment.NewLine)
Return strbuf.ToString()
End Function
End Class
End Namespace

709
The Complete Reference To Professional SOA with Visual Studio 2005

In the Client implementation the order is set before it is sent to the message queue. We will be relying on
WCF to send the message to the queue. By using the System.ServiceModel.MsmqIntegration.MsmqMessage. The
MsmqMessage class encapsulates an MSMQ message that is sent and received, over a MSMQ integration
channel, to and from an existing MSMQ application.

Listing 16-48. Implementing MsmqMessage using Visual C#

MsmqMessage<PurchaseOrder> ordermsg =
new MsmqMessage<PurchaseOrder>(po);
using (TransactionScope scope =
new TransactionScope(TransactionScopeOption.Required))
{
orderProcessor.SubmitPurchaseOrder(ordermsg);
scope.Complete();
}

Listing 16-49. Implementing MsmqMessage using Visual Basic .NET

Using orderProcessor As OrderProcessorProxy = New OrderProcessorProxy("OrderResponseEndpoint")


Dim ordermsg As MsmqMessage(Of PurchaseOrder) = New MsmqMessage(Of PurchaseOrder)(po)
Using scope As TransactionScope = New TransactionScope(TransactionScopeOption.Required)
orderProcessor.SubmitPurchaseOrder(ordermsg)
scope.Complete()
End Using
The last thing we need to do is to specify the binding and the endpoints for the message queue. This is so
that the client application can readily connect to the queue in code using the endpoint name specified in the
configuration.

1. To specify the configuration file in Visual Studio go to the Tools menu -> WCF SvcConfigEditor. This will
bring up the Microsoft Service Configuraiton Editor. Select File-> New Config.
2. We need to create a new Bindings first. Expand Advanced node.

3. Then right mouse click on Bindings and select Create a New Binding.

4. Select msmqIntegrationBinding. Then click OK.

710
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 16-36. Specifying msmqIntegrationBinding

5. Change the Name of the binding from NewBinding to OrderProcessorBinding.

6. Select the Security tab on OrderProcessorBinding and change the security Mode to None.

Now we need to create an endpoint to point to the MSMQ.


7. To create a new endpoint right mouse click on endpoints then select “New Client Endpont”.

8. Give the endpoint the name of OrderResponseEndpoint

9. On the endpoint Binding attribute specify msmqIntegrationBinding from the dropdownlist.

10. On the BindingConfiguration attribute specify OrderProcessorBinding from the dropdownlist

11. Enter Client.MSMQ.IOrderProcessor as the Contract name

12. Enter msmq.formatname:DIRECT=OS:.\private$\Orders as the value of the address. If the message queue is
not on the same computer as the client application add the name of the computer in the address. So its in the
format msmq.formatname:DIRECT=OS:[computer name]\private$\Orders.

13. Once the above steps had been completed select Save As from the File menu and save the App.config
configuration file to the client application’s location.

14. Once the above steps had been completed the configuration file should look like below.

<?xml version="1.0" encoding="utf-8"?>


<configuration>

711
The Complete Reference To Professional SOA with Visual Studio 2005

<system.serviceModel>
<bindings>
<msmqIntegrationBinding>
<binding name="OrderProcessorBinding">
<security mode="None" />
</binding>
</msmqIntegrationBinding>
</bindings>
<client>
<endpoint
address="msmq.formatname:DIRECT=OS:.\private$\Orders"
binding="msmqIntegrationBinding"
bindingConfiguration="OrderProcessorBinding"
contract="Client.MSMQ.IOrderProcessor"
name="OrderResponseEndpoint" />
</client>
</system.serviceModel>
</configuration>
Now we can execute the application. Since we’re using MSMQ as middleware we don’t have to start both
applications at the same time. The results are shown below in figure 16-37 and figure 16-38.

Figure 16-37. Client order application

712
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 16-38. Order Processing Service

WCF Sessions
WCF sessions are used to allow messages to maintain state over a period of time. Implementing sessions is quite
easy and all we have to do is set the Session parameter to True within ServiceContract
[ServiceContract(Session=true)] and WCF will make sure that a session is established for the communication
between endpoints using that particular contract. The existence of such a communication session does, however,
not immediately control how instances of the service are handled. The correlation between a service instance and
a session is explicitly controlled through the [ServiceBehavior] property InstanceMode. If we need the instance
to stay alive for as long as the session lasts, we can use InstanceMode.PrivateSession and if we need to have a
new instance for every call irrespective of the session scope, you use InstanceMode.PerCall. In the latter case,
we can, if we wanted to, store and recover whatever state we want to associate with the session using the session
identifier that's readily available as a value on OperationContext.Current.SessionIdentifier.

Listing 16-50. Implementing Session in Visual C#

[ServiceContract(Session=true)]
public interface IMyService
{
[OperationContract]
int Add(int num);
}

Listing 16-51. Implementing Session in Visual Basic .NET

<ServiceContract(Session:=True)> _
Public Interface IMyService

<OperationContract()> _
Function Add(ByVal num As Integer) As Integer
End Interface

713
The Complete Reference To Professional SOA with Visual Studio 2005

WCF Transactions
WCF supports a variety of transacted communications. The following code demonstrates a transacted service
operation. To enable a transaction in WCF, use the transaction parameters within the OperationBehavior
attribute, the listing 16-52 and listing 16-53 shows an example of implementing automatic transaction by setting
TransactionAutoComplete = true.

Listing 16-52. Implementing Transaction in Visual C#

[ServiceContract(Session=true)]
public interface IMyService
{
[OperationContract]
[OperationBehavior(
TransactionScopeRequired = true,
TransactionAutoComplete= true)]
int Add(int num);
}

Listing 16-53. Implementing Transaction in Visual Basic .NET

<ServiceContract(Session:=True)> _
Public Interface IMyService

<OperationContract()> _
<OperationBehavior(TransactionScopeRequired:=True,_
TransactionAutoComplete:=True)> _
Function Add(ByVal num As Integer) As Integer
End Interface

Duplex Communication
Traditional remote procedure calls (RPCs) use in-and-out operations. WCF supports multichannel inout
operations, otherwise known as duplex communication. These are implemented using duplex contracts. A duplex
Contract defines two logical sets of operations, A set that the Service exposes for the Client to call and a set that
the Client exposes for the Service to call. The programming model for defining a duplex Contract is to split each
set in a separate type (each type must be a class or an interface). We should use ServiceContract to define our
inputs and CallContract to define the outputs. In the following example we will be developing a duplex WCF
service that performs a large operation before sending a response back to the client on a separate channel see
listing 16-54 and listing 16-55.

Listing 16-54. Demonstrates service implementation using Duplex communication using Visual C#

using System;
using System.ServiceModel;
using System.Threading;

[ServiceContract(Namespace = "http://WCF.Duplex",
Session = true, CallbackContract=typeof(ICalculatorDuplexCallback))]
public interface ICalculatorDuplex
{

714
The Complete Reference To Professional SOA with Visual Studio 2005

[OperationContract(IsOneWay=true)]
void Clear();
[OperationContract(IsOneWay = true)]
void VeryLongAddOperation(double n);
}

public interface ICalculatorDuplexCallback


{
[OperationContract(IsOneWay = true)]
void Equals(double result);
[OperationContract(IsOneWay = true)]
void Duration(string duration);
}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class CalculatorService : ICalculatorDuplex
{
double result;
TimeSpan totalDuration;
ICalculatorDuplexCallback callback = null;

public CalculatorService()
{
result = 0.0D;
callback = OperationContext.Current.GetCallbackChannel
<ICalculatorDuplexCallback>();
}

public void Clear()


{
callback.Duration("Operation duration in milliseconds: " +
totalDuration.TotalMilliseconds);
result = 0.0D;
}

public void VeryLongAddOperation(double n)


{
DateTime start = DateTime.Now;
Thread.Sleep(2000);
result += n;
callback.Equals(result);

totalDuration = (TimeSpan)DateTime.Now.Subtract(start);
}
}

Listing 16-55. Demonstrates using Duplex communication using Visual Basic .NET

Imports System
Imports System.ServiceModel

715
The Complete Reference To Professional SOA with Visual Studio 2005

Imports System.Runtime.Serialization
Imports System.Threading

<ServiceContract(Namespace:="http://WCF.Duplex", _
Session:=True, CallbackContract:=GetType(ICalculatorDuplexCallback))> _
Public Interface ICalculatorDuplex

<OperationContract(IsOneWay:=True)> _
Sub Clear()

<OperationContract(IsOneWay:=True)> _
Sub VeryLongAddOperation(ByVal n As Double)
End Interface

Public Interface ICalculatorDuplexCallback

<OperationContract(IsOneWay:=True)> _
Sub Equals(ByVal result As Double)

<OperationContract(IsOneWay:=True)> _
Sub Duration(ByVal duration As String)
End Interface

<ServiceBehavior(InstanceContextMode:=InstanceContextMode.PerSession)> _
Public Class CalculatorService
Implements ICalculatorDuplex

Private result As Double


Private totalDuration As TimeSpan
Private callback As ICalculatorDuplexCallback = Nothing

Public Sub CalculatorService()


result = 0
callback = OperationContext.Current.GetCallbackChannel _
(Of ICalculatorDuplexCallback)()
End Sub

Public Sub Clear() Implements ICalculatorDuplex.Clear


callback.Duration("Operation duration in milliseconds: " + _
totalDuration.TotalMilliseconds)
result = 0
End Sub

Public Sub VeryLongAddOperation(ByVal n As Double) _


Implements ICalculatorDuplex.VeryLongAddOperation
Dim start As DateTime = DateTime.Now
Thread.Sleep(2000)
result += n
callback.Equals(result)

716
The Complete Reference To Professional SOA with Visual Studio 2005

totalDuration = CType(DateTime.Now.Subtract(start), TimeSpan)


End Sub
End Class

The duplex communication is achieved by implementing duplex contracts. We use ServiceContract to define
our inputs and CallContract to define the outputs. See the listing below example:

Listing 16-56. Using Visual C#


[ServiceContract(Namespace = "http://WCF.Duplex",
Session = true, CallbackContract=typeof(ICalculatorDuplexCallback))]

Listing 16-57. Using Visual Basic .NET

<ServiceContract(Namespace:="http://WCF.Duplex", _
Session:=True, CallbackContract:=GetType(ICalculatorDuplexCallback))> _
The OperationContract is also decorated with the IsOneWay = true attribute. This property indicates that the
method should not deliver a reply. Thus all response to the client should only be treated as a one-way message.
To set up a duplex receiver, we must first implement a ServiceContract and use the callback channel (from
the OperationContext). Here is an example:

Listing 16-58. Using Visual C#


public CalculatorService()
{
result = 0.0D;
callback = OperationContext.Current.GetCallbackChannel
<ICalculatorDuplexCallback>();
}

Listing 16-59. Using Visual Basic .NET

Public Sub CalculatorService()


result = 0
callback = OperationContext.Current.GetCallbackChannel _
(Of ICalculatorDuplexCallback)()
End Sub

Now we need to set the configuration for the WCF service.


1. Select Tools->WCF SvcConfigEditor to bring up Microsoft Service Configuration Editor

2. Select File->New Config

3. We need to create a new binding to support the duplex communication so browse to the Advanced node right
mouse click on Bindings and select “Create a New Binding”.

4. Select wsDualHttpBinding, then click OK

717
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 16-40. wsDualHttpBinding

5. Change the name of the binding to “duplexBinding”

6. Select the Security tab of the new duplexBinding node, change the security Mode to None.

7. Because this is a duplex communication we also need to add a behavior to the configuration. Right mouse click
on Behaviors node under Advanced. Select “New Behavior”

8. Change the name of the behavior to “CalculatorServiceBehavior”

9. Now we can create a service element. Select the Services node right mouse click and select “New Service”

10. Select CalculatorServiceBehavior from the BehaviorConfiguration drop downlist and change the name of the
service from NewServiceType to CalculatorService

11. Now we’re finally ready to create an end point right mouse click on the CalculatorService node we’ve just
created. Select New Endpoint.

12. Select wsDualHttpBinding from for the Binding property. And add ICalculatorDuplex as the name for the
Contract.

13. Select duplexBinding as the BindingConfiguration

14. Now Select File->Save to save the configuration as Web.config

Listing 16-60. Demonstrates the Web.config file created.

<?xml version="1.0"?>

718
The Complete Reference To Professional SOA with Visual Studio 2005

<configuration>
<system.serviceModel>
<behaviors>
<behavior name="CalculatorServiceBehavior"/>
</behaviors>
<bindings>
<wsDualHttpBinding>
<binding name="duplexBinding">
<security mode="None" />
</binding>
</wsDualHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="CalculatorServiceBehavior"
name="CalculatorService">
<endpoint binding="wsDualHttpBinding"
bindingConfiguration="duplexBinding"
contract="ICalculatorDuplex" />
</service>
</services>
</system.serviceModel>
<system.web>
<compilation debug="true"/></system.web></configuration>

Implementing the client application for duplex communication is not very different to how we normally
develop. All the duplex specification is handled by WCF at the binding level. The only thing to keep in mind is
that we do need to wait for the WCF service to return the result from the execution. As the client does not wait
for the service to return and this causes an exception to be thrown when the server tries to return the result and
realize the proxy is out of scope.
To implement the client first create a new console application and call it Client. Then use the svcutil to
generate the proxy by:
svcutil http://localhost:10433/Service/Service.svc
Or for Visual Basic .NET:
svcutil http://localhost:10433/Service/Service.svc /language:vb
Include the output.config and the generated CalculatorService class to the project rename the output.config
file to App.config.

Listing 16-61. Demonstrates duplex client implementation using Visual C#

using System;
using System.ServiceModel;

// The service contract is defined in generatedProxy.cs,


// generated from the service by the svcutil tool.

// Define class which implements callback interface of


//duplex contract
public class CallbackHandler : ICalculatorDuplexCallback
{
public void Equals(double result)
{

719
The Complete Reference To Professional SOA with Visual Studio 2005

Console.WriteLine("Equals({0})", result);
}

public void Duration(string duration)


{
Console.WriteLine(duration);
}

class Client
{
static void Main()
{
// Construct InstanceContext to handle messages on callback
// interface
InstanceContext instanceContext =
new InstanceContext(new CallbackHandler());

// Create a proxy with given client endpoint configuration


using (CalculatorDuplexProxy proxy =
new CalculatorDuplexProxy(instanceContext))
{
Console.WriteLine("request very long operation");
// Call very long service operation.
double value = 100.00D;
proxy.VeryLongAddOperation(value);

// Complete equation
proxy.Clear();
System.Threading.Thread.Sleep(5000);
}

Console.WriteLine();
Console.WriteLine("Press <ENTER> to terminate client.");
Console.ReadLine();
}
}

Listing 16-62. Demonstrates duplex client implementation using Visual Basic .NET

Imports System
Imports System.ServiceModel
Imports System.Runtime.Serialization
Imports System.Threading

<ServiceContract(Namespace:="http://WCF.Duplex", _
Session:=True, CallbackContract:=GetType(ICalculatorDuplexCallback))> _
Public Interface ICalculatorDuplex

<OperationContract(IsOneWay:=True)> _

720
The Complete Reference To Professional SOA with Visual Studio 2005

Sub Clear()

<OperationContract(IsOneWay:=True)> _
Sub VeryLongAddOperation(ByVal n As Double)
End Interface

Public Interface ICalculatorDuplexCallback

<OperationContract(IsOneWay:=True)> _
Sub _Equals(ByVal result As Double)

<OperationContract(IsOneWay:=True)> _
Sub Duration(ByVal duration As String)
End Interface

<ServiceBehavior(InstanceContextMode:=InstanceContextMode.PerSession)> _
Public Class CalculatorService
Implements ICalculatorDuplex

Private result As Double


Private totalDuration As TimeSpan
Private callback As ICalculatorDuplexCallback = Nothing

Public Sub CalculatorService()


result = 0
callback = OperationContext.Current.GetCallbackChannel _
(Of ICalculatorDuplexCallback)()
End Sub

Public Sub Clear() Implements ICalculatorDuplex.Clear


callback.Duration("Operation duration in milliseconds: " + _
totalDuration.TotalMilliseconds)
result = 0
End Sub

Public Sub VeryLongAddOperation(ByVal n As Double) _


Implements ICalculatorDuplex.VeryLongAddOperation
Dim start As DateTime = DateTime.Now
Thread.Sleep(2000)
result += n
callback._Equals(result)
totalDuration = CType(DateTime.Now.Subtract(start), TimeSpan)
End Sub
End Class

To set up a duplex sender, we need to implement a Callbackcontract handle the the callback from the proxy.
This method is executed by the client’s proxy when the request is returned by the WCF service.

Listing 16-63. CallbackHandler using Visual C#

721
The Complete Reference To Professional SOA with Visual Studio 2005

public class CallbackHandler : ICalculatorDuplexCallback


{
public void Equals(double result)
{
Console.WriteLine("Equals({0})", result);
}

public void Duration(string duration)


{
Console.WriteLine(duration);
}
}

Listing 16-64. CallbackHandler using Visual Basic .NET

Public Class CallbackHandler


Implements ICalculatorDuplexCallback

Public Sub _Equals(ByVal result As Double) _


Implements ICalculatorDuplexCallback._Equals
Console.WriteLine("Equals({0})", result)
End Sub

Public Sub Duration(ByVal duration As String) _


Implements ICalculatorDuplexCallback.Duration
Console.WriteLine(duration)
End Sub
End Class
Then create an instance of the InstanceContext class which is used to handle the incoming messages. By
passing in an object of the CallbackHandler the proxy will invoke the CallbackHandler and relevant methods
within the object upon receiving the message from the WCF service.

Listing 16-65. Implementing InstanceContext in Visual C#

InstanceContext instanceContext =
new InstanceContext(new CallbackHandler());

// Create a proxy with given client endpoint configuration


using (CalculatorDuplexProxy proxy =
new CalculatorDuplexProxy(instanceContext))
{
Console.WriteLine("request very long operation");
// Call very long service operation.
double value = 100.00D;
proxy.VeryLongAddOperation(value);

Listing 16-66. Implementing InstanceContext in Visual Basic .NET

Dim instanceContext As InstanceContext = New InstanceContext(New CallbackHandler)


Dim proxy As CalculatorDuplexProxy = New CalculatorDuplexProxy(instanceContext)
Try
Console.WriteLine("request very long operation")
Dim value As Double = 100
proxy.VeryLongAddOperation(value)

722
The Complete Reference To Professional SOA with Visual Studio 2005

Now we need to examine the configuration for the WCF client application. Using the svcutil.exe we have
already generated the output.config file which we have renamed to App.config. Simply right mouse click the
App.config file in solution explorer select “Edit WCF Configuration”. Expand the Advanced node, under
Bindings selet the wsDualHttpBinding node add an address of http://localhost:8000/myClient/ to the
ClientBaseAddress property. We need to add this address because when the WCF service returns the result this
is the address from which the WCF service will call.
Select File->Save to commit the changes to the App.config file.

Figure 16-40. Client application result.

Summary
In this chapter, we have covered the fundamentals of WCF ABCs. We have also learnt to implement WCF
service as well as creating WCF client with the help of SvcUtil.exe to automatically create client side proxy and
configuration.
We have walked through developing hosting environment for a WCF service from which a WCF service can
be launched.
We have also covered developing for secure and reliable messaging. While configuring the WCF service
and client with Microsoft Service Configuration Editor (SvcConfigEditor) which helps to fast track WCF
configuration files.
We have explored the concept of bindings and endpoints and looked at developing and implementing both.
We have also covered how to implement custom bindings to mix and match our requirement in protocols with
WCF.
In this chapter we have also looked at using WCF to communicate with a Microsoft Message Queue
(MSMQ). This allows the client to submit orders to the middleware queue regardless of the status of the
processing service.
Lastly we have implemented duplex communication with the new WCF duplex model.

723
The Complete Reference To Professional SOA with Visual Studio 2005

Chapter 17. Architecture


Conceptualization with
Distributed System Designers
With Microsoft Visual Studio Team System comes with a suite of designers. These designer tools are used to
help reduce the complexity of developing and deploying service-oriented applications.
With these designers, application architects can visualize their architecture. The designers themselves can
generate codes to help work with the developers while the code changes are synchronized with the visual design.
Infrastructure architects can create logical diagrams of their infrastructures such as datacenters. With these
designers we can validate the requirements of the application design against that of the logical design.
There are four Distributed System Designers:

* Application Designer (AD): Represents applications that expose services and communicate through endpoints.
* Logical Datacenter Designer (LDD): Represents the logical structure of a datacenter.

* System Designer (SD): Represents the arrangement of applications defined in the application designer.

* Deployment Designer (DD): Used to create a deployment configuration for a system.

Application Designer
The application designer is suitable for application architects. It is essentially a whiteboard allowing an
application architect to drag and drop shapes to create diagrams of their application system. Services and
applications can be dragged and dropped onto the design surface, from there necessary configuration settings can
be made, and then applications and services can be connected.
The application designer has several benefits compared to Visio type designs:

* The diagrams can produce code that the developers can use to implement services
* The diagrams can be validated against one or more logical datacenters

* The diagrams can generate reports for IT operations


* The diagrams are also very visually pleasing

Implementing Application Designer


In the example below we will be using the Application Designer to create a contact management application
designed for AdventureWorks. The contact management application consists of a Web service, a web based
application used to consume the Web service and the AdventureWorks SQL server database.
To start the Application Designer select File->New->Project.
Under project types select Distributed System Solutions, under Templates there will be Distributed System
and Logical Datacenter template, select Distributed System from under the Templates section see figure 17-1.

724
The Complete Reference To Professional SOA with Visual Studio 2005

Enter the name of ApplicationDesigner, click OK

Figure 17-1. Opening Distributed System Solutions

We now have a blank work space for our application designer. A file called ApplicationDesigner.ad is
created (this is named after the solution name). The toolbox now contains General Designer Tools, Endpoint
Tools, Applications Tools see figure 17-2.

Figure 17-2. Application Designer Toolbox

Table 17-1. Application Designer Tools

725
The Complete Reference To Professional SOA with Visual Studio 2005

Item Description
Pointer The pointer tool is used for selecting and moving objects
Connection The connection tool is used to link two application prototype endpoints
Comment The comment tools creates a comment text box
WebServiceEndpoint Represents a connection endpoint for a web service provider/consumer
WebContentEndpoint Represents a connection endpoint for a web content provider/consumer
GenericEndpoint Represents a connection point to services of a generic type
provider/consumer
WindowsApplication Represents a windows application
ASP.NETWebService An ASP.NET web service application that includes a web service endpoint
ASP.NETWebApplication An ASP.NET web application that includes a web content endpoint
OfficeApplication Represents a Microsoft Office application (Excel, Word and Outlook
templates)
ExternalWebService A reference to a single web service defined by a single Web Service
Description Language .wsdl file
ExternalDatabase Represents a database system
BizTalkWebService Reprents a BizTalkWebService
GenericApplication A generic user-defined application that supports user-defined settings and
constraints.

Click the ASP.NETWebService Tool from under the Applications section of the toolbar and drag and drop it
on to the design surface. This will create an ASP.NETWebApplication shape onto our designer see figure 17-3.
By default the the ASP.NETWebApplication shape has one Web service endpoint called WebService1.

Figure 17-3. ASP.NETWebApplication for Web service

Right click on the ASP.NETWebApplication shape for our Web service select properties change the name to
WebserviceContactManagement. This will rename our shape to WebserviceContactManagement.
Then click the ExternalDatabase component in the Applications section of the toolbar and drag and drop the
tool onto the designer. This will create the ExternalDatabase shape on the designer. By default the
ExternalDatabase shape also has one endpoint called Database1 figure 17-4.

Figure 17-4. ExternalDatabase

726
The Complete Reference To Professional SOA with Visual Studio 2005

Right Click on the database shape and select properties, by default the name is Database1 change the name
to AdventureWorks. This will change the name of the endpoint, this implies that other applications will be
connecting to the AdventureWorks database.

Connecting the Applications


To connect the applications it usually is a simple matter of selecting the connection tool from the general
designer section of the toolbox and drag and drop the endpoint of the required connections. For example now we
will need to create a connection from the AdventureWorks database to our WebserviceContactManagement
service.
Select the Connection tool from the General Designer
Simply select the ExternalDatabase (AdventureWorks) shape’s endpoint and then select our
ASP.NETWebApplication(WebserviceContactManagement) see figure 17-5.

Figure 17-5. Establishing a connection.

Creating connections is fairly straight forward. The application designer contains constraints about
connections for example we can not connect a connection between a Web service endpoint and that of a
Database endpoint see figure 17-6. Logically it doesn’t make sense as a Web service endpoint provides service
functionalities and the endpoint itself is to be consumed. While a database endpoint is used by an application to
connect to the database. So if we tried to drag and drop a connection from a Web service endpoint to a database
endpoint the designer will not allow us to establish the connection.

727
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-6. Connecting ASP.NETWebApplication endpoint to ExternalDatabase endpoint

Once the connection has been established a Connection Properties window will appear prompting for the
Database details. In the Choose Data Source dialog box, enter the data source and data provider. For this
example, select Microsoft SQL Server and the .NET Data Provider for SQL Server, respectively. Click
Continue.
In the Connection Properties dialog box figure 17-7, enter the database server name, the security context,
and the database name. (We can enter a period for the server name to indicate as local SQL Server installation,
or enter .\sqlexpress for default installations of SQL Express edition.) Click Test Connection to verify that the
configuration information for the data source is correct. Click OK to establish the connection.

Figure 17-7. Database Connection Property

TIP: If we’re only whiteboarding our idea to designer we don’t have to specify the connection details simply click cancel to configure the
connection at a later time.

To verify the connection properties, right-click the database consumer endpoint of our web service and
select Properties. In the properties section the connection information is stored under Connection String, as
shown in figure 17-8 (below). This Connection String property will be generated into the Web.config file of the
AdventureWorks application when it is implemented.

728
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-8. Demonstrates the connection properties of the Webservice endpoint.

Now we should have a diagram which look like the figure below.

Figure 17-9. ASP.NETWebApplication connected to a ExternalDatabase

As we configure the database information it is generated into a XML file. To file this file simply right-click
the Database1.sdm file in the solution explorer and choose to open it with the XML editor. We cannot have the
XML editor and the Application Designer open at the same time. We will be prompted to close and save the
diagram prior to opening the .sdm file.
The listing below shows the .sdm file generated so far:

Listing 17-1. XML file describing the database application

<?xml version="1.0" encoding="utf-8"?>


<!--System Definition Model (SDM) based file generated by Visual Studio.-->
<!--Manual editing of this file is not
recommended and can result in errors.-->
<SystemDefinitionModel

729
The Complete Reference To Professional SOA with Visual Studio 2005

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
Name="AdventureWorks" Version="1.0.0.0"
Culture="en-US" DocumentLanguage="en-US"
xmlns="http://schemas.microsoft.com/SystemDefinitionModel/2005/1">
<Import Alias="System" Name="System" Version="1.0.50729.0" />
<Import Alias="MicrosoftDatabase"
Name="Microsoft.Database" Version="1.0.50729.0" />
<Import Alias="MicrosoftData"
Name="Microsoft.Data" Version="1.0.50729.0" />
<DesignData>
<VisualStudio
xmlns="http://schemas.microsoft.com/SystemDefinitionModel/2005/1/
DesignData/VisualStudio">
<ModelElement Id="25efdca4f5544980a3349613dabd38cb"
Type="Microsoft.VisualStudio.EnterpriseTools.Application
.Modeling.SoftwareComponentDocument">
<Property Name="Version" Value="1" />
</ModelElement>
</VisualStudio>
</DesignData>
<SystemDefinition Name="AdventureWorks"
Extends="MicrosoftDatabase:Database" SimulationRoot="false">
<DesignData>
<VisualStudio xmlns="http://schemas.microsoft.com/
SystemDefinitionModel/2005/1/DesignData/VisualStudio">
<ModelElement
Type="Microsoft.VisualStudio.EnterpriseTools.Application
.Modeling.PlugIns.DeployedDBComponentType">
<Property Name="State" Value="Implemented" />
<Property Name="Realization" Value="External" />
</ModelElement>
</VisualStudio>
</DesignData>
<EndpointDefinition Name="DatabaseProviderEndpoint1"
Extends="MicrosoftData:DataServer">
<DesignData>
<VisualStudio xmlns="http://schemas.microsoft.com/
SystemDefinitionModel/2005/1/DesignData/VisualStudio">
<ModelElement Type="Microsoft.VisualStudio.EnterpriseTools
.Application.Modeling.ApplicationPortType" />
</VisualStudio>
</DesignData>
</EndpointDefinition>
<Endpoint Name="AdventureWorks"
Definition="AdventureWorks.DatabaseProviderEndpoint1"
MinOccurs="1" MaxOccurs="1" Reference="false">
<DesignData>
<VisualStudio
xmlns="http://schemas.microsoft.com/SystemDefinitionModel/
2005/1/DesignData/VisualStudio">
<ModelElement
Type="Microsoft.VisualStudio.EnterpriseTools.Application

730
The Complete Reference To Professional SOA with Visual Studio 2005

.Modeling.PlugIns.DeployedDBProviderPort">
<Property Name="State" Value="Implemented" />
<Property Name="NeedsGeneration" Value="true" />
</ModelElement>
</VisualStudio>
</DesignData>
</Endpoint>
<Containment Name="AdventureWorksContainment"
Definition="MicrosoftDatabase:DatabaseContainsDataServer"
ChildMember="AdventureWorks" />
</SystemDefinition>
</SystemDefinitionModel>

In the above listing we can see that the diagram object has a state of Implemented. This is also categorized
by the object’s shadow over its shape see figure 17-9.
There are several different endpoints that are used for different providers. We can only connect a consumer
endpoint to only a single provider endpoint. The Table 17-2 illustrates the different shapes for different
endpoints and their associated meanings.

Table 17-2. Object endpoint representations

Endpoint Description
Generic endpoint

Database endpoint

Web content endpoint

Web service endpoint

Rules for Connecting Applications


The following rules apply when connecting applications:

* We can create connections between existing endpoints, or if an application does not have endpoints, we can
add them, if supported by the application type.
* Endpoints define their role in communication as consumers or providers of services. Therefore, the direction in
which we draw a connection does not affect the direction of that connection.

* When an application or endpoint is selected, choosing the Connect command from the Diagram or context
menu opens a connection dialog box. In the connection dialog box, we can choose a compatible application and
a provider endpoint on that application to complete the connection.

* We can begin a connection from a provider endpoint by using the Connection tool or the Connect command.

731
The Complete Reference To Professional SOA with Visual Studio 2005

* We cannot draw connections directly between applications using the Connection tool. However, we can draw a
connection between an application and a suitable provider endpoint, starting from either the application or the
provider endpoint.

* If compatible provider and consumer endpoints exist, we can connect them by beginning the connection from
either endpoint using the Connection tool or Connect command.

* If a connection has been deleted, we can reconnect the disconnected applications directly between their
endpoints.

Defining Web Service Prototypes


One of the key features of the Application Designer is the ability to define the operations and parameters for web
services that are exposed on the diagram. This is part of the contract-first design, where we first design the
service contracts for communicating between different application types. If we have an existing .wsdl file, we
can also consume the operations from the existing exposed service.
To start defining the Endpoint of the ASP.NETWebApplication simply select the WebService1 endpoint.
Right click on the endpoint and select Define Operations to open the Web Service Details window.
Using the Web Service Details window, we can add the operations, parameters, types, and details. For this
sample application, we will be creating the following operations: AddContact, UpdateContactByID,
RemoveContactByID, SelectContactByID see figure 17-10 below.

To add these operations Click <add operation> and type the name AddContact.

Figure 17-10. Add operation

1. Click the plus sign next to the AddContact function to reveal the <add parameter> section.

2. Then click <add parameter> and add the following parameters: FirstName, MiddleName, LastName change
their Type to String.

3. Following the above steps add the operations for UpdateContactByID, RemoveContactByID and
SelectContactByID see figure 17-11 below.

732
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-11. Web Service Details.

Adding an Endpoint through WSDL


We can also add a Web service endpoint from a WSDL document. In this example we will be creating a
reference from another Web service. The second web service is defined in the listing below.

Listing 17-2. Sample Web service using Visual C#

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
public Service () {

//Uncomment the following line if using designed components


//InitializeComponent();
}

[WebMethod]
public string HelloWorld1() {
return "Hello World";
}

[WebMethod]
public string HelloWorld2()
{
return "Hello World";

733
The Complete Reference To Professional SOA with Visual Studio 2005

[WebMethod]
public string HelloWorld3()
{
return "Hello World";
}
}

Listing 17-3. Sample Web service using Visual Basic .NET

Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols

<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class Service
Inherits System.Web.Services.WebService

<WebMethod()> _
Public Function HelloWorld1() As String
Return "Hello World"
End Function

<WebMethod()> _
Public Function HelloWorld2() As String
Return "Hello World"
End Function

<WebMethod()> _
Public Function HelloWorld3() As String
Return "Hello World"
End Function
End Class

To add the above implementation or any WSDL document to the designer as an endpoint simply right
mouse-click the ASP.NETWebApplication object and select “Create Web Service Endpoint From WSDL” see
figure 17-12.

734
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-12. Creating a Web service from a WSDL document

This will bring up the Add Web Reference dialog window see figure 17-13 below. Enter the url containing
the WSDL document. Please keep in mind that the port number may differ if you’re launching the Web service
application with ASP.NET Development Web Server. Once complete select the Add Reference button.

Figure 17-13. Add reference.

This will result in another Web service endpoint called Service see figure 17-14 below.

735
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-14. A new endpoint

Selecting the Service endpoint and looking into the Web Service Details window. We can see that the
WebMethods had been entered into the details section see figure 17-15 below.

Figure 17-15. Web Service Details.

Implement the Application


In this section we will generate the actual code for a developer to implement from the diagram we had
constructed. When an application is implemented, the Application Designer automatically generates the
corresponding project, code files, and configuration files. Because the application diagram is synchronized with
the code and configuration files, the diagram is immediately updated if the files are modified. Similarly, changes
to the diagram are reflected in the code and configuration files. Upon implementation, the application prototypes
will be identified by the shadow effect around the object shape.

Creating a Toolbox Item


The first thing that we need to do is to select the implementation language used to generate. For this example we
will select Visual C# for Visual Basic users select Visual Basic.

1. Click ASP.NETWebApplication in the application diagram and right mouse click and select Properties. In the
Implementation section, select the language to generate as Visual C# figure 17-16.

736
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-16. Select the language to implement

We can also add our diagrams to the Toolbox.

2. Simply right mouse click the ASP.NETWebApplication shape and select “Add to Toolbox”.
3. In the Name field type in WebserviceContactManager then click OK see figure 17-17 below.

Figure 17-17. Add to Toolbox

4. The Save File dialog box appears we’re prompted to save the Application Designer Prototype. Click Save, and
WebserviceContactManager is added to our Toolbox see figure 17-18.

737
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-18. WebserviceContactManager

This is particularly useful by adding our shape to the toolbar we can easily drag and drop the duplicates of
WebserviceContactManager to the designer. The WebserviceContactManager will contain the exact same
properties.

Generating Code
Now that we have selected the necessary language for our shape we can implement the application to let Visual
Studio create our code for us.

1. To implement the shape ASP.NETWebApplication simply right click the shape and choose Implement
Application. Alternatively, we can select Diagrams -> Implement Application from the main menu. This will in
turn launch the Confirm Application implementation dialog box see figure 17-19.

Figure 17-19. Confirm Application Implementation.

738
The Complete Reference To Professional SOA with Visual Studio 2005

2. Select OK and wait for the application code to be generated inside the solution. We may receive a warning that
the connection string is being written into the configuration files unencrypted see figure 17-20. Select close to
let the process continue.

Figure 17-20. Security warning dialog box.

The result of the implementation is that a new web service project has been added to the solution. This new
project includes language-specific source and configuration files see figure 17-21.

Figure 17-21. A new web service project

Notice now that our WebserviceContactManager is implemented. All implemented components are
represented in the Application Designer by a shadow border outlining the component on the diagram surface see
figure 17-22.

Figure 17-22. Implemented ASP.NETWebApplication

739
The Complete Reference To Professional SOA with Visual Studio 2005

Updating the Design


One of the advantages of using the application designer is that we can make changes within our code and Visual
Studio will automatically reflect the changes within the Application Designer. In the following example we will
create an additional method in our newly generated Web service code.
Double-click MyService1.cs in the Solution Explorer to display the generated code. Notice that the
operations and parameters we defined earlier in the designer have been implemented in code. We can see all four
methods have been implemented into code: AddContact, UpdateContactByID, RemoveCotnactByID and
SelectContactByID see listing 17-4 and listing 17-5 below.

Listing 17-4. Demonstrates the newly generated code in Visual C#

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

namespace WebserviceContactManagement
{
[System.Web.Services.WebServiceBinding(
Name = "WebService1",
ConformsTo = System.Web.Services.WsiProfiles.BasicProfile1_1,
EmitConformanceClaims = true),
System.Web.Services.Protocols.SoapDocumentService()]
public class WebService1 : System.Web.Services.WebService
{
/// <summary>
/// Add a contact
/// </summary>
[System.Web.Services.WebMethod(),
System.Web.Services.Protocols.SoapDocumentMethod
(Binding = "WebService1")]
public void AddContact(string FirstName,
string MiddleName, string LastName)
{
throw new System.NotImplementedException();
}

/// <summary>
/// Update a contact detail by ID
/// </summary>
[System.Web.Services.WebMethod(),
System.Web.Services.Protocols.SoapDocumentMethod(Binding =
"WebService1")]
public void UpdateContactByID(int ContactID,
string FistName, string MiddleName, string LastName)
{
throw new System.NotImplementedException();
}

/// <summary>

740
The Complete Reference To Professional SOA with Visual Studio 2005

/// Remove a contact detail by ID


/// </summary>
[System.Web.Services.WebMethod(),
System.Web.Services.Protocols.SoapDocumentMethod
(Binding = "WebService1")]
public void RemoveContactByID(int ContactID)
{
throw new System.NotImplementedException();
}

/// <summary>
/// Select a contact by ID
/// </summary>
[System.Web.Services.WebMethod(),
System.Web.Services.Protocols.SoapDocumentMethod
(Binding = "WebService1")]
public DataSet SelectContactByID(int ContactID)
{
throw new System.NotImplementedException();
}
}
}

Listing 17-5. Demonstrates the newly generated code in Visual Basic .NET

Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols

Namespace WebserviceContactManagement

<System.Web.Services.WebServiceBinding(Name:="WebService1", _
ConformsTo:=System.Web.Services.WsiProfiles.BasicProfile1_1, _
EmitConformanceClaims:=True)> _
<System.Web.Services.Protocols.SoapDocumentService()> _
Public Class WebService1

''' <summary>
''' Add a contact
''' </summary>
<System.Web.Services.WebMethod()> _
<System.Web.Services.Protocols.SoapDocumentMethod _
(Binding:="WebService1")> _
Public Sub AddContact(ByVal FirstName As String, _
ByVal MiddleName As String, ByVal LastName As String)

End Sub

''' <summary>
''' Update a contact detail by ID
''' </summary>

741
The Complete Reference To Professional SOA with Visual Studio 2005

<System.Web.Services.WebMethod()> _
<System.Web.Services.Protocols.SoapDocumentMethod _
(Binding:="WebService1")> _
Public Sub UpdateContactByID(ByVal ContactID As Integer, _
ByVal FirstName As String, ByVal MiddleName As String, _
ByVal LastName As String)

End Sub

''' <summary>
''' Remove a contact detail by ID
''' </summary>
<System.Web.Services.WebMethod()> _
<System.Web.Services.Protocols.SoapDocumentMethod _
(Binding:="WebService1")> _
Public Sub RemoveContactByID(ByVal ContactID As Integer)

End Sub

''' <summary>
''' Select a contact by ID
''' </summary>
<System.Web.Services.WebMethod()> _
<System.Web.Services.Protocols.SoapDocumentMethod _
(Binding:="WebService1")> _
Public Function SelectContactByID(ByVal ContactID As Integer) _
As System.Data.DataSet

End Function

End Class

End Namespace

Now we will be implementing a new WebMethod called FindContactByFirstName see listing 17-6 and
listing 17-7.

Listing 17-6. New FindContactByFirstName WebMethod using Visual C#

/// <summary>
/// Find a contact by first name
/// </summary>
[System.Web.Services.WebMethod(), System.Web.Services.Protocols.SoapDocumentMethod(Binding = "WebService1")]
public DataSet FindContactByFirstName(string FirstName)
{
throw new System.NotImplementedException();
}

Listing 17-7. New FindContactByFirstName WebMethod using Visual Basic .NET

<System.Web.Services.WebMethod(), _
System.Web.Services.Protocols.SoapDocumentMethod(Binding="WebService1")> _

742
The Complete Reference To Professional SOA with Visual Studio 2005

Public Function FindContactByFirstName(ByVal FirstName As String) _


As DataSet
Throw New System.NotImplementedException
End Function

Upon saving the WebService1.cs file will result in an immediate update to the Application Designer see
figure 17-23. The newly added function will have been added to the Web Service Details window.

Figure 17-23. Newly implemented FindContactByFirstName

Now to test the service code that was generate open the source code again. Because we are returning a
DataSet from some of the functions we need to add the System.Data namespace into the code. So for C# users
add using System.Data; for Visual Basic .NET users add Imports System.Data. Press F5 to Run the Web service
application see figure 17-24.
When prompted to Run a dialog window may appear asking you whether you want to enable debugging.

Figure 17-24. The implementations of the Webservice using Visual C#

743
The Complete Reference To Professional SOA with Visual Studio 2005

We will complete the rest of the implementation of the Web service by using the code in the listing 17-8 and
listing 17-9.

Listing 17-8. The full implementation of the Web service code using Visual C#.

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;

namespace WebserviceContactManagement
{
[System.Web.Services.WebServiceBinding(Name = "WebService1",
ConformsTo = System.Web.Services.WsiProfiles.BasicProfile1_1,
EmitConformanceClaims = true),
System.Web.Services.Protocols.SoapDocumentService()]
public class WebService1 : System.Web.Services.WebService
{
SqlConnection sqlcon = new SqlConnection
(ConfigurationManager.AppSettings["ConnectionString"]
.ToString());

/// <summary>
/// Add a contact
/// </summary>
[System.Web.Services.WebMethod(),
System.Web.Services.Protocols.SoapDocumentMethod
(Binding = "WebService1")]
public void AddContact(string FirstName,
string MiddleName, string LastName)
{
sqlcon.Open();
SqlTransaction transaction =
this.sqlcon.BeginTransaction("ContactTran");

SqlCommand sqlcmdEmployee = new SqlCommand(


@"insert into Person.Contact (FirstName,
MiddleName, LastName) Values
(@FirstName, @MiddleName, @LastName)", sqlcon);
sqlcmdEmployee.Transaction = transaction;
sqlcmdEmployee.Parameters.Add
("@FirstName", SqlDbType.VarChar, 50).Value = FirstName;
sqlcmdEmployee.Parameters.Add
("@MiddleName", SqlDbType.VarChar, 50).Value = MiddleName;
sqlcmdEmployee.Parameters.Add
("@LastName", SqlDbType.VarChar, 50).Value = LastName;

sqlcmdEmployee.ExecuteNonQuery();
transaction.Commit();
sqlcon.Close();

744
The Complete Reference To Professional SOA with Visual Studio 2005

/// <summary>
/// Update a contact detail by ID
/// </summary>
[System.Web.Services.WebMethod(),
System.Web.Services.Protocols.SoapDocumentMethod
(Binding = "WebService1")]
public void UpdateContactByID(int ContactID, string FirstName,
string MiddleName, string LastName)
{
sqlcon.Open();
SqlTransaction transaction =
this.sqlcon.BeginTransaction("ContactTran");

SqlCommand sqlcmdEmployee = new SqlCommand(


@"update Person.Contact set
FirstName = @FirstName,
MiddleName = @MiddleName,
LastName = @LastName
where Person.Contact.ContactID = @ContactID;", sqlcon);
sqlcmdEmployee.Transaction = transaction;
sqlcmdEmployee.Parameters.Add
("@ContactID", SqlDbType.Int, sizeof(int)).Value = ContactID;
sqlcmdEmployee.Parameters.Add
("@FirstName", SqlDbType.VarChar, 50).Value = FirstName;
sqlcmdEmployee.Parameters.Add
("@MiddleName", SqlDbType.VarChar, 50)
.Value = MiddleName;
sqlcmdEmployee.Parameters.Add
("@LastName", SqlDbType.VarChar, 50).Value = LastName;

sqlcmdEmployee.ExecuteNonQuery();
transaction.Commit();
sqlcon.Close();

/// <summary>
/// Remove a contact detail by ID
/// </summary>
[System.Web.Services.WebMethod(),
System.Web.Services.Protocols.SoapDocumentMethod
(Binding = "WebService1")]
public void RemoveContactByID(int ContactID)
{
sqlcon.Open();
SqlTransaction transaction =
this.sqlcon.BeginTransaction("ContactTran");

SqlCommand sqlcmdEmployee = new SqlCommand(


@"delete from Person.Contact where

745
The Complete Reference To Professional SOA with Visual Studio 2005

Person.Contact.ContactID = @ContactID;", sqlcon);


sqlcmdEmployee.Transaction = transaction;
sqlcmdEmployee.Parameters.Add
("@ContactID", SqlDbType.Int, sizeof(int)).Value = ContactID;

sqlcmdEmployee.ExecuteNonQuery();
transaction.Commit();
sqlcon.Close();
}

/// <summary>
/// Select a contact by ID
/// </summary>
[System.Web.Services.WebMethod(),
System.Web.Services.Protocols.SoapDocumentMethod
(Binding = "WebService1")]
public DataSet SelectContactByID(int ContactID)
{
// retrieve employee contact details
string sql = String.Format
("select ContactID, Title, FirstName, MiddleName, LastName" +
" from Person.Contact where ContactID = {0}", ContactID);
SqlCommand sqlcmd = new SqlCommand(sql, sqlcon);

SqlDataAdapter da = new SqlDataAdapter(sql, sqlcon);


DataSet ds = new DataSet();
da.Fill(ds);
sqlcon.Close();

return ds;
}

/// <summary>
/// Find a contact by first name
/// </summary>
[System.Web.Services.WebMethod(),
System.Web.Services.Protocols.SoapDocumentMethod
(Binding = "WebService1")]
public DataSet FindContactByFirstName(string FirstName)
{
// retrieve employee contact details
string sql = String.Format
("select ContactID, Title, FirstName, MiddleName, LastName" +
" from Person.Contact where FirstName like '%{0}%'", FirstName);
SqlCommand sqlcmd = new SqlCommand(sql, sqlcon);

SqlDataAdapter da = new SqlDataAdapter(sql, sqlcon);


DataSet ds = new DataSet();
da.Fill(ds);
sqlcon.Close();

return ds;
}

746
The Complete Reference To Professional SOA with Visual Studio 2005

}
}

Listing 17-9. The full implementation of the Web service code using Visual Basic .NET

Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.Data
Imports System.Data.SqlClient

Namespace WebserviceContactManagement

<System.Web.Services.WebServiceBinding(Name:="WebService1", _
ConformsTo:=System.Web.Services.WsiProfiles.BasicProfile1_1, _
EmitConformanceClaims:=True)> _
<System.Web.Services.Protocols.SoapDocumentService()> _
Public Class WebService1
Private sqlcon As SqlConnection = New SqlConnection _
(ConfigurationManager.AppSettings("ConnectionString").ToString())

''' <summary>
''' Add a contact
''' </summary>
<System.Web.Services.WebMethod()> _
<System.Web.Services.Protocols.SoapDocumentMethod _
(Binding:="WebService1")> _
Public Sub AddContact(ByVal FirstName As String, _
ByVal MiddleName As String, ByVal LastName As String)
sqlcon.Open()
Dim transaction As SqlTransaction = _
Me.sqlcon.BeginTransaction("ContactTran")
Dim sqlcmdEmployee As SqlCommand = _
New SqlCommand("insert into Person.Contact (FirstName," & _
" MiddleName, LastName) Values (@FirstName, @MiddleName, " & _
" @LastName)", sqlcon)
sqlcmdEmployee.Transaction = transaction
sqlcmdEmployee.Parameters.Add("@FirstName", SqlDbType.VarChar, _
50).Value = FirstName
sqlcmdEmployee.Parameters.Add("@MiddleName", SqlDbType.VarChar, _
50).Value = MiddleName
sqlcmdEmployee.Parameters.Add("@LastName", SqlDbType.VarChar, _
50).Value = LastName
sqlcmdEmployee.ExecuteNonQuery()
transaction.Commit()
sqlcon.Close()
End Sub

''' <summary>
''' Update a contact detail by ID

747
The Complete Reference To Professional SOA with Visual Studio 2005

''' </summary>
<System.Web.Services.WebMethod()> _
<System.Web.Services.Protocols.SoapDocumentMethod _
(Binding:="WebService1")> _
Public Sub UpdateContactByID(ByVal ContactID As Integer, _
ByVal FirstName As String, ByVal MiddleName As String, _
ByVal LastName As String)
sqlcon.Open()
Dim transaction As SqlTransaction = _
Me.sqlcon.BeginTransaction("ContactTran")
Dim sqlcmdEmployee As SqlCommand = New SqlCommand _
("update Person.Contact set FirstName = @FirstName, " & _
" MiddleName = @MiddleName, LastName = @LastName " & _
" where Person.Contact.ContactID = @ContactID;", sqlcon)
sqlcmdEmployee.Transaction = transaction
sqlcmdEmployee.Parameters.Add("@ContactID", SqlDbType.Int) _
.Value = ContactID
sqlcmdEmployee.Parameters.Add("@FirstName", _
SqlDbType.VarChar, 50).Value = FirstName
sqlcmdEmployee.Parameters.Add("@MiddleName", _
SqlDbType.VarChar, 50).Value = MiddleName
sqlcmdEmployee.Parameters.Add("@LastName", _
SqlDbType.VarChar, 50).Value = LastName
sqlcmdEmployee.ExecuteNonQuery()
transaction.Commit()
sqlcon.Close()
End Sub

''' <summary>
''' Remove a contact detail by ID
''' </summary>
<System.Web.Services.WebMethod()> _
<System.Web.Services.Protocols.SoapDocumentMethod _
(Binding:="WebService1")> _
Public Sub RemoveContactByID(ByVal ContactID As Integer)
sqlcon.Open()
Dim transaction As SqlTransaction = _
Me.sqlcon.BeginTransaction("ContactTran")
Dim sqlcmdEmployee As SqlCommand = _
New SqlCommand("delete from Person.Contact where " & _
" Person.Contact.ContactID = @ContactID;", sqlcon)
sqlcmdEmployee.Transaction = transaction
sqlcmdEmployee.Parameters.Add("@ContactID", SqlDbType.Int) _
.Value = ContactID
sqlcmdEmployee.ExecuteNonQuery()
transaction.Commit()
sqlcon.Close()
End Sub

''' <summary>
''' Select a contact by ID
''' </summary>
<System.Web.Services.WebMethod()> _

748
The Complete Reference To Professional SOA with Visual Studio 2005

<System.Web.Services.Protocols.SoapDocumentMethod _
(Binding:="WebService1")> _
Public Function SelectContactByID(ByVal ContactID As Integer) _
As System.Data.DataSet
Dim sql As String = String.Format("select ContactID, Title, " & _
" FirstName, MiddleName, LastName from Person.Contact where" & _
" ContactID = {0}", ContactID)
Dim sqlcmd As SqlCommand = New SqlCommand(sql, sqlcon)
Dim da As SqlDataAdapter = New SqlDataAdapter(sql, sqlcon)
Dim ds As DataSet = New DataSet
da.Fill(ds)
sqlcon.Close()
Return ds
End Function

''' <summary>
''' Find a contact by first name
''' </summary>
<System.Web.Services.WebMethod()> _
<System.Web.Services.Protocols.SoapDocumentMethod(Binding:="WebService1")> _
Public Function FindContactByFirstName(ByVal FirstName As String) _
As System.Data.DataSet
Dim sql As String = String.Format("select ContactID, " & _
" Title, FirstName, MiddleName, LastName from Person.Contact " & _
" where FirstName like '%{0}%'", FirstName)
Dim sqlcmd As SqlCommand = New SqlCommand(sql, sqlcon)
Dim da As SqlDataAdapter = New SqlDataAdapter(sql, sqlcon)
Dim ds As DataSet = New DataSet
da.Fill(ds)
sqlcon.Close()
Return ds
End Function
End Class

End Namespace

To test the service press F5 to start the WebService1.asmx. Select the SelectContactByID link and enter a
ContactID to test the service see figure 17-25.

749
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-25. SelectContactByID

The result of the execution is shown in figure 17-26.

Figure 17-26. SelectContactByID result

750
The Complete Reference To Professional SOA with Visual Studio 2005

Adding a Web Application


Once we have established that our Web service is working. Its time to implement a Web application that will
consume the service.

1. Return to the Application Designer diagram.

2. Select the ASP.NETWebApplication Tool and drag and drop it onto the designer

3. Right mouse click and select properties. Rename the object from WebApplication1 to
WebApplicationWSConsumer.

4. Select your preferred language for implementation.

5. To connect the web application to the web service, right click the WebApplicationWSConsumer and select
Connect.

6. In the Connect To section, select WebserviceContactManagement for the application and WebService1 for the
endpoint and click OK figure 17-27.

Figure 17-27. Create Connection

7. The completed diagram is shown in figure 17-28. It is also a good idea to illustrate the diagram by drag and
drop the comment tool from the Toolbox.

751
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-28. Complete design

Now we can implement the application right mouse click on WebApplicationWSConsumer and selecting
Implement Application. The result of implementing our design is that a new web application project has been
added to the solution, figure 17-29 below.

Figure 17-29. ASP.NETWebApplication Properties.

In the new Web Application project that Visual Studio has automatically created, a web reference to the
Web service project is automatically added to the project. To create a simple user interface (UI) for our contact
management system edit Default.aspx see figure 17-30.

752
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-30. The web application layout

To implement the above design we will need to drag and drop a series of UI elements within the table to
create an operational web page. We will need to drag and drop a series of Labels and Textboxes from the
Toolbox onto the designer to achieve this. Please refer to the source code for this chapter for the implementation
of Web Application as coverage is beyond scope of this book. listing 17-10 below shows the html for the Web
application.

Listing 17-10. ASP.NET HTML SourceCode

<%@ Page Language="C#" AutoEventWireup="true"


CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>

753
The Complete Reference To Professional SOA with Visual Studio 2005

<table>
<th colspan="2" style="height: 21px">
Get Contact By ID</th>
<tr>
<td>
<asp:TextBox ID="TextbxGetContactContactID"
runat="server"></asp:TextBox><br />
</td>
<td>
<asp:Button ID="BtnContactByID" runat="server"
OnClick="BtnContactByID_Click"
Text="Get Contact By ID" />
</td>
</tr>
<td colspan="2">
<asp:GridView ID="GridView1" runat="server">
</asp:GridView>
</td>
</table>
<hr />
<table>
<th colspan="2">
Update Contact</th>
<tr>
<td>
Contact ID</td>
<td>
<asp:TextBox ID="txtbxContactID" runat="server">
</asp:TextBox></td>
</tr>
<tr>
<td>
First Name</td>
<td>
<asp:TextBox ID="txtbxFirstName" runat="server">
</asp:TextBox></td>
</tr>
<tr>
<td>
Middle Name</td>
<td>
<asp:TextBox ID="txtbxMiddleName" runat="server">
</asp:TextBox></td>
</tr>
<tr>
<td>
Last Name</td>
<td>
<asp:TextBox ID="txtbxLastName" runat="server">
</asp:TextBox></td>
</tr>
<tr>
<td colspan="2" style="height: 26px">

754
The Complete Reference To Professional SOA with Visual Studio 2005

<asp:Button ID="ButtonUpdatecontact" runat="server"


OnClick="ButtonUpdatecontact_Click"
Text="Update Contact" /></td>
</tr>
</table>
<hr />
<table>
<th colspan="2">
Remove contact by ID</th>
<tr>
<td>
Contact ID</td>
<td>
<asp:TextBox ID="TextbxRemoveContactContactID"
runat="server"></asp:TextBox></td>
</tr>
<tr>
<td colspan="2">
<asp:Button ID="ButtonRemoveContact" runat="server"
OnClick="ButtonRemoveContact_Click"
Text="Remove Contact By ID" /></td>
</tr>
</table>
<hr />
<table>
<th colspan="2">
Create Contact</th>
<tr>
<td>
First Name</td>
<td>
<asp:TextBox ID="TextbxCreateContactFirstName"
runat="server"></asp:TextBox></td>
</tr>
<tr>
<td>
Middle Name</td>
<td>
<asp:TextBox ID="TextbxCreateContactMiddleName"
runat="server"></asp:TextBox></td>
</tr>
<tr>
<td>
Last Name</td>
<td>
<asp:TextBox ID="TextbxCreateContactLastName"
runat="server"></asp:TextBox></td>
</tr>
<tr>
<td colspan="2">
<asp:Button ID="ButtonCreateContact" runat="server"
OnClick="ButtonCreateContact_Click"
Text="Create Contact" /></td>

755
The Complete Reference To Professional SOA with Visual Studio 2005

</tr>
</table>
<hr />
<table>
<th colspan="2">
Find User by First Name
</th>
<tr>
<td>
First Name
</td>
<td>
<asp:TextBox ID="TextbxFindUserFirstName"
runat="server"></asp:TextBox>
</td>
</tr>
<tr>
<td colspan="2">
<asp:Button ID="ButtonFindUser" runat="server"
OnClick="ButtonFindUser_Click" Text="Find User" />
</td>
<td>
</td>
</tr>
<tr>
<td colspan="2">
<asp:GridView ID="GridView2" runat="server">
</asp:GridView>
</td>
</tr>
</table>
</div>
</form>
</body>
</html>

The listing below demonstrates the code used to implement our calls to the web service from the Web
Application.

Listing 17-11. Demonstrates the implementation of the ASP.NET code in the code behind using Visual C#

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using WebApplicationWSConsumer.WebServiceProxies;

public partial class _Default : System.Web.UI.Page

756
The Complete Reference To Professional SOA with Visual Studio 2005

{
protected void Page_Load(object sender, EventArgs e)
{

protected void BtnContactByID_Click(object sender, EventArgs e)


{
WebService1 proxies = new WebService1();
DataSet ds = proxies.SelectContactByID(
int.Parse(this.TextbxGetContactContactID.Text));
this.GridView1.DataSource = ds;
this.GridView1.DataBind();
}

protected void ButtonUpdatecontact_Click(object sender, EventArgs e)


{
WebService1 proxies = new WebService1();
proxies.UpdateContactByID(int.Parse(this.txtbxContactID.Text),
this.txtbxFirstName.Text, this.txtbxMiddleName.Text,
this.txtbxLastName.Text);
}

protected void ButtonRemoveContact_Click(object sender, EventArgs e)


{
WebService1 proxies = new WebService1();
proxies.RemoveContactByID(
int.Parse(this.TextbxRemoveContactContactID.Text));
}

protected void ButtonCreateContact_Click(object sender, EventArgs e)


{
WebService1 proxies = new WebService1();
proxies.AddContact(this.TextbxCreateContactFirstName.Text,
this.TextbxCreateContactMiddleName.Text,
this.TextbxCreateContactLastName.Text);
}

protected void ButtonFindUser_Click(object sender, EventArgs e)


{
WebService1 proxies = new WebService1();
DataSet ds = proxies.FindContactByFirstName(
this.TextbxFindUserFirstName.Text);
GridView2.DataSource = ds;
GridView2.DataBind();
}
}

Listing 17-12. Demonstrates the implementation of the ASP.NET code in the code behind using Visual Basic .NET

Imports System.Data
Imports WebApplicationWSConsumer.WebServiceProxies

757
The Complete Reference To Professional SOA with Visual Studio 2005

Partial Class _Default


Inherits System.Web.UI.Page

Protected Sub BtnContactByID_Click(ByVal sender As Object, _


ByVal e As System.EventArgs) Handles BtnContactByID.Click
Dim proxies As WebService1 = New WebService1
Dim ds As DataSet = proxies.SelectContactByID _
(Integer.Parse(Me.TextbxGetContactContactID.Text))
Me.GridView1.DataSource = ds
Me.GridView1.DataBind()
End Sub

Protected Sub ButtonUpdatecontact_Click(ByVal sender As Object, _


ByVal e As System.EventArgs) Handles ButtonUpdatecontact.Click
Dim proxies As WebService1 = New WebService1
proxies.UpdateContactByID(Integer.Parse(Me.txtbxContactID.Text), _
Me.txtbxFirstName.Text, Me.txtbxMiddleName.Text, _
Me.txtbxLastName.Text)
End Sub

Protected Sub ButtonRemoveContact_Click(ByVal sender As Object, _


ByVal e As System.EventArgs) Handles ButtonRemoveContact.Click
Dim proxies As WebService1 = New WebService1
proxies.RemoveContactByID(Integer.Parse _
(Me.TextbxRemoveContactContactID.Text))
End Sub

Protected Sub ButtonCreateContact_Click(ByVal sender As Object, _


ByVal e As System.EventArgs) Handles ButtonCreateContact.Click
Dim proxies As WebService1 = New WebService1
proxies.AddContact(Me.TextbxCreateContactFirstName.Text, _
Me.TextbxCreateContactMiddleName.Text, _
Me.TextbxCreateContactLastName.Text)
End Sub

Protected Sub ButtonFindUser_Click(ByVal sender As Object, _


ByVal e As System.EventArgs) Handles ButtonFindUser.Click
Dim proxies As WebService1 = New WebService1
Dim ds As DataSet = proxies.FindContactByFirstName _
(Me.TextbxFindUserFirstName.Text)
GridView2.DataSource = ds
GridView2.DataBind()
End Sub
End Class

The result of the Web application querying the Web service is shown in the figure 17-31.

758
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-31. Result from execution

Settings and Constraints


In the application designer we can also define a number of constraints. These constraints can be specified against
endpoints as well as objects. For example if we need to enable support on a Windows Server 2003 machine for a
Web Application object.

1. Select a Web service object then open the Settings and Constraints window.
2. Select the Operation System checkbox to enable it, see figure 17-32.

759
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-32. Enable Logical Server Constraint

There are different constraint settings for different objects. If we selected a Web based (either Web service
or Web content) endpoint there are a number of hosting constraints that we can specify see figure 17-33.

Figure 17-33. Hosting Constraints

System Designer
The System Designer is another designer from the Distributed System Designer suite. This allows us to
configure the actual deployment of a particular configured use of the applications but does not refer to the
deployment of the application themselves. In other words it describes the deployment of the application systems
to reflect the deployable system. For example we are to deploy the system we had built from the previous section
from the Application Designer to two separate systems where each requires a different configuration of the same
basic functions. This might be a necessary case if our Database and Web service is to be hosted internally while
the Web application can be hosted externally on a separate machine all together.
Before we begin we should clarify the meaning of a System. A System described by the System designer
defines the architectural representation of a system and how it looks within the deployed environment.
In the following examples we will be creating a System Designer using the Application Designer diagram
we had designed earlier. In this example we will be creating two environments one for the intranet where our
Database and our Web service will sit for secured internal use. Whilst our Web based application will be hosted
externally for public access.

760
The Complete Reference To Professional SOA with Visual Studio 2005

1. Start the System Designer by right clicking on the Application Designer project within the solution explorer.
2. Select “New Distributed System Diagram…” see figure 17-34.

Figure 17-34. Add a System Designer

3. This will bring up a “Add New Item” dialog window. Select Distributed System diagrams from the Categories
section and select System Diagram from the Templates section. Rename the Diagram as Internal.sd see figure
17-35.

761
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-35. Adding a System Diagram

Selecting Add will create a new designer workspace in Visual Studio, figure 17-36. A new window called
System View will also appear. This window contains all the objects that we had created in our Application
Designer.

Figure 17-36. Internal System Designer

4. Select the objects from the System View on the left hand side see figure 17-36. Drag and drop the objects onto
the work space. The system box on screen represents an implementation of the deployed internal architecture.

5. Complete the implementation by dragging the WebserviceContactManagement (Web service) and the
AdventureWorks (Database) objects onto the workspace.

6. Use the connection tool from the Toolbox to connect the objects figure 17-37.

762
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-37. Internal architecture representation.

7. Since our internal system will be protected by a firewall the only way to access the system is through a proxy
server. We can represent this using a system designer. Simply select the Web service endpoint, right click and
select Add Proxy Endpoint see figure 17-38.

Figure 17-38. Internal architecture

Now we have a complete internal representation of what we had implemented through Application designer.
To implement the external system where our Web application will be hosted follow the following steps:

8. In the solution explorer right-click Solution Items and select Add-> New Distributed System Diagram. In the
Add New Item dialog box, select System Diagram, Name it External.sd and click Add.

9. Now with a new empty work space drag and drop WebApplicationWSConsumer onto the designer.

763
The Complete Reference To Professional SOA with Visual Studio 2005

10. Right click on the Web service endpoint and select Add Proxy Endpoint.

11. Then use the connection tool from the Toolbox and select the Web content endpoint the select the edge of the
system boundry. We should have something that look like figure 17-39.

Figure 17-39. External System Diagram

Now we have two System Diagrams. To represent them on one diagram we can use a nesting technique.
Here are the steps below:

12. Create a new system diagram by right click on Solution Items and select Add-> New Distributed System
Diagram.
13. Select Distributed System Diagrams from Categories and System Diagram from Templates.

14. Enter Overall.sd as the name of the diagram.

15. Click Add

16. This will create a blank work space for a new system diagram select Internal and External from the Systems
folder under System View and drag and drop them onto the designer.

17. Then use the connection tool to link the endpoints together see figure 17-40.

764
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-40. Over all representation of internal and external System Diagram

With a nested multilevel system diagram we can easily traverse the different system diagram levels by right
clicking on a sub system diagram and selecting “Open in System Designer” see figure 17-41.

Figure 17-41. Viewing sub system diagrams

Specifying Logical Datacenter Diagram


The logical datacenter diagram allows us to create the hardware setup to run the application on. Too often
developers have developed software without considering the setup of existing infrastructure. In the following
example we will be following on from the previous examples to create a logical datacenter to host the Web
application we had created previously.

1. Right click on the Solution Items and select Add -> New Distributed System Diagram.
2. Select Distributed System Diagrams from the Categories and Logical Datacenter Diagram from the Templates.
Rename the diagram as Infrastructure.ldd figure 17-42.

765
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-42. New Logical Datacenter Diagram

3. Select Add to create a new designer.

At this point another an infrastructure logical diagram would have been created. There’re also new tools in
the Toolbox that we can use to create our infrastructure see figure 17-43.

Figure 17-43. Toolbox for Logical Datacenter Designer

Table 17-3. Tools for the Logical Datacenter

766
The Complete Reference To Professional SOA with Visual Studio 2005

Tools Description
Pointer Used to drag and drop objects on the diagram
Connection Used to connect two similar endpoints
Comment Used to add a comment to the diagram
WebSiteEndpoint Manages Serverside communication with a logical IIS web server
HTTPClientEndpoint Manages clientside communication with a logical IIS web server
DatabaseClientEndpoint Manages client-side communication with a logical database server
GenericServerEndpoint Manages server-side communication with a logical generic server
GenericClientEndpoint Manages client-side communication with a logical generic server
ZoneEndpoint Manages communication on the boundry of a zone
WindowsClient Corresponds to a Windows client or server that hosts a Windows Application
IISWebServer Corresponds to a IIS Web server
DatabaseServer Corresponds to a database server
GenericServer Corresponds to a user-defined server or component
Zone Zones can be nested. A zone corresponds to a logical boudry that is separate
from other portions of a datacenter.

Generally an infrastructure is protected through firewalls. A zone as such defines the communication boundaries
within the Logical Datacenter Designer. They are used to define communication boundaries, physical boundaries
or security boundaries.
Let’s add the internal and external zones to the designer:

1. Select the zone tool from the Toolbox and drag and drop it onto the designer surface.
2. Rename the zone by clicking on the Zone1 text and renaming it to Internal

3. Repeat the process to create an External zone see figure 17-44.

767
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-44. Zones

Now we can place the relevant servers into the zones. We can start by adding the database and the IIS web
server to the internal zone followed by an IIS web server to the external zone.

1. Select DatabaseServer tool from the Toolbox and drag and drop the tool onto the Internal zone.
2. Do the same with the IISWebServer by drag and dropping the tool onto the Internal zone.

3. Drag and drop a new IISWebServer tool to the External zone. We should have something similar to figure 17-
45.

Figure 17-45. Server setup within the zones.

Communication between zones are managed through the zone endpoints. The communications can be
inbound, outbound, or bidirectional. The arrows used between the zones are used to represent the communication
flow.
To implement connection between the zones, we will start with implementing the connection for the internal
zone. Follow the following steps:

4. Select connection tool from the Toolbox. Select the inbound arrow (>) in dark grey in the diagram and then
select one of the WebSiteEndpoint for the IISWebServer object. This will create an incoming communication
flow.
5. To create an outgoing communication flow select the outbound arrow (>) in lighter colour and select the other
not yet assigned WebSiteEndpoint in the IISWebServer.

We also need to establish a database connection from the IIS web server to the DatabaseServer.

768
The Complete Reference To Professional SOA with Visual Studio 2005

6. Select the DatabaseClientEndpoint and drag and drop the tool onto the IISWebServer.

7. Then select the connection tool from the Toolbox and select the DatabaseClientEndpoint on the IISWebServer
and then select the DatabaseServer’s DatabaseServerEndpoint.

Having completed the above steps the diagram should look similar to the figure 17-46.

Figure 17-46. Internal infrastructure with connections

8. Now to configure the connection for the External Zone. Select the connection tool then select incoming zone
endpoint connection from the Internal zone (the (>) with grey) to the outgoing zone endpoint of the External
Zone (the (>) without grey).

Tip: We can drag the Zone endpoint around the boudry of the zone object to visually improve the layout of the communication flow.

9. To connect the External IISWebServer to the communication flow. Select the connection tool then select the
WebSiteEndpoint followed by selecting the incoming zone communication endpoint.

10. To specify an outgoing communication flow from the External zone to the Internal zone select the connection
tool then select the WebSiteEndpoint of the IISWebServer followed by selecting the outgoing zone endpoint.

We also want to distinguish between the two IISWebServers. It is always a good idea to give them names
that they can be identified by individually.
11. Select the IISWebServer in the Internal Zone right click the object select properties. Rename the object to
IISWebServerInternal.

12. Select the IISWebServer in the External Zone right click the object select properties. Rename the object to
IISWebServerExternal.

13. Now we should have something similar to the figure 17-47.

769
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-47. Infrastructure

Tip: The zone endpoint can be configured as Bidirectional, Outbound and Inbound. To configure the communication flow, select an
endpoint then right click and select properties. In properties under Behavior under Communication Flow we can select from the drop down
list figure 17-48.

Figure 17-48. Communication Flow

770
The Complete Reference To Professional SOA with Visual Studio 2005

Settings and Constraints


In the Logical Datacenter Diagram we can also specify constraints for all logical servers and endpoints. For
example we can specify the security constraints for an IISWebServer. To do this simply select the object and
right click then select Settings and Constraints. Using constraints we can specify the security requirements for an
Internal IISWebServer see figure 17-49.

Figure 17-49. Constraints for IISWebServer.

Importing IIS Server Settings


Using the Logical Designer we can also import IIS settings into the settings and constraints. The logical
IISWebServer should represent the actual IISWebServer in the real infrastructure. So its important to ensure that
the constraints are correct.
To import settings:

1. Right click on the Logical Server Settings. The context menu contains an option to Import Settings see figure
17-50.

771
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-50. Import Settings

Select the option this will bring up a wizard see figure 17-51.

Figure 17-51. Import Settings

2. Select Next to continue the process. This will bring us to an IIS setting window. Incase the IIS web server is
not on the same machine as Visual Studio we can specify the necessary information in this window to connect
to the IIS Web server see figure 17-52.

772
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-52. Import Wizard

3. Once the wizard connects to the IIS Web server it may detect that we might have several Web sites specified
on our IIS Web Server. In this case it will prompt us to select which Web Site setting we want to use as a
binding setting for a WebSiteEndpoint. Once the selection is complete select Next to complete the process
figure 17-53.

Figure 17-53. Selecting Endpoint

4. We will be prompted to confirm the process before the imported setting overwrites the current settings
associated for the Endpoint figure 17-54.

773
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-54. Confirm import settings

We can see that the Logical Sever Settings is named after the server. Selecting the WebSiteEndpoint1 as the binding
endpoint we can see that the settings had been imported successfully. Below shows a screenshot of the before import
image figure 17-55 and an after image figure 17-56 for comparison.

Figure 17-55. Before import

774
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-56. New settings after import

Deployment Diagram
Deployment Diagram is the final diagram that we need to construct to consolidate all the information we had
entered into the Application Diagram, System Diagram and Logical Datacenter Diagram. It provides a means to
validate the different settings specified by that of the application architect, to the system architect to the
infrastructure architect. This process usually is extremely tedious and complicated in the real world with endless
meetings between architects. However with Visual Studio this consolidation of information and verification can
be achieved with a click of a button.
In the following example we will be implementing a deployment diagram to consolidate all of the diagrams
we had created in the previous section.

Creating the Deployment Diagram


1. Open the System Diagram Overall.sd we had created earlier.
2. Right click on the work space and select Define Deployment figure 17-57.

775
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-57. Overall System Diagram

3. This raises a Define Deployment dialog window figure 17-58. The Logical Datacenter diagram selects
Infrastructure as our default datacenter diagram. This is the same infrastructure Logical Datacenter Diagram we
had created earlier.

Figure 17-58. Define Deployment Diagram

4. Select OK to continue the process.

776
The Complete Reference To Professional SOA with Visual Studio 2005

This will result in the generation of an Overall1.dd deployment diagram see figure 17-59 below.

Figure 17-59. Generated Deployment Diagram

Once the deployment diagram has been created we need to associated the infrastructure that we had
specified with actual applications that will reside on them.
There are two ways to associate applications to infrastructures the easiest way is simply selecting the
application we’re interested in and drag and dropping them into the relevant application figure 17-60.

Figure 17-60. Drag and drop application to server binding.

If this results in an incorrect binding between application and server then a cross will be shown figure 17-61.

777
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-61. Incompatiable

Alternatively we can use the Bind Application option to associate application to server:

5. We can do this by right click on the WebApplicationWSConsumer application then selecting Bind Application
figure 17-62.

Figure 17-62. Bind Application

A bind application to logical server dialog window will appear.

Figure 17-63. Selecting a logical server

6. Because the web service consumer is situated outside on the external infrastructure we will select
IISWebServerExternal (this is the name of the IIS Web server we had specified in Logical Datacenter
Designer). The application is now associated with the logical server see figure 17-64.

778
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-64. Associated application and logical server

7. Do the same for WebserviceContactManagement application by right click on the application and selecting
Bind Application. The designer is smart enough to work out that there is only one web server that can host the
WebserviceContactManagement application and that’s using the IIS Web server in the Internal Zone see figure
17-65.

Figure 17-65. Selecting logical server

8. Do the same process to AdventureWorks Database application by right click on the database application and
selecting Bind Application. Select the Database server that’s shown see figure 17-66.

Figure 17-66. Selecting a Database Server

Once the process is complete all the application under the System View window should be shown as
<Bound> see figure 17-67 below.

779
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-67. System View

Each of the logical servers in the deployment diagram also shows to have an application to have bound to
them figure 17-68.

Figure 17-68. Deployment Diagram

Validating the Deployment Scenario


After we have created the deployment diagram. We can validate our deployment secenario against the settings
and constraints that what we had specified through the different designers.
To start the validation process simply right click on the deployment designer work space and select Validate
Diagram figure 17-69.

780
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-69. Validate Diagram

The Error List window will display any errors or warnings that Visual Studio will come across as being
inconsistent between the diagrams see figure 17-70.

Figure 17-70. Error List

To check what actually resulted in the warning. Simply double click on the warning to view the
inconsistency. In this case the two IIS Web application settings are inconsistent. We’re brought to the System
Diagram which resulted in the inconsistency. The object in question now has a red cross on the diagram, figure
17-71.

781
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-71. Inconsistency in diagram is marked with a red cross

After double clicking on the warning message in the Error List window. A dialog window appears it shows
where the inconsistency is located. In this case it is the authentication mode. As with the connecting web service
we have specified an authentication mode of none. Whilst the current IIS web server requires Windows
authentication mode. To rectify the warning simply set the Mode from Windows to None.
Then save the changes on the solution designer.

Figure 17-72. Modifying settings and constraints.

Going back to the deployment designer right click on the screen and select Validate Diagram again to make
sure that there is no more errors left, figure 17-73.

782
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-73. Error List

Generating Deployment Report


After we have created a valid deployment diagram. We can generate a deployment report. The report generation
feature is particularly handy, as it provides the means to document everything within the architecture for
reference at a later date. Generating the report is very simple. Follow the following steps:

1. Right click on the deployment diagram and select Generate Deployment Report figure 17-74.

Figure 17-74. Generate Deployment Report

The Overall1 HTML report is generated. It’s a large document which contains all system diagrams and
logical datacenter diagrams as well as all details on endpoints, resources and settings see figure 17-75.

783
The Complete Reference To Professional SOA with Visual Studio 2005

Figure 17-75. Infrastructure deployment report.

We can also view this document in the web browser simply right click on the document and select View in
Browser.

Summary
In this chapter we have learnt how to conceptually represent diagrams using the four designers from the
Distributed Systems Designer suite: Application Designer, System Designer, Logical Datacenter Designer and
Deployment Designer.
The application designer can be used to construct diagrams that represent the actual software system. We
can represent different types of application using the application designer then using the connection tool to
establish the links between the systems.
The system designer can be used to configure the deployment view of a particular use of the actual
application system. Using the diagrams that we have configured in the system designer we can also specify the
logical datacenter diagram. This diagram represents the infrastructure of a datacenter.
Once the diagrams had been completed we can consolidate all the information acquired into a deployment
diagram. This is where application systems are consolidated to specific logical servers. Through the deployment
diagram we can validate settings and constraints that we had specified at different levels of the diagram. From
the deployment diagram we can also generate a deployment report. The report contains all information about the
deployable components and infrastructures. It is a very detailed report that can be used as reference in future.

784
The Complete Reference To Professional SOA with Visual Studio 2005

Indexes

& C
&amp; .........................................................................137
&apos; .........................................................................137 CacheDuration .................................................... 419, 424
&gt; .............................................................................137 Call Stack Window ..................................................... 362
&lt; ..............................................................................137 CDATA ...................................................................... 138
&quot; .........................................................................137 CDATA sections......................................................... 138
Choreography ............................................................... 53
Cities............................................................................. 24
. Class View.................................................................. 114
ClickOnce ........................................................... 399, 403
.NET Data Provider.....................................................189 Code Coverage............................................................ 378
.NET DataSets.............................................................185 ColumnChanged ......................................................... 218
.NET Deployment .......................................................389 ColumnChanging........................................................ 218
.NET Framework.........................................................100 Command.................................................................... 186
.NET Framework 2.0...................................................103 Common Language Runtime (CLR)........................... 102
.NET Framework class libraries ..................................101 Common Type System (CTS)..................................... 102
.NET Serialization.......................................................271 Confidentiality .............................................................. 61
.NET Web Service Message Flow...............................124 Connected System Strategy .......................................... 71
.NET XML Serialization .............................................271 Connection.................................................................. 186
ConnectionString ........................................................ 190
A Continuous Track.......................................................... 86
Controlled code sharing .............................................. 389
ADO.NET ...................................................................182 Controlling Serialization............................................. 282
ADO.NET DataSet Events ..........................................218 Coordination Services................................................... 55
ADO.NET DataSets ....................................................213 Copying DataSet Contents.......................................... 216
Advanced Web Service Programming ........................419 Creating Data Views ................................................... 217
Application Proxy .........................................................68 Creating XML Web Services...................................... 316
Architectural Tradeoff Matrix .......................................26 Cross Entities Query ..................................................... 52
Architectural Tradeoff Triangle ....................................26
Assembly Information.................................................390
Asymmetric (Public) Key Encryption ...........................65 D
Async Data Access......................................................183 Data Adapters ............................................................. 195
Asynchronous Web service .........................................432 Data Encoding ............................................................ 161
Attributes and Namespaces .........................................136 Data Providers ............................................................ 186
Authentication...............................................................60 DataAdapter................................................................ 187
Authorization ................................................................60 Data-Centric Services ................................................... 48
Autos Window ............................................................362 DataReader ......................................................... 186, 197
DataRow ..................................................................... 208
B DataSet........................................................................ 207
DataTable.................................................................... 207
Basic services ................................................................48 Datatype picker ........................................................... 155
BEA ..............................................................................45 Date............................................................................. 143
BeginExecuteReader ...................................................183 dateTime ..................................................................... 144
BeginExecuteXmlReader ............................................183 decimal........................................................................ 144
binding ........................................................................177 definitions ................................................................... 175
Boolean .......................................................................143 DeleteCommand ......................................................... 196
Breakpoint Window ....................................................363 Deploying Track ........................................................... 85
Budget Consideration....................................................81 Deployment ................................................................ 389
Buffering .....................................................................419 Description.................................................................. 419
BufferResponse ...........................................................419 Description for a Web Method.................................... 425
Business and IT.............................................................80 Developing Track ......................................................... 84
Business Benefits of SOA .............................................27 Distributed Event Driven Architecture and SOA........ See
Business Process Execution Language for Web Services EDA
(BPEL4WS).............................................................54 Document.................................................................... 114
Byte .............................................................................143 Document Object Model............................................. 240

785
The Complete Reference To Professional SOA with Visual Studio 2005

DocumentType............................................................242 integer ......................................................................... 145


double..........................................................................144 Integrity ........................................................................ 61
duration .......................................................................144 Internal Politics............................................................. 80
Inter-Platform Connection ............................................ 76
Invoking Web Method using .NET HTTP POST, GET
E and SOAP .............................................................. 164
EDA ..............................................................................55 IsClosed ...................................................................... 199
Elements......................................................................134 IT Cost Savings............................................................. 74
EnableSession .....................................................419, 427 IT Infrastructure Evolution ........................................... 25
EndExecuteNonQuery.................................................183 Iterative Quality Assurance........................................... 47
EndExecuteReader ......................................................183
EndExecuteXmlReader ...............................................183 J
Enterprise Application Integration (EAI) ......................52
Enterprise Architecture .................................................25 Just-In-Time (JIT)....................................................... 102
Enterprise Service Bus & Services................................56
Entity Aggregation ........................................................50
enumeration.................................................................149
L
Envisioning Track .........................................................84 language...................................................................... 146
Error list ......................................................................141 Language constructs ................................................... 153
Error List.....................................................................113 Legacy Enterprise Architecture .................................... 33
ESB ......................See Enterprise Service Bus & Services length .......................................................................... 150
ExecuteReader ............................................................183 list 154
ExecuteScalar..............................................................193 Locals Window........................................................... 362
ExpectedExceptionAttribute .......................................377 Logical Layers to Physical Tiers................................... 49
Logic-Centric Services ................................................. 48
F long............................................................................. 146
Loose Coupling............................................................. 29
Facets ..........................................................................149
Factories........................................................................24
fractionDigits ..............................................................150
M
managed applications.................................................. 102
G Managed Development ............................................... 102
Manipulating XML with .NET ................................... 240
Gathering Internal Support............................................81 Manually Creating a Typed Dataset............................ 220
gDay............................................................................144 Manufactured................................................................ 24
GET and POST ...........................................................128 maxExclusive.............................................................. 150
GetFileBuffered()........................................................424 maxInclusive............................................................... 150
GetFileUnbuffered()....................................................424 maxLength .................................................................. 151
GetResponse................................................................170 Measuring a SOA ......................................................... 78
global.asax ..................................................................115 message....................................................................... 176
gMonth........................................................................144 Message Reliability....................................................... 68
gMonthDay .................................................................145 MessageName..................................................... 419, 429
Governance ...................................................................85 Metropolis..................................................................... 23
gYear...........................................................................145 minExclusive .............................................................. 151
gYearMonth ................................................................145 minInclusive ............................................................... 151
minLength................................................................... 152
minOccurs................................................................... 157
H MSF .............................................................................. 81
hexBinary ....................................................................145 MSF Agile .................................................................... 83
Horizontal Partitions .....................................................51 MSF Risk Management ................................................ 90
HTTP ..........................................................................126 MSF Tracks .................................................................. 82
HTTP With .NET........................................................130
HttpWebRequest .........................................................130 N
HttpWebResponse...............................................130, 170
Hyper Text Transfer Protocol (HTTP) ........................124 Name........................................................................... 146
namespaces ................................................................. 135
NCName ............................................................. 135, 146
I negativeInteger ........................................................... 146
Implementing Sampling ..............................................382 NMTOKEN ................................................................ 157
Initializing and Cleaning Up Tests ..............................379 No-impact deployment.............................................. 389
InsertCommand ...........................................................195 noNamespaceSchemaLocation ................................... 156
Instrumentation ...........................................................382 nonNegativeInteger..................................................... 147
int 145 nonPositiveInteger ...................................................... 147

786
The Complete Reference To Professional SOA with Visual Studio 2005

Non-repudiation ............................................................61 SelectCommand .......................................................... 195


normalizedString.........................................................147 SerializableClass......................................................... 279
Numeric types .............................................................142 Serialization Formatter ............................................... 273
Serializing Arrays ....................................................... 293
Server Explorer........................................................... 113
O service......................................................................... 178
OdbcDataAdapter........................................................187 Service Oriented Architecture....................................... 23
OdbcDataReader .........................................................187 Service Oriented Enterprise Architecture ..................... 33
OLE DB Data Provider in .NET .................................189 Service Types................................................................ 48
OleDBAuthors ............................................................190 Services......................................................................... 30
OleDbCommand .........................................................192 Session State ............................................................... 427
OleDbConnection................................................189, 190 short ............................................................................ 148
OleDbDataAdapter......................................................187 Simple Object Access Protocol (SOAP) ..................... 159
OleDbDataReader ...............................................187, 199 simpleType ................................................................. 153
Open Schema ..............................................................310 Single View of Entity ................................................... 50
Opening and Closing Connections ..............................190 SOA Architectural Roadmap ........................................ 44
Operational Management ..............................................86 SOA Driven Project Development......................See MSF
OracleDataAdapterfor .................................................187 SOA future vision ......................................................... 46
OracleDataReader .......................................................187 SOA Governance .......................................................... 47
Orchestration................................................................53 SOA maturity assessment ............................................. 46
Organization Vision ......................................................80 SOA planning ............................................................... 46
Organizational Roadmap...............................................79 SOA roadmap definition............................................... 47
Overloaded ..................................................................429 SOAP .................................................................... 31, 159
SOAP Body ................................................................ 160
SOAP Fault................................................................. 161
P SOAP Header.............................................................. 160
pattern .........................................................................152 SOAP Interceptor.......................................................... 66
Planning Track ..............................................................84 SOAP Message Monitoring .......................................... 65
Point-to-Point vs End-to-End Security..........................61 SOAP Request ............................................................ 161
portType ......................................................................177 SOAP Response.......................................................... 162
positiveInteger.............................................................147 SOAP via HTTP ......................................................... 162
Primary Keys...............................................................215 Solution Explorer........................................................ 113
Profiling ......................................................................381 SqlCommand.ExecuteXmlReader .............................. 184
Program Management ...................................................87 SqlCommandBuilder .................................................. 210
Project Conversion Report ..........................................111 SqlConnection Class ................................................... 190
Project Conversion Wizard .........................................111 SqlDataAdapter........................................................... 210
Project Teams................................................................86 SqlDataReader ............................................................ 198
Properties ....................................................................113 SqlTruncateException................................................. 228
Public Services ..............................................................49 SqlUdt......................................................................... 184
Publishing ...................................................................399 Stabilizing Track........................................................... 85
Standardization ............................................................. 24
Static Analysis ............................................................ 380
Q StreamReader.............................................................. 130
StreamWriter............................................................... 130
QName ........................................................................147
string ........................................................................... 148
Strongly Typed XML Serialization............................. 299
R Support for digital signature ....................................... 180
Symmetric Key Encryption........................................ 65
RecordsAffected..........................................................199 System.Data.SqlTypes ................................................ 184
Relationships with Typed Dataset ...............................227 System.Runtime.Serialization.Formatters.Soap.......... 276
restriction ....................................................................153 System.Xml.Serialization ........................................... 279
RowChanged...............................................................218
RowChanging..............................................................219
RowDeleted.................................................................219 T
RowDeleting ...............................................................219
TableCleared............................................................... 219
TableClearing ............................................................. 219
S TableNewRow ............................................................ 219
Task List ............................................................. 114, 118
SAML ...................................................................67, 181 Technology Soup .......................................................... 33
Sampling .....................................................................381 Test Plan ..................................................................... 354
schemaLocation...........................................................156 TestCleanupAttribute.................................................. 379
Security Basics ..............................................................60 TestInitializeAttribute................................................. 379
Security in Service Oriented Architecture.....................60 Tests............................................................................ 376
Security with Federation ...............................................66

787
The Complete Reference To Professional SOA with Visual Studio 2005

time .............................................................................148 WriteXmlSchema ....................................................... 266


token............................................................................148 WS-* Standards .......................................................... 180
Toolbox.......................................................................113 WSDL................................................................... 31, 178
totalDigits....................................................................152 WS-Federation............................................................ 180
TransactionOption.......................................................419 WS-Policy................................................................... 180
Transitional Services .....................................................49 WS-PolicyAttachment ................................................ 181
Transportation ...............................................................24 WS-SecureConversation ............................................. 180
Typed ADO.NET DataSet...........................................219 WS-Security.......................................................... 64, 180
types ............................................................................175 WS-SecurityPolicy...................................................... 180
WS-Trust .................................................................... 180
U
X
UDDI.............................................................................32
UDDI SDK..................................................................180 XACML...................................................................... 181
UDDI v3......................................................................179 XCOPY....................................................................... 389
Union ..........................................................................154 XKMS......................................................................... 181
unmanaged applications ..............................................102 XML ........................................................................... 134
unsignedByte...............................................................148 XML and DataSet ....................................................... 266
unsignedInt..................................................................148 XML and XML Schema ............................................... 30
unsignedLong..............................................................149 XML Comments ......................................................... 136
unsignedShort..............................................................149 XML Datatypes .......................................................... 142
UpdateCommand.........................................................196 XML Date and time types........................................... 142
Urban Infrastructure ......................................................25 XML declaration......................................................... 138
Using Web Deployment Projects ................................404 XML Encryption........................................................... 64
XML Name and string types....................................... 143
XML Parser ................................................................ 247
V XML Prohibited character literals............................... 137
ValidationType............................................................266 XML Schema.............................................................. 155
Virtual Enterprises ........................................................25 XML Schema Definition (XSD) ................................. 141
Visual Studio 2005 Editions........................................105 XML Schema Structures............................................. 155
Visual Studio 2005 Express Editions ..........................105 XML Serialization ...................................................... 279
Visual Studio 2005 Professional Edition.....................106 XML Signature ............................................................. 65
Visual Studio 2005 Projectless Development..............110 XML Validation.......................................................... 262
Visual Studio 2005 Standard Edition ..........................105 XML Web service....................................................... 124
Visual Studio 2005 Team Edition for Software Architects XML Web Services ...................................................... 30
...............................................................................104 XML Whitespace........................................................ 137
Visual Studio 2005 Team Edition for Software XmlAnyAttribute................................................ 296, 310
Developers .............................................................105 XmlAnyElement ................................................. 296, 310
Visual Studio 2005 Team Edition for Software Testers XmlAttribute............................................................... 242
...............................................................................105 XML-Data Reduced (XDR)........................................ 262
Visual Studio 2005 Team Foundation Server..............105 XmlDocument............................................................. 242
Visual Studio 2005 Team Roles ..................................104 XmlDocumentFragment ............................................. 242
Visual Studio 2005 Team Suite...................................105 XmlDocumentType .................................................... 242
Visual Studio 2005 Team System ...............................388 XmlElement........................................................ 242, 283
Visual Studio IDE .......................................................112 XmlEntity ................................................................... 242
Visual Studio Windows...............................................113 XmlEntityReference ................................................... 242
XmlInclude ................................................................. 297
XmlNodeType ............................................................ 252
W XmlNotation ............................................................... 242
Watch Window ...........................................................361 XmlProcessingInstruction........................................... 242
Web Server Description Language (WSDL)...............103 XmlReader.................................................................. 249
Web Service ..........................................................28, 315 XmlRoot ..................................................................... 283
Web Service Authentication..........................................63 XMLSchemainstance.................................................. 155
Web Service Choreography Interface (WSCI) ..............53 XmlSchemaSet’s......................................................... 266
Web Service Management Orchestration ......................59 XmlTextReader........................................................... 250
Web service technology stack .....................................124 XMLTextReader......................................................... 252
Web Service Template ................................................106 XmlWriter................................................................... 249
Web Services Description Language (WSDL)............175 XPath .................................................................... 30, 256
Web Setup Project.......................................................414 XPathNavigator .......................................................... 255
web.config...................................................................114 XPathNodeType ......................................................... 257
Well-formed XML ......................................................138 xs:sequence ................................................................. 140
whiteSpace ..................................................................153 XSD .................................................................... 158, 259

788

You might also like