the complete reference to professional soa with visual studio 2005 dot net 3.0

789

Upload: varunkaushish

Post on 14-Nov-2014

203 views

Category:

Documents


40 download

DESCRIPTION

SOA with Visual Studio 2005 .

TRANSCRIPT

Page 1: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0
Page 2: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA With Visual Studio 2005 (C# & VB 2005) .NET 3.0

Tom Yuan Gao

Page 3: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

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.

Page 4: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

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.

Page 5: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

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)

Page 6: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

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.”

Page 7: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

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

Page 8: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

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!

Page 9: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

Sondre Bjellås

Microsoft Regional Director

Software Architect & Product Manager

Page 10: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

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

Page 11: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

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

Page 12: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

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

Page 13: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

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

Page 14: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

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

Page 15: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

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

Page 16: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

.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

Page 17: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

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

Page 18: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

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

Page 19: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

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

Page 20: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

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

Page 21: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

20

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.

Page 22: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

21

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.

Page 23: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

22

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

Page 24: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

23

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.

Page 25: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

24

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.

Page 26: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

25

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

Page 27: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

26

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.

Page 28: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

27

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.

Page 29: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

28

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

Page 30: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

29

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

Page 31: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

30

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

Page 32: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

31

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

Page 33: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

32

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.

Page 34: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

33

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.

Page 35: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

34

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.

Page 36: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

35

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.

Page 37: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

36

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.

Page 38: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

37

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.

Page 39: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

38

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,

Page 40: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

39

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.”

Page 41: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

40

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

Page 42: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

41

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

Page 43: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

42

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.

Page 44: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

43

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

Page 45: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

44

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

Page 46: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

45

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.

Page 47: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

46

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

Page 48: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

47

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.

Page 49: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

48

* 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

Page 50: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

49

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.

Page 51: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

50

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

Page 52: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

51

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.

Page 53: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

52

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.

Page 54: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

53

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.

Page 55: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

54

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.

Page 56: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

55

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.

Page 57: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

56

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

Page 58: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

57

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

Page 59: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

58

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.

Page 60: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

59

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

Page 61: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

60

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

Page 62: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

61

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.

Page 63: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

62

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.

Page 64: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

63

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.

Page 65: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

64

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.

Page 66: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

65

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.

Page 67: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

66

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

Page 68: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

67

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

Page 69: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

68

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.

Page 70: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

69

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.

Page 71: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

70

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

Page 72: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

71

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.

Page 73: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

72

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.

Page 74: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

73

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

Page 75: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

74

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

Page 76: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

75

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 aside for pedestrians (CA, GB, HK)

paved surface of road (US)

biscuit (noun) A crisp, generally sweet, confection (AU, GB, HK, ZA)

Soft, flakey savoury pastry eaten with gravy (US)

corn (noun) Grain, or a cereal crop, as in “cornfield” (GB)

Maize (AU, CA, US)

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

To abandon a proposal (US)

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.

Page 77: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

76

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.

Page 78: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

77

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.

Page 79: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

78

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.

Page 80: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

79

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.

Page 81: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

80

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.

Page 82: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

81

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.

Page 83: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

82

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,

Page 84: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

83

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

Page 85: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

84

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.

Page 86: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

85

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).

Page 87: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

86

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:

Page 88: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

87

* 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.

Page 89: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

88

* 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.

Page 90: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

89

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.

Page 91: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

90

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

Page 92: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

91

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

Page 93: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

92

* 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

Page 94: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

93

* 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.

Page 95: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

94

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.

Page 96: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

95

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

Page 97: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

96

//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();

Page 98: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

97

} [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

Page 99: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

98

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.

Page 100: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

99

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.

Page 101: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

100

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).

Page 102: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

101

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”.

Page 103: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

102

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.

Page 104: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

103

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.

Page 105: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

104

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

Page 106: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

105

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.

Page 107: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

106

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

Page 108: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

107

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.

Page 109: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

108

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

Page 110: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

109

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,

Page 111: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

110

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

Page 112: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

111

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.

Page 113: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

112

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

Page 114: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

113

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.

Page 115: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

114

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.

Page 116: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

115

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.

Page 117: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

116

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.

Page 118: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

117

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'.

Page 119: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

118

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.

Page 120: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

119

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.

Page 121: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

120

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.

Page 122: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

121

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

Page 123: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

122

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.

Page 124: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

123

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

Page 125: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

124

{ 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.

Page 126: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

125

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

Page 127: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

126

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.

Page 128: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

127

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.

Page 129: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

128

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.

Page 130: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

129

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

Page 131: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

130

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.

Page 132: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

131

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

Page 133: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

132

.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:

Page 134: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

133

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.

Page 135: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

134

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

Page 136: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

135

* 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

Page 137: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

136

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"/>

Page 138: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

137

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.

Page 139: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

138

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

Page 140: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

139

{ 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"

Page 141: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

140

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.

Page 142: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

141

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.

Page 143: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

142

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

Page 144: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

143

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.

Page 145: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

144

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

Page 146: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

145

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.

Page 147: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

146

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>

Page 148: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

147

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.

Page 149: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

148

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.

Page 150: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

149

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.

Page 151: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

150

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.

Page 152: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

151

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

Page 153: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

152

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.

Page 154: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

153

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.

Page 155: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

154

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>

Page 156: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

155

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'/>

Page 157: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

156

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>

Page 158: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

157

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>

Page 159: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

158

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.

Page 160: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

159

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

Page 161: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

160

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>

Page 162: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

161

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' >

Page 163: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

162

<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

Page 164: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

163

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>

Page 165: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

164

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.

Page 166: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

165

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>

Page 167: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

166

<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>

Page 168: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

167

<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"

Page 169: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

168

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.

Page 170: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

169

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>

Page 171: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

170

</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>

Page 172: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

171

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"

Page 173: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

172

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.

Page 174: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

173

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.

Page 175: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

174

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) {

Page 176: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

175

//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();

Page 177: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

176

} 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;

Page 178: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

177

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/" + _

Page 179: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

178

"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

Page 180: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

179

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()

Page 181: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

180

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) {

Page 182: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

181

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>

Page 183: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

182

<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);

Page 184: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

183

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

Page 185: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

184

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

Page 186: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

185

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

Page 187: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

186

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"

Page 188: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

187

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">

Page 189: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

188

<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>

Page 190: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

189

<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" />

Page 191: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

190

</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

Page 192: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

191

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.

Page 193: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

192

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.

Page 194: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

193

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.

Page 195: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

194

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

Page 196: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

195

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

Page 197: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

196

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.

Page 198: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

197

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.

Page 199: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

198

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:

Page 200: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

199

* 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.

Page 201: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

200

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.

Page 202: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

201

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.

Page 203: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

202

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

Page 204: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

203

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)

Page 205: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

204

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;

Page 206: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

205

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();

Page 207: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

206

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();

Page 208: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

207

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"

Page 209: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

208

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.

Page 210: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

209

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);

Page 211: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

210

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

Page 212: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

211

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.

Page 213: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

212

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.

Page 214: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

213

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.

Page 215: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

214

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)

Page 216: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

215

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.

Page 217: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

216

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.

Page 218: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

217

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.

Page 219: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

218

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.

Page 220: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

219

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

Page 221: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

220

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);

Page 222: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

221

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;

Page 223: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

222

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.

Page 224: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

223

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

Page 225: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

224

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);

Page 226: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

225

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";

Page 227: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

226

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)

Page 228: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

227

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

Page 229: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

228

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.

Page 230: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

229

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.

Page 231: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

230

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.

Page 232: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

231

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

Page 233: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

232

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)

Page 234: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

233

{ 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

Page 235: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

234

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:

Page 236: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

235

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.

Page 237: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

236

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

Page 238: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

237

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.

Page 239: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

238

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.

Page 240: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

239

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.

Page 241: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

240

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

Page 242: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

241

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

Page 243: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

242

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.

Page 244: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

243

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) {

Page 245: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

244

... } 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 ...

Page 246: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

245

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.

Page 247: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

246

* 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

Page 248: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

247

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.

Page 249: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

248

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) {

Page 250: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

249

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.

Page 251: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

250

Figure 6-44 build the project.

And deploy

Figure 6-45 deploy the project

Page 252: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

251

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:

Page 253: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

252

>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)

Page 254: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

253

{ // 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

Page 255: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

254

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

Page 256: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

255

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

Page 257: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

256

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.

Page 258: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

257

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>

Page 259: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

258

</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" />

Page 260: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

259

</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 Class

A temporary bag containing one or more nodes 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.

Page 261: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

260

ProcessingInstruction XmlProcessingInstruction Class

Is a processing instruction node.

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

Page 262: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

261

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>

Page 263: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

262

<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.

Page 264: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

263

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

Page 265: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

264

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 {

Page 266: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

265

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()

Page 267: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

266

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.

Page 268: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

267

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

Page 269: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

268

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)

Page 270: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

269

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(); } } }

Page 271: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

270

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.

Page 272: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

271

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

Page 273: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

272

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(); } } }

Page 274: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

273

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.

Page 275: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

274

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

Page 276: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

275

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

Page 277: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

276

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)

Page 278: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

277

{ 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

Page 279: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

278

<?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

Page 280: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

279

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()

Page 281: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

280

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");

Page 282: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

281

// 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>

Page 283: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

282

<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;

Page 284: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

283

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

Page 285: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

284

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.

Page 286: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

285

Method Description

GetXml This method allows us to retrieve the XML representation of the data stored in a DataSet in a string variable.

GetXmlSchema This method allows us to retrieve the XSD schema for the XML representation of 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");

Page 287: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

286

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>

Page 288: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

287

<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" />

Page 289: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

288

<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

Page 290: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

289

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.

Page 291: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

290

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; }

Page 292: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

291

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

Page 293: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

292

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) {

Page 294: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

293

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

Page 295: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

294

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.

Page 296: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

295

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;

Page 297: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

296

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();

Page 298: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

297

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()

Page 299: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

298

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.

Page 300: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

299

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);

Page 301: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

300

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

Page 302: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

301

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"

Page 303: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

302

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.

Page 304: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

303

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) {

Page 305: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

304

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

Page 306: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

305

<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 = _

Page 307: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

306

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) .

Page 308: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

307

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))> _

Page 309: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

308

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;

Page 310: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

309

} 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);

Page 311: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

310

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

Page 312: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

311

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()

Page 313: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

312

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;

Page 314: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

313

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)

Page 315: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

314

_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)> _

Page 316: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

315

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.

Page 317: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

316

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.

Page 318: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

317

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

Page 319: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

318

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()> _

Page 320: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

319

<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

Page 321: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

320

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">

Page 322: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

321

<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

Page 323: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

322

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")]

Page 324: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

323

[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/>

Page 325: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

324

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()]

Page 326: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

325

[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;

Page 327: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

326

/// <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; }

Page 328: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

327

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

Page 329: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

328

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

Page 330: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

329

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)> _

Page 331: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

330

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/>

Page 332: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

331

<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

Page 333: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

332

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.

Page 334: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

333

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; } }

Page 335: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

334

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

Page 336: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

335

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" />

Page 337: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

336

<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.

Page 338: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

337

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):

Page 339: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

338

* 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:

Page 340: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

339

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.

Page 341: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

340

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]

Page 342: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

341

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

Page 343: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

342

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

Page 344: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

343

<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

Page 345: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

344

)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]

Page 346: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

345

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.

Page 347: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

346

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;

Page 348: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

347

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]

Page 349: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

348

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,

Page 350: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

349

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

Page 351: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

350

("@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", _

Page 352: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

351

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.

Page 353: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

352

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.

Page 354: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

353

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" />

Page 355: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

354

<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

Page 356: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

355

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.

Page 357: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

356

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

Page 358: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

357

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.

Page 359: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

358

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.

Page 360: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

359

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.

Page 361: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

360

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

Page 362: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

361

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>

Page 363: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

362

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>

Page 364: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

363

<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

Page 365: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

364

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}); } . .

Page 366: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

365

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.

Page 367: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

366

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”.

Page 368: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

367

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”

Page 369: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

368

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”

Page 370: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

369

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.

Page 371: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

370

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

Page 372: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

371

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

Page 373: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

372

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>

Page 374: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

373

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();

Page 375: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

374

}

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>

Page 376: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

375

</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.

Page 377: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

376

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.

Page 378: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

377

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.

Page 379: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

378

* 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.

Integration testing During integration testing, we combine the functions that had already been 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

Page 380: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

379

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

Page 381: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

380

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.

Page 382: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

381

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] | [[ class::] function [:offset]]

Using the break command we can set or displays 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

Page 383: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

382

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

We can specify several options:

list command can be used to displays a list of loaded modules, classes, or global functions.

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.

Page 384: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

383

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

Page 385: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

384

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

Page 386: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

385

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: {

Page 387: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

386

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.

Page 388: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

387

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

Page 389: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

388

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

Page 390: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

389

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.

Page 391: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

390

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.

Page 392: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

391

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]

Page 393: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

392

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

Page 394: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

393

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.

Page 395: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

394

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.

Page 396: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

395

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]

Page 397: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

396

'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.

Page 398: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

397

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;

Page 399: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

398

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 //

Page 400: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

399

//[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()

Page 401: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

400

{ 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>

Page 402: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

401

<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>

Page 403: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

402

<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

Page 404: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

403

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()]

Page 405: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

404

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

Page 406: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

405

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.

Page 407: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

406

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.

Page 408: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

407

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.

Page 409: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

408

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.

Page 410: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

409

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.

Page 411: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

410

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.

Page 412: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

411

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.

Page 413: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

412

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...

Page 414: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

413

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).

Page 415: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

414

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.

Page 416: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

415

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.

Page 417: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

416

* 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.

Page 418: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

417

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.

Page 419: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

418

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>

Page 420: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

419

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”.

Page 421: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

420

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.

Page 422: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

421

' 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).

Page 423: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

422

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

Page 424: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

423

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.

Page 425: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

424

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).

Page 426: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

425

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

Page 427: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

426

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

Page 428: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

427

Update from Web Yes No

Does not affect shared components or other applications

Yes No

Security permissions granted Grants only permissions necessary for the application (more safe)

Grants Full Trust by default (less safe)

Security permissions required Internet or Intranet Zone (Full Trust for CD-ROM installation)

Administrator

Application and deployment manifest signing

Yes No

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).

Page 429: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

428

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.

Page 430: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

429

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.

Page 431: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

430

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.

Page 432: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

431

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

Page 433: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

432

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.

Page 434: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

433

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 8\Common7\Packages

MsWebDeployProj.dll

WebDeploy.wdproj

Page 435: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

434

C:\Program Files\Microsoft Visual Studio 8\Common7\Packages\1033

MsWebDeployProjUi.dll

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.

Page 436: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

435

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

Page 437: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

436

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 source input

During compilation, if there are sub-Web sites this will result in build errors. 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 be updatable

This option is used for ASP.NET Web form. It allows HTML component of 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

Page 438: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

437

Setting Description

Merge all outputs to a single assembly

This option merges all output assemblies from the compiler into a single 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 output to its own assembly

This option will create a separation output assembly for each folder. This allows us to update a Web Project at the folder level rather than the entire application.

Merge all pages and controls to a single assembly

This option merges all output assemblies for all pages and user controls in a Web project into a single assembly. We can use the assembly to update UI components separately.

Create a separate assembly for each page and control output

This option creates separate assemblies for each page and user control.

Version Output Assemblies

Assembly Version

File Version

Selecting Version Output Assembly will enable the Asembly Version and File Version. We can set the Assembly Version and File Version in the following format. The format is 0.0.0.0.

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.

Page 439: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

438

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 AllowPartiallyTrustedCallersAttribute (APTCA).

This allows types in the strongly named assembly to be called by partially trusted code only when the assembly is marked with 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 replacement

By enabling the Web.config file section replacement we can replace any 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.

Page 440: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

439

Enforce matching section replacements

This option requires that the specified section in the Web.config file 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 output folder

This option when selected will automatically create an IIS virtual directory 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 the output location

This option removes the App_Data from the precompiled image of the 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.

Page 441: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

440

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.

Page 442: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

441

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

Page 443: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

442

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\Release

Employee.asmx

PrecompiledApp.config

web.config

C:\Projects\Book\SourceCode\Ch11\Employee_deploy\Release\bin

App_Code.compiled

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.

Page 444: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

443

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).

Page 445: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

444

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).

Page 446: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

445

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

Page 447: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

446

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).

Page 448: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

447

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.

Page 449: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

448

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.

Page 450: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

449

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();

Page 451: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

450

} } 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; }

Page 452: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

451

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")> _

Page 453: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

452

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

Page 454: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

453

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;

Page 455: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

454

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

Page 456: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

455

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

Page 457: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

456

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.

Page 458: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

457

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.

Page 459: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

458

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

Page 460: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

459

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

Page 461: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

460

<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

Page 462: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

461

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(); } }

Page 463: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

462

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.

Page 464: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

463

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).

Page 465: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

464

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#

Page 466: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

465

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

Page 467: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

466

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();

Page 468: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

467

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

Page 469: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

468

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);

Page 470: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

469

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.

Page 471: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

470

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

Page 472: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

471

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); }

Page 473: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

472

} 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

Page 474: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

473

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#

Page 475: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

474

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 =

Page 476: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

475

((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 = _

Page 477: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

476

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.

Page 478: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

477

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

Page 479: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

478

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).

Page 480: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

479

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) {

Page 481: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

480

// 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

Page 482: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

481

// 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; } }

Page 483: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

482

}

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

Page 484: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

483

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, _

Page 485: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

484

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

Page 486: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

485

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

Page 487: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

486

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)

Page 488: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

487

{ // 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

Page 489: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

488

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

Page 490: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

489

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)]

Page 491: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

490

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

Page 492: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

491

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).

Page 493: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

492

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

Page 494: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

493

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.

Page 495: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

494

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 HTTP.

.NET Remoting can be used across three channels TCP, HTTP, IPC. and two formatters SOAP and Binary.

Web services work in a stateless environment. Each request results in a new object created to service the request.

.NET Remoting supports state management options and can associate multiple calls from the same client. Remoting model also support Asynchronous callbacks.

Web services serialize objects into XML that is contained in the SOAP message and as such can only handle items that can be fully expressed in XML.

.NET Remoting relies the Common Language Runtime assemblies that contain information about data types. This allows objects to be passed by value or by reference.

Web services are interoperable across platforms and are good for environment that consists of different technologies but are required to work together.

.NET Remoting can only be created using .NET

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,

Page 496: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

495

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

Page 497: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

496

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.

Page 498: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

497

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

Page 499: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

498

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),

Page 500: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

499

"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);

Page 501: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

500

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()

Page 502: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

501

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(); } }

Page 503: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

502

}

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

Page 504: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

503

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().

Page 505: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

504

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.

Page 506: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

505

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();

Page 507: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

506

// 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.

Page 508: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

507

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

Page 509: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

508

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>

Page 510: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

509

/// 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;

Page 511: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

510

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( _

Page 512: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

511

"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.

Page 513: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

512

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

Page 514: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

513

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.

Page 515: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

514

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>

Page 516: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

515

<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")

Page 517: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

516

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

Page 518: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

517

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);

Page 519: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

518

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())

Page 520: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

519

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- activation code (Code required on the client side)

a) Activator.GetObject()

b) new() with config file

Client's config file references the URL:

ValidateRegistration = http://localhost:80/ ValidateRegistration/ ValidateRegistration.soap

a) Activator.CreateInstance()

b) new() with CFG file

Client's CFG file references the URL. For example http://localhost:80/ValidateRegistration

Page 521: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

520

Activation of the server object

Message is only sent when the first method call is made. No activation messages is sent upon requesting the reference. Constructor is not executed.

Activation messages is sent to the server when a proxy is created after the client creates the object. Constructors with parameters are supported.

Lifetime of the server object

The lifetime for single call and singleton is determined by the configuration on the server. Singleton objects are also subjected to lifetime management.

Lifetime is the earlier of these two events:

a) Lease expires

b) When the client loses its reference on the server object

Server side registration

a) Use configuration file to specify the type (SingleCall or Singleton).

b) Use RegisterWellKnownServiceType() api to register the type.

configuration file can be used to export the client-activated object.

Advantages of the models

a) Clients can be compiled against server component’s base class or interface definition.

b) Useful to perform finite operations on the server side.

c) Applications that uses Single call objects are easily deployed in a Load Balanced environment, as they don't hold state.

d) Singleton Objects can maintain state information across client objects.

a) Classic COM "coclass" like invocation of the server object.

b) Gives clients more flexibility to govern the server object's lifetime.

c) Client can pass constructor parameters to the created object.

d) Server Objects can hold state for its specific client between method calls.

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

Page 522: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

521

.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

Page 523: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

522

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),

Page 524: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

523

"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

Page 525: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

524

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

Page 526: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

525

{ 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

Page 527: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

526

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

Page 528: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

527

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.

Page 529: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

528

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.

Page 530: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

529

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

Page 531: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

530

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>

Page 532: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

531

</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

Page 533: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

532

{ 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")

Page 534: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

533

[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.

Page 535: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

534

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);

Page 536: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

535

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

Page 537: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

536

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:

Page 538: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

537

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

Page 539: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

538

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");

Page 540: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

539

} 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")

Page 541: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

540

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;

Page 542: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

541

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");

Page 543: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

542

} 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)

Page 544: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

543

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

Page 545: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

544

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.

Page 546: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

545

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.

Page 547: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

546

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>

Page 548: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

547

<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; }

Page 549: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

548

}

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:

Page 550: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

549

* 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.

Page 551: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

550

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

Page 552: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

551

{ 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

Page 553: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

552

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();

Page 554: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

553

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

Provides general membership facilities.

Creates a new user.

Deletes a user.

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.

Page 555: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

554

Searches for users by username or e-mail address.

MembershipUser

Provides information about a specific user.

Gets the password and password question.

Changes the password.

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

Defines functionality for data providers that can be used by the membership system.

The Membership provider defines the methods and properties that a provider is required to implement.

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).

Page 556: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

555

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

Page 557: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

556

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

Page 558: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

557

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.

Page 559: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

558

-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 filename

Create a SQL script file. We can customize this file to modify specific features.

-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.

Page 560: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

559

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

Page 561: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

560

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.

Page 562: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

561

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.

MinRequiredNonAlphanumericCharacters

Retrieve the minimum number of special charaters that must be used 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.

PasswordStrengthRegularExpression

Retrieve the regular expression used to evaluate a password.

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.

Page 563: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

562

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

Page 564: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

563

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.

Page 565: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

564

GeneratePassword Generates a random password of the specified length.

GetAllUsers Retrieve all users in the database

GetNumberOfUsersOnline

Retrieve the number of users currently accessing the application.

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) {

Page 566: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

565

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

Page 567: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

566

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.

Page 568: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

567

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#

Page 569: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

568

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

Page 570: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

569

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

Page 571: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

570

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;

Page 572: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

571

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#

Page 573: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

572

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.

Page 574: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

573

<?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.

Page 575: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

574

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.");

Page 576: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

575

} 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)) {

Page 577: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

576

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

Page 578: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

577

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

Page 579: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

578

<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 {

Page 580: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

579

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

Page 581: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

580

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)

Page 582: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

581

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

Page 583: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

582

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.

Page 584: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

583

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

Page 585: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

584

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

Page 586: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

585

<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>

Page 587: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

586

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();

Page 588: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

587

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.

Page 589: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

588

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/" />

Page 590: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

589

</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

Page 591: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

590

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:

Page 592: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

591

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.

Page 593: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

592

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).

Page 594: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

593

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.

Page 595: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

594

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).

Page 596: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

595

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).

Page 597: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

596

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.

Page 598: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

597

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,

Page 599: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

598

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).

Page 600: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

599

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.

Page 601: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

600

* 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.

Page 602: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

601

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

Page 603: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

602

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).

Page 604: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

603

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.

Page 605: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

604

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).

Page 606: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

605

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

Page 607: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

606

<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

Page 608: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

607

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"

Page 609: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

608

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.

Page 610: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

609

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.

Page 611: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

610

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

Page 612: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

611

<?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".

Page 613: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

612

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(); } } } }

Page 614: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

613

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.

Page 615: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

614

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"

Page 616: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

615

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>

Page 617: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

616

</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

Page 618: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

617

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;

Page 619: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

618

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

Page 620: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

619

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) { }

Page 621: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

620

/// <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

Page 622: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

621

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

Page 623: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

622

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">

Page 624: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

623

<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;

Page 625: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

624

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

Page 626: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

625

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.

Page 627: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

626

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.

Page 628: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

627

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.

Page 629: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

628

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.

Page 630: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

629

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.

Page 631: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

630

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.

Page 632: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

631

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

Page 633: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

632

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"

Page 634: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

633

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

Page 635: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

634

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).

Page 636: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

635

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.

Page 637: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

636

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#

Page 638: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

637

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);

Page 639: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

638

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>

Page 640: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

639

<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,

Page 641: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

640

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); } } }

Page 642: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

641

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.

Page 643: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

642

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

Page 644: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

643

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.

Page 645: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

644

* "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

Page 646: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

645

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.

Page 647: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

646

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

Page 648: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

647

[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;

Page 649: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

648

[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

Page 650: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

649

{ 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()> _

Page 651: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

650

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.

Page 652: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

651

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

Page 653: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

652

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.

Page 654: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

653

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;

Page 655: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

654

[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 _

Page 656: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

655

(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.

Page 657: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

656

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");

Page 658: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

657

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;}

Page 659: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

658

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" + _

Page 660: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

659

" 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

Page 661: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

660

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

Page 662: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

661

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.

Page 663: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

662

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:

Page 664: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

663

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 {

Page 665: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

664

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,

Page 666: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

665

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

Page 667: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

666

<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

Page 668: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

667

<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"

Page 669: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

668

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);

Page 670: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

669

//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()

Page 671: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

670

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

Page 672: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

671

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.

Page 673: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

672

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;

Page 674: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

673

} 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 {

Page 675: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

674

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")

Page 676: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

675

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

Page 677: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

676

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

Page 678: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

677

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);

Page 679: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

678

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), _

Page 680: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

679

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.

Page 681: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

680

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

Page 682: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

681

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.

Page 683: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

682

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

Page 684: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

683

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.

Page 685: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

684

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.

Page 686: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

685

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

Page 687: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

686

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.

Page 688: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

687

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"

Page 689: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

688

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.

Page 690: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

689

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.

Page 691: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

690

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.

Page 692: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

691

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.

Page 693: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

692

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.

Page 694: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

693

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.

Page 695: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

694

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.

Page 696: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

695

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 />

Page 697: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

696

</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.

Page 698: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

697

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.

Page 699: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

698

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.

Page 700: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

699

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.

Page 701: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

700

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);

Page 702: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

701

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()

Page 703: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

702

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

Page 704: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

703

(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)})

Page 705: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

704

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;

Page 706: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

705

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

Page 707: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

706

<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

Page 708: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

707

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";

Page 709: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

708

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

Page 710: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

709

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

Page 711: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

710

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.

Page 712: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

711

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>

Page 713: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

712

<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

Page 714: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

713

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

Page 715: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

714

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 {

Page 716: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

715

[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

Page 717: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

716

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)

Page 718: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

717

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

Page 719: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

718

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"?>

Page 720: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

719

<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) {

Page 721: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

720

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)> _

Page 722: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

721

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#

Page 723: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

722

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)

Page 724: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

723

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.

Page 725: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

724

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.

Page 726: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

725

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

Page 727: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

726

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

Page 728: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

727

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.

Page 729: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

728

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.

Page 730: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

729

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

Page 731: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

730

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

Page 732: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

731

.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.

Page 733: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

732

* 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.

Page 734: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

733

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";

Page 735: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

734

} [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.

Page 736: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

735

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.

Page 737: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

736

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.

Page 738: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

737

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.

Page 739: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

738

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.

Page 740: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

739

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

Page 741: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

740

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>

Page 742: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

741

/// 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>

Page 743: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

742

<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")> _

Page 744: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

743

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#

Page 745: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

744

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();

Page 746: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

745

} /// <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

Page 747: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

746

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; }

Page 748: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

747

} }

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

Page 749: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

748

''' </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()> _

Page 750: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

749

<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.

Page 751: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

750

Figure 17-25. SelectContactByID

The result of the execution is shown in figure 17-26.

Figure 17-26. SelectContactByID result

Page 752: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

751

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.

Page 753: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

752

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.

Page 754: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

753

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>

Page 755: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

754

<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">

Page 756: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

755

<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>

Page 757: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

756

</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

Page 758: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

757

{ 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

Page 759: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

758

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.

Page 760: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

759

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.

Page 761: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

760

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.

Page 762: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

761

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.

Page 763: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

762

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.

Page 764: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

763

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.

Page 765: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

764

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.

Page 766: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

765

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.

Page 767: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

766

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

Page 768: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

767

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.

Page 769: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

768

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.

Page 770: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

769

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.

Page 771: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

770

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

Page 772: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

771

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.

Page 773: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

772

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.

Page 774: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

773

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.

Page 775: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

774

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

Page 776: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

775

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.

Page 777: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

776

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.

Page 778: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

777

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.

Page 779: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

778

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.

Page 780: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

779

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.

Page 781: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

780

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.

Page 782: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

781

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.

Page 783: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

782

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.

Page 784: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

783

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.

Page 785: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

784

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.

Page 786: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

785

Indexes

& &amp; .........................................................................137 &apos; .........................................................................137 &gt; .............................................................................137 &lt; ..............................................................................137 &quot; .........................................................................137

. .NET Data Provider.....................................................189 .NET DataSets.............................................................185 .NET Deployment .......................................................389 .NET Framework.........................................................100 .NET Framework 2.0...................................................103 .NET Framework class libraries ..................................101 .NET Serialization.......................................................271 .NET Web Service Message Flow...............................124 .NET XML Serialization .............................................271

A ADO.NET ...................................................................182 ADO.NET DataSet Events ..........................................218 ADO.NET DataSets ....................................................213 Advanced Web Service Programming ........................419 Application Proxy .........................................................68 Architectural Tradeoff Matrix .......................................26 Architectural Tradeoff Triangle ....................................26 Assembly Information.................................................390 Asymmetric (Public) Key Encryption ...........................65 Async Data Access......................................................183 Asynchronous Web service .........................................432 Attributes and Namespaces .........................................136 Authentication...............................................................60 Authorization ................................................................60 Autos Window ............................................................362

B Basic services ................................................................48 BEA ..............................................................................45 BeginExecuteReader ...................................................183 BeginExecuteXmlReader ............................................183 binding ........................................................................177 Boolean .......................................................................143 Breakpoint Window ....................................................363 Budget Consideration....................................................81 Buffering .....................................................................419 BufferResponse...........................................................419 Business and IT.............................................................80 Business Benefits of SOA .............................................27 Business Process Execution Language for Web Services

(BPEL4WS).............................................................54 Byte .............................................................................143

C CacheDuration .................................................... 419, 424 Call Stack Window .....................................................362 CDATA ......................................................................138 CDATA sections.........................................................138 Choreography ...............................................................53 Cities.............................................................................24 Class View..................................................................114 ClickOnce ........................................................... 399, 403 Code Coverage............................................................378 ColumnChanged .........................................................218 ColumnChanging........................................................218 Command....................................................................186 Common Language Runtime (CLR)...........................102 Common Type System (CTS).....................................102 Confidentiality ..............................................................61 Connected System Strategy ..........................................71 Connection..................................................................186 ConnectionString ........................................................190 Continuous Track..........................................................86 Controlled code sharing ..............................................389 Controlling Serialization.............................................282 Coordination Services...................................................55 Copying DataSet Contents..........................................216 Creating Data Views...................................................217 Creating XML Web Services......................................316 Cross Entities Query .....................................................52

D Data Adapters .............................................................195 Data Encoding ............................................................161 Data Providers ............................................................186 DataAdapter................................................................187 Data-Centric Services ...................................................48 DataReader ......................................................... 186, 197 DataRow .....................................................................208 DataSet........................................................................207 DataTable....................................................................207 Datatype picker ...........................................................155 Date.............................................................................143 dateTime .....................................................................144 decimal........................................................................144 definitions ...................................................................175 DeleteCommand .........................................................196 Deploying Track ...........................................................85 Deployment ................................................................389 Description..................................................................419 Description for a Web Method....................................425 Developing Track .........................................................84 Distributed Event Driven Architecture and SOA........ See

EDA Document....................................................................114 Document Object Model.............................................240

Page 787: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

786

DocumentType............................................................242 double..........................................................................144 duration .......................................................................144

E EDA ..............................................................................55 Elements......................................................................134 EnableSession .....................................................419, 427 EndExecuteNonQuery.................................................183 EndExecuteReader ......................................................183 EndExecuteXmlReader ...............................................183 Enterprise Application Integration (EAI) ......................52 Enterprise Architecture .................................................25 Enterprise Service Bus & Services................................56 Entity Aggregation ........................................................50 enumeration.................................................................149 Envisioning Track .........................................................84 Error list ......................................................................141 Error List .....................................................................113 ESB ......................See Enterprise Service Bus & Services ExecuteReader ............................................................183 ExecuteScalar..............................................................193 ExpectedExceptionAttribute .......................................377

F Facets ..........................................................................149 Factories........................................................................24 fractionDigits ..............................................................150

G Gathering Internal Support............................................81 gDay............................................................................144 GET and POST ...........................................................128 GetFileBuffered() ........................................................424 GetFileUnbuffered()....................................................424 GetResponse................................................................170 global.asax ..................................................................115 gMonth........................................................................144 gMonthDay .................................................................145 Governance ...................................................................85 gYear...........................................................................145 gYearMonth ................................................................145

H hexBinary....................................................................145 Horizontal Partitions .....................................................51 HTTP ..........................................................................126 HTTP With .NET........................................................130 HttpWebRequest .........................................................130 HttpWebResponse...............................................130, 170 Hyper Text Transfer Protocol (HTTP) ........................124

I Implementing Sampling ..............................................382 Initializing and Cleaning Up Tests ..............................379 InsertCommand...........................................................195 Instrumentation ...........................................................382 int 145

integer .........................................................................145 Integrity ........................................................................61 Internal Politics.............................................................80 Inter-Platform Connection ............................................76 Invoking Web Method using .NET HTTP POST, GET

and SOAP..............................................................164 IsClosed ......................................................................199 IT Cost Savings.............................................................74 IT Infrastructure Evolution ...........................................25 Iterative Quality Assurance...........................................47

J Just-In-Time (JIT).......................................................102

L language......................................................................146 Language constructs ...................................................153 Legacy Enterprise Architecture ....................................33 length ..........................................................................150 list 154 Locals Window...........................................................362 Logical Layers to Physical Tiers...................................49 Logic-Centric Services .................................................48 long.............................................................................146 Loose Coupling.............................................................29

M managed applications..................................................102 Managed Development ...............................................102 Manipulating XML with .NET ...................................240 Manually Creating a Typed Dataset............................220 Manufactured................................................................24 maxExclusive..............................................................150 maxInclusive...............................................................150 maxLength ..................................................................151 Measuring a SOA .........................................................78 message.......................................................................176 Message Reliability.......................................................68 MessageName..................................................... 419, 429 Metropolis.....................................................................23 minExclusive ..............................................................151 minInclusive ...............................................................151 minLength...................................................................152 minOccurs...................................................................157 MSF ..............................................................................81 MSF Agile ....................................................................83 MSF Risk Management ................................................90 MSF Tracks ..................................................................82

N Name...........................................................................146 namespaces .................................................................135 NCName ............................................................. 135, 146 negativeInteger ...........................................................146 NMTOKEN ................................................................157 No-impact deployment..............................................389 noNamespaceSchemaLocation ...................................156 nonNegativeInteger.....................................................147 nonPositiveInteger ......................................................147

Page 788: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

787

Non-repudiation ............................................................61 normalizedString.........................................................147 Numeric types .............................................................142

O OdbcDataAdapter........................................................187 OdbcDataReader .........................................................187 OLE DB Data Provider in .NET .................................189 OleDBAuthors ............................................................190 OleDbCommand .........................................................192 OleDbConnection................................................189, 190 OleDbDataAdapter......................................................187 OleDbDataReader ...............................................187, 199 Open Schema ..............................................................310 Opening and Closing Connections ..............................190 Operational Management ..............................................86 OracleDataAdapterfor .................................................187 OracleDataReader .......................................................187 Orchestration................................................................53 Organization Vision ......................................................80 Organizational Roadmap...............................................79 Overloaded ..................................................................429

P pattern .........................................................................152 Planning Track ..............................................................84 Point-to-Point vs End-to-End Security ..........................61 portType......................................................................177 positiveInteger.............................................................147 Primary Keys...............................................................215 Profiling ......................................................................381 Program Management ...................................................87 Project Conversion Report ..........................................111 Project Conversion Wizard .........................................111 Project Teams................................................................86 Properties ....................................................................113 Public Services ..............................................................49 Publishing ...................................................................399

Q QName ........................................................................147

R RecordsAffected..........................................................199 Relationships with Typed Dataset ...............................227 restriction ....................................................................153 RowChanged...............................................................218 RowChanging..............................................................219 RowDeleted.................................................................219 RowDeleting ...............................................................219

S SAML ...................................................................67, 181 Sampling .....................................................................381 schemaLocation...........................................................156 Security Basics ..............................................................60 Security in Service Oriented Architecture.....................60 Security with Federation ...............................................66

SelectCommand..........................................................195 SerializableClass.........................................................279 Serialization Formatter ...............................................273 Serializing Arrays .......................................................293 Server Explorer...........................................................113 service.........................................................................178 Service Oriented Architecture.......................................23 Service Oriented Enterprise Architecture .....................33 Service Types................................................................48 Services.........................................................................30 Session State ...............................................................427 short ............................................................................148 Simple Object Access Protocol (SOAP) .....................159 simpleType .................................................................153 Single View of Entity ...................................................50 SOA Architectural Roadmap ........................................44 SOA Driven Project Development......................See MSF SOA future vision .........................................................46 SOA Governance ..........................................................47 SOA maturity assessment .............................................46 SOA planning ...............................................................46 SOA roadmap definition...............................................47 SOAP.................................................................... 31, 159 SOAP Body ................................................................160 SOAP Fault.................................................................161 SOAP Header..............................................................160 SOAP Interceptor..........................................................66 SOAP Message Monitoring ..........................................65 SOAP Request ............................................................161 SOAP Response..........................................................162 SOAP via HTTP .........................................................162 Solution Explorer........................................................113 SqlCommand.ExecuteXmlReader ..............................184 SqlCommandBuilder ..................................................210 SqlConnection Class ...................................................190 SqlDataAdapter...........................................................210 SqlDataReader ............................................................198 SqlTruncateException.................................................228 SqlUdt.........................................................................184 Stabilizing Track...........................................................85 Standardization .............................................................24 Static Analysis ............................................................380 StreamReader..............................................................130 StreamWriter...............................................................130 string ...........................................................................148 Strongly Typed XML Serialization.............................299 Support for digital signature .......................................180 Symmetric Key Encryption........................................65 System.Data.SqlTypes ................................................184 System.Runtime.Serialization.Formatters.Soap..........276 System.Xml.Serialization ...........................................279

T TableCleared...............................................................219 TableClearing .............................................................219 TableNewRow ............................................................219 Task List ............................................................. 114, 118 Technology Soup ..........................................................33 Test Plan .....................................................................354 TestCleanupAttribute..................................................379 TestInitializeAttribute.................................................379 Tests............................................................................376

Page 789: The Complete Reference to Professional SOA With Visual Studio 2005 Dot NET 3.0

The Complete Reference To Professional SOA with Visual Studio 2005

788

time .............................................................................148 token............................................................................148 Toolbox.......................................................................113 totalDigits....................................................................152 TransactionOption.......................................................419 Transitional Services .....................................................49 Transportation ...............................................................24 Typed ADO.NET DataSet...........................................219 types ............................................................................175

U UDDI.............................................................................32 UDDI SDK..................................................................180 UDDI v3......................................................................179 Union ..........................................................................154 unmanaged applications ..............................................102 unsignedByte...............................................................148 unsignedInt..................................................................148 unsignedLong..............................................................149 unsignedShort..............................................................149 UpdateCommand.........................................................196 Urban Infrastructure ......................................................25 Using Web Deployment Projects ................................404

V ValidationType............................................................266 Virtual Enterprises ........................................................25 Visual Studio 2005 Editions........................................105 Visual Studio 2005 Express Editions ..........................105 Visual Studio 2005 Professional Edition.....................106 Visual Studio 2005 Projectless Development..............110 Visual Studio 2005 Standard Edition ..........................105 Visual Studio 2005 Team Edition for Software Architects

...............................................................................104 Visual Studio 2005 Team Edition for Software

Developers .............................................................105 Visual Studio 2005 Team Edition for Software Testers

...............................................................................105 Visual Studio 2005 Team Foundation Server..............105 Visual Studio 2005 Team Roles ..................................104 Visual Studio 2005 Team Suite...................................105 Visual Studio 2005 Team System ...............................388 Visual Studio IDE .......................................................112 Visual Studio Windows...............................................113

W Watch Window ...........................................................361 Web Server Description Language (WSDL)...............103 Web Service ..........................................................28, 315 Web Service Authentication..........................................63 Web Service Choreography Interface (WSCI) ..............53 Web Service Management Orchestration ......................59 Web service technology stack .....................................124 Web Service Template ................................................106 Web Services Description Language (WSDL)............175 Web Setup Project.......................................................414 web.config...................................................................114 Well-formed XML ......................................................138 whiteSpace ..................................................................153

WriteXmlSchema .......................................................266 WS-* Standards ..........................................................180 WSDL................................................................... 31, 178 WS-Federation............................................................180 WS-Policy...................................................................180 WS-PolicyAttachment ................................................181 WS-SecureConversation .............................................180 WS-Security.......................................................... 64, 180 WS-SecurityPolicy......................................................180 WS-Trust ....................................................................180

X XACML......................................................................181 XCOPY.......................................................................389 XKMS.........................................................................181 XML ...........................................................................134 XML and DataSet .......................................................266 XML and XML Schema ...............................................30 XML Comments .........................................................136 XML Datatypes ..........................................................142 XML Date and time types...........................................142 XML declaration.........................................................138 XML Encryption...........................................................64 XML Name and string types.......................................143 XML Parser ................................................................247 XML Prohibited character literals...............................137 XML Schema..............................................................155 XML Schema Definition (XSD).................................141 XML Schema Structures.............................................155 XML Serialization ......................................................279 XML Signature .............................................................65 XML Validation..........................................................262 XML Web service.......................................................124 XML Web Services ......................................................30 XML Whitespace........................................................137 XmlAnyAttribute................................................ 296, 310 XmlAnyElement ................................................. 296, 310 XmlAttribute...............................................................242 XML-Data Reduced (XDR)........................................262 XmlDocument.............................................................242 XmlDocumentFragment .............................................242 XmlDocumentType ....................................................242 XmlElement........................................................ 242, 283 XmlEntity ...................................................................242 XmlEntityReference ...................................................242 XmlInclude .................................................................297 XmlNodeType ............................................................252 XmlNotation ...............................................................242 XmlProcessingInstruction...........................................242 XmlReader..................................................................249 XmlRoot .....................................................................283 XMLSchemainstance..................................................155 XmlSchemaSet’s.........................................................266 XmlTextReader...........................................................250 XMLTextReader.........................................................252 XmlWriter...................................................................249 XPath .................................................................... 30, 256 XPathNavigator ..........................................................255 XPathNodeType .........................................................257 xs:sequence.................................................................140 XSD .................................................................... 158, 259