The Complete Reference To Professional SOA With Visual Studio 2005 Dot NET 3.0
The Complete Reference To Professional SOA With Visual Studio 2005 Dot NET 3.0
All rights reserved. No part of the content of this book may be reproduced or transmitted in any form or
by any means without the written permission of the author.
About The Author
Tom Yuan Gao has been developing software for over ten years. Having completed Unisys Scholarship at
University of Sydney at the age of 16. He is current a Microsoft Certified Application Developer (MCAD),
Microsoft Certified Solution Developer (MCSD), Microsoft Certified Database Administrator (MCDBA),
Microsoft Certified Trainer (MCT) as well as Nationaly Accredited IT Trainer within Australia. He has also
given lecture at universities on the benefits of Service Orientated Architecture. Tom is currently completing his
Doctorate in Distributed Software Security. In his spare time he can be found on his Windows Communication
Foundation Community Center at http://www.mswcf.com ran for solution/enterprise architects. Tom is currently
working as the National Technical Manager for EuroRSCG World Wide.
Letter from the Author
The concept of service orientation has been around for a very long time. The idea of service orientation is about
developing structured reusable solutions that can be used over and over again. Although the concept itself is
simplistic there has been no consistent and uniform means of achieving service orientation until recently when
Microsoft has targeted the service orientation area with the release of ASP.NET.
Microsoft’s support for service orientation through ASP.NET XML Web service has generated
overwhelming support within the industry. The .NET framework coupled with the revolutionary development
environment Visual Studio 2005 will revolutionize the way you view and develop future applications.
In this book I will take you through the hype and myth of service orientation and into the real world of
experience that will help you understand and transform the way you view and develop applications within your
enterprise architecture. We will investigate the reasons to why service oriented architecture can help application
infrastructures in terms of flexibility, interoperability, and integration.
The book is divided into two parts. The first part deals with theory and concepts of service orientation. We
will be exploring the risks and trade offs that are required. We will also learn how to meet enterprise
requirements for availability, scalability and security. For IT managers and business stakeholders we will explore
the concept of generating additional customer base through the previously taboo subject of exposing and yet
protecting your intellectual property.
The second part of the book focuses on the application of service orientation through ASP.NET XML Web
Services. You will learn to use and take advantage of the newly released Visual Studio 2005 development
environment, through step by step guides for each and every example in both Visual C# and Visual Basic .NET.
You will also learn to develop XML Web Services to supplement the concepts you have learnt in part one of the
book.
This book is a worthwhile investment and I thank you for purchasing it. I thank you for taking the effort to
take one step beyond everyone else, beyond your competitors.
I have to say that this book would not have been possible without the support from my family and friends. To my
dad, who was my role model in persistence and hard work. To my mum, who has always taught to be efficient
and smart.
There are a few that I would be enternally grateful to. I would have to thank Todd Meister and Fabio
Claudio Ferracchiati for their relentless effort in technical review and in getting every detail perfect as it were
intended. Thanks to Peter Hovany, Bill Heish, David Abraham and Marlon Deleon for their encouragements
during some very difficult times.
Chinese proverb – “The journey of 1000 miles begins with a single step.”
Resource
As a reward for purchasing this book I have also made The Complete Reference to Professional SOA with
Visual Studio 2005 (Visual C# & VB 2005) available for you to download. You will be able to find the book on
http://www.mswcf.com/BookSOA.zip
Source code for both series can be found on
http://www.mswcf.com/source.zip
Foreword
The concepts behind SOA has been with us for many years, but it’s not until recent times with advances in
Microsoft .NET and Sun’s Java that some of the services that architects, business decision takers and visionaries
have envisioned, can finally be implemented in a reusable and platform agnostic manner.
The hype behind SOA in recent years has helped increase the knowledge and the request for Service-
oriented solutions; which in essence is all about moving away from data silos (where information often are
proprietary and hard to access), to open and interchangeable services that deliver the data you need, when you
need it, and allowing you to form these services to fit your business processes and create tangible benefits.
Government, military and private customers are rapidly increasing their demand for service-oriented
platforms that are secure and easy-to-use. This means it has become more important to learn and understand the
concepts and gain the technical skills to implement service-oriented solutions.
This book delivers great content for developers and it can empower you (as a developer and architect) to
better educate others about the benefits and reality behind Service-oriented solutions. It also delivers
comprehensive technical content that is easily understood by business people and decision makers. This is a
book I will promote to everyone involved in business and IT process improvement.
The book can enable you to become better at providing new and innovative solutions that help solve your
customer’s most challenging problems, and can give you inspiration to look at your own internal business
processes in a new light.
Tom delivers the content in a clear and concise way. Tom will guide you through how to start building a
Web Service, how to consume it, how to debug it, and how to finally deploy it into your testing, staging or
production environments. This book is a book for professionals who want to develop quality service-oriented
solutions.
Tom starts out by explaining the core concepts of SOA, allowing you to better understand and start learning
some of the new and innovative ways of thinking. Then going through and giving you a real description what
Web Services is all about without the hype.
If you are new to the whole concept of Web Services, Tom explains the basics of XML based technologies
like XML Schema, SOAP and WSDL which are the foundations of Web Services.
You will learn some of the more advanced topics with building Web Services, important topics like security
and logging. Tom will show you how to use some of the WS-* standard specification, especially WS-Security
with encryption and signing of messages, how to make a custom username service on WSE 3.0 (Web Service
Enhancements), and much more.
There is a special chapter dedicated to Windows Communication Foundation which is the new and unified
communication platform coming with the release of Microsoft .NET Framework 3.0, released around Windows
Vista timeframe. This can prepare you for the future changes for developing communication solutions with
Visual Studio.
Microsoft released a version of Visual Studio for software architects, where they introduced some new
features that can help you plan your overall architecture of your distributed service-oriented solutions. Part of
this initiative is the Distributed System Designers that Tom covers comprehensively in this book. These give you
capabilities to model and manage distributed solutions directly from Visual Studio, making deployment
packages and validating them against your server-farms amongst other things.
Look no further for a full in-depth review of Service-oriented architecture and technologies. Tom has
written an excellent book for professionals, that will guide you through the process of building services the way
they where meant to be.
Introduction
-Applications must retool or perish. Organizations that fail to realize the efficiencies of integration by-design will
lose in the long run to those who pursue them. – Pat Helland
Service Oriented Architecture has the potential to be the next great paradigm that will once and for all change
computing as we know it. The main promise of Service Oriented Architecture is that business systems can be
used by anyone, from anywhere, at any time and on any system.
The popularity in Service Oriented Architecture is largely generated by the ability to allow developers to
seamlessly integrate disparate systems without the requirement to understand the underlying technology specific
details. This abstraction from technology is due to the ability to build Business Services which are application
components that describe the application process instead of describing the technology. The use of Business
Services allows developers to efficiently integrate application processes between disparate systems that are either
internal to the organization or are maintained by another vendor without the requirement to have an intimate
knowledge about the system process.
Today more and more developers, architects and IT managers are turning to Service Oriented Architecture.
This growth in popularity is due to today’s increase in pressure to provide the outmost efficiency and reliability
in solution development. As a result developers and architects are driven to focus their efforts on developing
reusable components to ensure that they can be easily reused in future. With the focus of reusability in mind
developers and architects are able to develop and expand on existing enterprise systems quickly and efficiently.
Through Service Oriented Architecture, system development is unlike before. For the first time in the
history of software development, developers are able to build enterprise systems that can easily keep up with
business agility and changing business requirements whilst developing new functionalities. Service Oriented
Architecture is a revolution that we have all been waiting for.
Following the release of the second generation of the .NET.Framework, application development is on a
new level playing field. The people at Microsoft have spent enormous amounts of time and research into
application development. The fruit is Visual Studio 2005. With Visual Studio 2005 applications can be
developed much more easily and efficiently.
Throughout the book we will use Visual Studio 2005 and .NET 2.0 to illustrate SOA development and
design. This book will not only focus on the technical aspects of SOA, but also place strong emphasis on the
delicate issues of establishing SOA at the enterprise level and the pitfalls associated. The principles described in
this book are the foundations on which enterprise systems are constructed. Through the book we will learn to
develop application systems that are flexible, agile, and secure at lower costs
This book will provide developers, architects and IT managers with a roadmap for success in establishing
SOA at the enterprise level. It is a concrete guide, blueprint and contains best practices for SOA architecture
using the .NET Framework.
20
The Complete Reference To Professional SOA with Visual Studio 2005
21
The Complete Reference To Professional SOA with Visual Studio 2005
22
The Complete Reference To Professional SOA with Visual Studio 2005
chain is not required. We can use another distribution chain that already exists, is established and operating in
that city to help distribute our own product. Using the SOA approach we can easily branch out our business
whenever required. This level of flexibility is transcendent and will allow the business to expand very rapidly.
Transportation as Communication
In Metropolis, transportation refers to the movement of people and goods. This movement stimulated
tremendous change. People were able to travel to different cities and visit places they were unable to previously.
Retail began to expand rapidly as people were able to visit other cities and gather goods from stores in these
cities. Through the movement in goods people arrived at a new expectation that things would work together.
However, prior to the transportation development, one manufacturer’s goods were incompatible with another
manufacturer’s.
In the application world, we can see that in the past applications were structured in a rigid monolithic
architecture. With the arrival of SOA through the use of business services, enterprise architectural applications
are becoming more interoperable and are starting to communicate with each other.
23
The Complete Reference To Professional SOA with Visual Studio 2005
24
The Complete Reference To Professional SOA with Visual Studio 2005
Enterprise Architecture
An Enterprise Architecture consists of the various structures and processes. Enterprise Architecture is a
representation of all that exists within an organization. The structures themselves can be either the IT based or
the business process based. A good representation of the enterprise architecture thus will represent the business
model as it is today as well as incorporate the business strategies for the future. The Enterprise Architecture
representation can thus be used as a communication bridge between business stakeholders and the IT system
implementer. For our purposes Enterprise Architecture will mean the design, planning and execution of the
overall IT systems of an enterprise.
To see how Enterprise Architecture affects the role and circumstances of IT in business, we should first
examine the concept of “architecture” itself. Architecture is the process of designing buildings so that they serve
their intended purpose. If an architect designs a house, it is meant to be lived in if he or she designs an office, it
is meant to be used for work. Similarly, Enterprise Architecture is the process of designing IT systems in order to
develop an IT structure that realizes the needs of the business. Enterprise Architecture refers to the ability to
enable the business goals of the organization. We must keep in mind when designing architecture not to over
step the boundary of over indulgence and detract from the need of the organization. To do so is dangerous and
costly for the organization that seeks to optimize its processes.
* 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.
25
The Complete Reference To Professional SOA with Visual Studio 2005
As illustrated by the trade-off triangle, any change to any one of the components implies that a
corresponding change might need to be made to the other components. The key to developing a solution that
meets the customer requirements is to determine and maintain the correct balance between resources,
development date, and features.
Often, project teams are reluctant to reduce the number of features in the solution. The trade-off triangle
helps to explain the constraints and present the options for trade-offs.
Figure 1-2 illustrates the trade-off matrix used to make trade off decisions
* 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.
26
The Complete Reference To Professional SOA with Visual Studio 2005
This process involves integrating and aggregating entities/information that are present in different systems. As a
result instead of making phone calls to HR and Payroll and Benefits to update an employee’s address details in
each of these different systems. By automating the process through entity aggregation we can update the
information with just one phone call. We can also construct a self-service portal that will update personal
information seamlessly across different systems.
Businesses also benefit by connecting systems and providing integrated solutions to customers. By
implementing SOA, the total cost of ownership (TCO) is dramatically reduced. While the integrated solution
with applications such as enterprise resource planning (ERP) and customer relationship management (CRM)
systems can also provide more value to the end users. The integration of all of these systems can also benefit the
business by reducing the overall total cost of ownership for support individual business functionalities.
Through the use of SOA, organizations are able to make better design, management, and investment
decisions. This level of visibility into application usage allows companies to identify, and, more importantly, to
make changes to existing business processes to take advantage of opportunities for continuous improvement.
This ability to nimbly change and modify business processes as business needs require will give companies a
distinct advantage over their less agile competitors.
Today integrating disparate systems components is about effectively orchestrating the interaction between
enterprise resources: whether it’s machine to machine, person to person, or a combination of both, in a manner
that is conducive to the way business is conducted. Through SOA, IT can easily morph into a valuable asset by
introducing a comprehensive process-centric integration approach that delivers that and more. Thus, allowing IT
systems to make the transition from an inhibitor to an enabler of business.
Organizations can expect to experience the following benefits when deploying enterprise systems built using
SOA.
27
The Complete Reference To Professional SOA with Visual Studio 2005
Loose Coupling
In the 1980s and earlier application architecture was developed in a fairly simple format. The architecture
usually consisted of UI Components at the very top, followed by business logic in the middle and data access
components at the very bottom. This was often referred to as the Silo Architecture also known as the Vertical
Architecture Figure 1-3.
From 1980s towards 1990s the software architecture moved towards a more horizontal architecture. This is
where we are starting to see a separation of logic in layers. Layers in software refers to a way of organizing the
code to provide logical abstraction and separation. Typical layers include Presentation, Business and Data layers.
Layers are primarily used to gain the benefits of logical organization and grouping of similar functionalities. This
in turn supports code reuse. This is referred to as the Layer Architecture or Horizontal Architecture
What we’re now seeing through service oriented architecture is a steady move from layers to tiers. Tiers is about
the physical separation between code. In other words tiers is about where layers run. We’re now increasingly
seeing that systems are no longer running off from one Server but from several different servers located in
different countries. A database on Human Resource might be located in the United States whilst another database
on payroll might be located in Australia. This form of architecture is referred to distributed architecture. This is
what SOA is helping us to evolve towards.
Figure 1-3 shows the evolution of software architecture from vertical to horizontal to today’s distributed architecture.
Loose Coupling refers to the act of joining things together. In application development loose coupling refers to
the degree which software components depend upon each other.
Traditionally applications are “tightly coupled”, where each application may or may not connect with others
in a distributed environment through a combination of proprietary interfaces and network protocols. These
28
The Complete Reference To Professional SOA with Visual Studio 2005
applications were often designed within system boundary of an enterprise or even within a specific business unit
of the enterprise. As a result the applications have no concept of interoperating with other units of work outside
of its system boundary.
A solution to the tightly coupled application is an attempt to develop applications in a loosely coupled
manner. Loose coupling is seen as a way to reduce the overall complexity and dependencies of applications on
each other. Loose coupling can be achieved through using XML Web service by using the
interface/implementation approach. Loose coupling leads towards the same goal as service orientation, which is
providing an architecture that is more agile, allowing faster response to change and improvement for overall
system agility. In addition, system maintenance is much easier.
Loose coupling is especially important in the enterprise architecture. As the relationships between business
partners change rapidly. Vendor alliances are constantly made, altered or broken, and business processes
between trading partners are constantly changing to adapt the new market requirements. Due to the severe and
fast paced competition in business today it is essential that the underlying IT infrastructure could reflect the
flexibility and independence of the business efficiently.
Overall scalability is also a lot easier in a loosely coupled architecture. Key software components can be
easily taken and deployed onto multiple servers to improve reliability and availability.
Today, in Service Oriented Architecture, loose coupling is mostly implemented through the use of Web
services. Once a piece of software has been exposed as a web service, it is relatively simple to access through the
use of WSDL and UDDI.
Services
The concept of services has been around for quite a while. Service by definition refers to any component that
provides functionality and is an independent building block that can be integrated together collectively to
represent an application.
Unlike traditional components each service represents a unique discrete unit of work in their environment.
This means that each service is responsible for its specified role in its own domain. In the business sense the
service focuses on a specific business function or possibly a group of functions.
This model allows for the creation of isolated units of business functionality that can be easily reused
throughout development. The loosely bound services help to provide freedom within the architecture.
In the past service orientation was created using services though increasingly today SOA refers to the use of
XML Web services. This is because of the vendor neutral implementation and its interface/implementation
provide as an ideal model for SOA.
29
The Complete Reference To Professional SOA with Visual Studio 2005
pushed for its own technology and proprietary standards. The industry was quickly filled with varying
technologies that weren’t able to work together. With the adoption of XML, industry vendors now had a means
to communicate and work together.
The structure of XML documents is based on rules that are also known as grammar. These rules are
specified by a XML Schema document. A schema document contains the definitions of elements, attributes, and
data types. Any XML that is created can be validated against an XML Schema. Though XML can be used
independently of XML Schema, in Web Services the XML that we work with will be governed by an XML
schema called Web Services Description Language (WSDL).
XPath
XPath is used to refer to parts of an XML document. XPath gets its name from its use of a path notation as in
URLs for navigating through the hierarchical structure of an XML document. In addition to its use for
addressing, XPath is also designed so that it has a natural subset that can be used for matching and testing
whether or not a node matches a pattern. XPath models an XML document as a tree of nodes. There are different
types of nodes, including element nodes, attribute nodes and text nodes. XPath defines a way to compute a
string-value for each type of node. Some types of nodes also have names.
SOAP
The SOAP specification provides standards for the format of a SOAP message and how SOAP should be used
over HTTP. SOAP was created to help provide the means to transport XML documents from one computer to
another. SOAP can be used with a number of standard transport protocols. HTTP is one of the most common and
preferred mode of transport protocols used because of its ability to work with firewalls.
SOAP itself is built using XML. SOAP is used to call exposed methods of the Web service. It describes how
the data being passed to those methods is structured, and what the data is. If the client passes the Web service a
correctly formatted SOAP document as a web service request, effectively calling a method, the Web service will
return another SOAP document containing a response. A SOAP message consists of three parts an Envelope,
Header and a Body.
The SOAP Envelope is used to store the XML message. This envelope is acts as a container to hold XML
information contained as shown in Figure 1-4. The envelope consists of two main parts: the SOAP Header and
the SOAP Body of the message. SOAP header can be used as a container for additional information about the
SOAP message for example security credentials or message authentication information like message hash
values. This information is then used to manage and or to help secure the package.
SOAP body contains the XML message content. The body can contain information about the Web service
method that we’re about to execute in a request. In a request the body would contain information about the
method’s parameters, the datatypes they expect as well as the value that will be passed into those parameters. In
30
The Complete Reference To Professional SOA with Visual Studio 2005
a response the body of the SOAP message would contain the information on the datatype that is being return as
well as the actual returned value.
WSDL
Web Services provide an interface of its functionalities through the use of Web Services Description Language
(WSDL). WSDL is an XML document, designed according to standards specified by the W3C, that describes
exactly how a specific web service works. However, the WSDL document is much more than a mere instruction
manual on how to use the web service that it describes. Web services development software can process the
WSDL document and generate the SOAP messages automatically.
Because of the capabilities of WSDL, web services are known as self describing software elements. This is a
very powerful concept. Not only can web services interoperate universally through SOAP, they can also be
described universally using WSDL. A software developer in Sydney, Australia can easily create software calls to
a Web Service in Canada just by reading and processing WSDL document.
Figure 1-5 Depicts a web service conceptually. A Web service using WSDL can expose its methods so that they can be
accessed from any application whether its windows application, web application or mobile application. Thus Web services
contributes to the power of the interoperable nature of distributed systems.
UDDI
Universal Discovery, Description and Integration (UDDI) directory as the general standard used as a registry of
web services that are available for use in a particular network. Think of the UDDI as a sort of yellow pages for
web services. If we wanted to find a web service for our enterprise application, we can look in the UDDI. The
UDDI would tell us where to find that service, and it would take us to the WSDL document so we could examine
the web service and make sure it was the one we wanted.
A UDDI registry is a central concept as one shifts to a model that assumes a distributed, loosely coupled set
of web services. The services that we want to consume could be anywhere at any given moment, and in fact the
same function may be performed by a different service depending on changing criteria, such as availability or
price. The magic of web services is that they are located at addresses to which any computer can connect. The
web service’s URL is the basis for its universality and network transparency. Universal transparency comes from
the ability to use a logical name in the consuming application that the UDDI can then translate into the
appropriate URL. If we wanted to use a service that provided credit card number validation, we can invoke a
logical name called “VisaAuth” and allow the UDDI to resolve the name into a URL. Thus, if the location of a
31
The Complete Reference To Professional SOA with Visual Studio 2005
service changes, the application can still resolve to the new URL location of the required Web Service. This is
key to achieving the agility that web services technology promises.
32
The Complete Reference To Professional SOA with Visual Studio 2005
The organization is separated regionally; each region is in charge of its own architecture. Figure 1-6 identifies
one particular regional branch. We can see that the architecture contains SAP and SAS running on IBM
mainframes, Analysis Services that use Microsoft Windows, and accounting systems that use Java on Sun. On
top of that there is an external payment gateway component that’s being accessed. The head office also accesses
the regional systems periodically to monitor certain operations.
Figure 1-6 depicts a very simplified version of an organization’s architecture diagram. As we can see there
are disparate systems running on many different technologies. As a result there are independent teams located in
each country to maintain and implement changes to the individual systems and subsystems. Because each branch
operated independently from others branches over time the architecture has evolved through years of patchwork.
33
The Complete Reference To Professional SOA with Visual Studio 2005
Each regional branch office has evolved to an untamed beast that was very rigid, non interoperable and difficult
to maintain. Frequently changes to one aspect of the system alone required redevelopment to many other
components. The regional CIO explained that due to the local nature of their business they were operating in
each region it was difficult to centralize globally.
The head office is not happy because development and maintenance is becoming costly regionally. Since
there are many regional offices around the world, the cost involved was quickly adding up. In an attempt to
reduce costs, and keep all systems changes in check, common functionalities consolidated and centralized. The
head office in Nuremberg Germany, had requested that all non-regional specific systems be moved and
consolidated to the head office. The move will allowed at the very least reduction on maintenance and also
supported system reuse at a global level.
Even though consolidating the architecture is an ambitious and necessary business change, the nightmare
began. The new architecture was nearly impossible to implement because at the regional level system conflicts
were rife. Applications were tightly coupled with one another and quite frankly the IT managers and developers
were not really sure where to start. The patched architecture that had evolved over the years had become the
legacy architecture beast.
In order to switch to the new architecture a lot of the existing system had to be re-written in order for the
systems to be more interoperable. Temporary systems were built, patch tools were created and temporary
solution put in place to attempt to bridge the gap between the existing architecture and the new architecture. A
change for better soon became an exhausting, expensive and time-consuming exercise.
The scenario outlined is not dissimilar to many enterprise architectures that currently exist in the industry
today. Diagrammatically Figure 1-6 is a standard architecture that can easily become overwhelming depending
on the business’s need and change in focus. Today business directions change constantly as new partnerships are
forged and broken. To have IT architectures that inhibit the merge of another partner or the quick separation
between the business and an ex-partner for security reasons can be detrimental to the business.
Often legacy architectures like the one outlined are inherited, and constantly patched. As a result it easily
becomes unmanageable, filled with traps and system conflicts. Changing one dimension of the architecture to
meet the change in business needs will result to change in almost every other dimension of the architecture.
Tight coupling in system architecture always results in a nightmare in maintenance and overall does not support
the change in business needs.
34
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 1-7 shows the regional office using a Service Oriented Architecture configuration.
Now, each component application in the architecture is exposed as a web service. Since each component is
now a web service it is now loosely coupled. As a result, it can be accessed from anywhere on the network
regardless of the makeup of the requesting computer.
There are several distinct advantages using service-oriented architecture over the traditional architecture. By
moving to web services the entire architecture experiences flexibility that was not there previously. Services can
now be called by different systems regardless of the technologies that they use complexities of deployment of
these services are reduced, and change management is also simplified. If the custom internal financial system
required changes and as long as the interface of the service is unchanged, the consumer of that service would not
be impacted or even know about it in any way.
Now that we have the service-oriented architecture established, we shall examine how it can help with the
head office’s request to centralize non-regional specific systems at a global level. With an architecture that’s now
built using SOA, the systems that are not region specific can be easily aggregated and re-deployed at the head
office. Reintegration from the regional system to head office is fairly simple and straightforward. By moving to
service-oriented architecture the organization has also experienced more flexibility at the global level.
35
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 1-8 shows a separated architecture through the use of SOA the organization’s architecture becomes much more agile
and flexible.
So how will Service Oriented Architecture affect the Enterprise Architecture? Actually, not much. We can
start by building Web service on top of existing system components. Then we can build or integrate these Web
services into applications. The applications that use these Web services will immediately benefit from the agile
properties of SOA. The flexibility is in the ability of Web services to work with each other regardless of the
underlying technology or platform.
If an organization is adopting SOA for the first time, and is converting its existing infrastructure to SOA.
The initial shift to SOA will be difficult and time consuming. However, in the long run, the amount of time and
money required making those changes would be a fraction of what would be required under the traditional
model. Not only will the entire architecture become more flexible, there will be considerably less maintenance,
and the cost savings on Enterprise Application Integration for new developed component will be enormous.
The main benefit of the SOA is its ability to deliver agility to the enterprise. The entire enterprise will
become simple, fast, and inexpensive to implement changes at the enterprise level. Service Oriented Architecture
really gives the system the ability to keep up with business changes, and not the other way around. Business
decisions are made based on business requirements instead of IT limitations.
The adoption of service-orientation is both liberating for the business manager and the IT manager. The
business manager can act according to strategic directive without the classic constraints of IT. While the IT
manager can deliver results in an efficient and cost-effective manner.
36
The Complete Reference To Professional SOA with Visual Studio 2005
Interoperability was difficult between these infrastructures. As a result it proved almost impossible to impose
enterprise-wide standards in large enterprise systems.
Its no wonder Service Oriented Architecture had almost disappeared briefly. However it was quickly
revived as soon as Web Service became widely adopted within the industry. Through the use of XML essentially
is the lowest common denominator that the industry could agree on. Unlike previous technologies XML is not
bound to a particular vendor or technology standard and thus provided a common communication framework.
Because of its flexibility it is frequently used as a way of transferring data across largely different platforms. As
we move through the book we will see that XML Web Services is a great provider for Service Oriented
Architecture. However, it is important to keep in mind that Web Services are not the only valid technology
platform for an SOA. As SOA concept is not dependent on any one single technology platform.
Case Studies
Service-oriented architecture is catching on. According to a recent Industry Development Center (IDC) report,
SOA spending has reached $8.6 billion in 2006 a 138% increase from 2005 at $3.6 billion. By 2010, IDC
estimates companies will spend upwards of $33 billion on SOA services.
1. Problem: Healthcare industry must address accelerating costs, slow response times and inconsistent quality of
patient records.
Solution: Use SOA approach to integrate payer systems, provider systems with hospitals record system.
2. Problem: The electronics industry is converging from traditional manufacturing to configure to order market.
Solution: Build SOA that facilitates mass production with easy to configure last-minute customization ability.
37
The Complete Reference To Professional SOA with Visual Studio 2005
3. Problem: The banking industry must deal with information silos, redundancy and underutilization of data,
while constantly under pressure to grow.
Solution: To address this we can utilize a SOA to add flexibility to existing infrastructures. Once systems are service-
oriented we can reduce information silos, redundancy and improve on the growth of the architecture to provide new
products and services.
4. Problem: Retailers are confronted with exponentially increasing data such as radio frequency identification
(RFID) that's not leveraged effectively.
Solution: To resolve this we can use SOA to deliver near real-time information to optimize the supply chain.
5. Problem: Telecom companies cope with island like infrastructures. As the industry spurs ahead many legacy
systems and heterogeneous environments are left costly to interoperate. These systems provide services such as
billing, account activation and other specialized customer care services.
Solution: Use SOA to aggregate and consolidate all services to deliver Enterprise Resource Planning (ERP)
application.
The case studies below demonstrates some of the use for SOA to resolve current issues. However the key to
SOA is not only in what it offers to resolve architectural issues but also its ability to support application reuse.
This aspect of SOA is not a result that can be seen immediately but over time service-oriented architectures has a
significant reduction on development costs through component reuse.
Case Study: Starwood Hotels Uses SOA to Improve Guest Services and
Cut Costs
Starwood Hotels, realized five years ago that service-oriented architecture was in its future, says Israel Del Rio,
Starwood's senior vice president of technology solutions. The international hotel chain, which includes such
brands such as the St. Regis Hotels, Sheraton, Westin's and the W Hotels, saw that its costly, clunky old
mainframe system was limiting its ability to accommodate rapidly growing distribution channels like the
Internet. "It was too difficult to add capabilities to our CRM system, do proper searching to find properties
basically many of the things a modern IT environment needs," says Del Rio.
Starwood's current systems were also having difficult handling the rapidly increasing traffic on its Web
sites, what hospitality professionals refer to as the "look-to-book" ratio. "In the old days of the Internet, the look-
to-book ratio was 50 to 1. Now it's 300 to 1. So we needed an IT environment that could handle all those
requests." To keep the legacy mainframe system would have required a multi-million-dollar investment in
upgrades and technical support. "It was very costly, and we didn't want to be held down," he says.
So Starwood began the long process of moving its systems to an open SOA framework. "It was the best way
to let us map our technology with our various brands," says Del Rio. Instead of having each of Starwood's hotel
chains build their own applications, SOA allows the brands to share the same programs and features—but they
can be customized specifically for each hotel's look and feel. Sheraton's search function, for example, may
deliver information differently than, say, the W Hotels', even though it's the same program. "That way we benefit
from using all the same tools that can be called up by different applications and interfaces," says Del Rio.
Because SOA is built on an open framework (meaning it can be called up by different operating systems), it
also creates greater flexibility for the company to create new tools. Starwood has put in place an application that
tracks guest requests and complaints, for example. "We created a workflow around that to ensure that our guests'
needs are satisfied," says Del Rio. The company also created a program that stores and tracks frequent guests'
preferences. "These are functions that didn't exist in the mainframe at all," he says. Software from Burlington,
38
The Complete Reference To Professional SOA with Visual Studio 2005
Mass.-based SOA vendor Systinet helps Starwood track all the SOA tools it has created. "That way everyone
across our brands knows which applications are available," he says.
But it didn't happen overnight. After five years, the company is finally ready to officially dismantle its
mainframe—an endeavor Del Rio expects will save the company as much as $20 million per year in
maintenance costs. He expects Starwood to be entirely up and running on SOA by 2007. "It's a very complex
initiative with a lot of moving parts," says Del Rio, "but if applied to the right business problem, it produces
good results."
39
The Complete Reference To Professional SOA with Visual Studio 2005
Web identity service: This is an authentication and authorization service for end-users accessing IBM
applications. "When an employee or partner signs into a Web site, they have a single user ID and password for
sign-on," Miller explained. "It used to be, every time I used a different application in IBM, I had a different user
ID and password. Now, all these applications call the Web service to validate the user ID and password. This
common Web service is callable from any application.”
Factory in a box: IBM's semiconductor group built a set of services called "semiconductor factory in a box.,"
Miller said. "It has enabled us to do is invest, acquire, or divest, or outsource manufacturing plant very quickly.
If we divest a manufacturing plant, we had to rip out all the connections to various systems. Or, to acquire a new
company that comes with a manufacturing plant, we had to integrate them into our systems. The process used to
take several weeks — now it's two hours.”
Customer order and tracking system: IBM's customer order analysis and tracking system (COATS) "was a big
spaghetti-code application, all integrated into one big app," said Miller. The huge application was being
overwhelmed by order volumes, which "were causing problems with performance with the application." MIller's
staff decomposed the entire application into 13 separate components. "We found that the logjam in the
application was only in a couple of the pieces of the app. We pulled out that application code for those two
pieces and wrapped them as Web services. It was a way to rewrite a legacy application in pieces, without having
to go do the full 13 big chunks of functional capability."
Miller says SOA enablement didn't happen overnight, even for IBM. "A lot of time, when we talk to folks about
this stuff, they say, ‘oh my gosh, I could never do an enterprise architecture of that size, with the complexity of
my company. It must have taken you years.’ The answer is yes, it did take years," he related. "But you can start
in a corner of the business, business unit or functional area, and work it out from there."
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.
NHS is pursuing this degree of integration because it believes that for any given patient, the hospital’s ability to
provide rapid and effective prognosis and treatment is directly impacted by the ability of the organization to
40
The Complete Reference To Professional SOA with Visual Studio 2005
transmit critical patient data among the various departments and hospitals within the NHS system. In the face of
the NHS integration mandate, Milton Keynes determined its existing patient admission system was no longer
capable of delivering the requirements of a modern day healthcare system. The patient admission system, which
is 22 years old, annually processes 60,000 in-patient admissions and 100,000 out-patient admissions, resulting in
approximately 1.5 million transactions per year. Upon receipt of the integration mandate, this enterprise was
comprised of 28 systems spread across more than 80 servers. There were numerous heterogeneous systems in
this configuration. Additionally, there were numerous disparate connections of both a point-to-point and many-
to-many nature within the system. As a result, the system was far from rationalized, and required much work in
order to comply with the NHS integration mandate.
Early in 2005, the hospital began looking for an integration solution that could be used to rationalize its
complex patient admission system. They chose to use Web service and along with Microsoft BizTalk Server
2004 for integration.
Subsequent to selecting Microsoft BizTalk Server 2004 as the integration platform for Milton Keynes, the
hospital formed a deployment team. Milton Keynes staff members, including a project manager, a systems
architect, and an integration and systems developer were joined by four consultants from WCI, a British
Microsoft partner. Over a 4-month period, the team completed the necessary development testing and
deployment for the Microsoft BizTalk solution. The process concluded with a 3-week long installation of
Microsoft BizTalk Server 2004 for interfacing with the existing 28 local departmental systems that are currently
tied together with point-to-point interfaces.
During the deployment, Milton Keynes made extensive use of Web service and along with Biztalk’s pre-
built messaging tools designed for healthcare institutions, which helped to accommodate local compliance
requirements such as those requested by the Health Insurance Portability and Accountability Act (HIPPA).
By converting to a service oriented architecture and integrating the existing patient admission system with
Microsoft BizTalk Server 2004, Milton Keynes is now able to accelerate its IT integration, reduce costs, and
improve patient service. Some of the key benefits are:
* Rapid system rationalization. The hospital can now transform the current state of the patient admission system
from one characterized by numerous point-to-point and many-to-many connections to one resembling a hub-
and-spoke structure.
* Reduced programming costs. Because Milton Keynes will make vigorous use of its service oriented
architecture, the hospital can complete its integration tasks with far less programming costs than had been
budgeted.
* SOA adoption. Service oriented architecture adaptation is viewed as an enabler of new practices, including
solution reuse, business-to-business integration, and business activity monitoring. These are viewed as critical
going forward, as other systems within Milton Keynes are rationalized and integrated as required under NHS
National Program for IT.
* Improved patient service. By improving data flows, the hospital will be able to provide better scheduling,
diagnostic services, and treatments to its patients.
41
The Complete Reference To Professional SOA with Visual Studio 2005
consolidated to a single point. This will essentially remove local processing at a regional level and all work will
be now done at head quarters.
The regional operations center has several departments, each department focused on a particular industry
within the local retail market. Because of the difference in the type of data that is submitted from the retailers
and difference in requirement for each department. The department themselves also has their own IT operation
teams which also developed different sub systems. Some of these systems relied on SAS others relied on Access
and MS SQL Server with different Business Intelligence (BI) tools such as Cognos, Microsoft Data Analyzer,
Analysis Services and even MS Excel tied onto the front of each of the systems. It was a difficult task sorting out
what can really be consolidated at the regional level which in turn can be consolidated to the central system in
Germany.
Each regional operation center differed from each other. Industry information and categories within each
region also differed greatly from each other. This posed an issue when trying to consolidate data and applications
at a regional level. On top of these problems with changes the operation teams were having a hard time
maintaining operation of the current systems. For quite awhile it seemed that the entire consolidation process to
Germany was on the verge of failure.
To ensure stability and operation at the regional office the head office has requested all regional offices
construct Web services on top of each application. With this request regional offices quickly established scalable
Web services on top each of its proprietary systems. The head quarter operation team was then able to duplicate
all applications to the head quarter level and using a hub and spoke approach with Enterprise Service Bus (ESB)
integrated the local proprietary systems into its centralized process.
42
The Complete Reference To Professional SOA with Visual Studio 2005
Summary
Web services uses SOAP messages a specific type of XML message format determined by the W3C standards to
communicate over a number of protocols such as HTTP.
Due to the open nature of web services, it is possible for many web service consumers to access the same
service regardless of operating system or programming language. As long as a consumer invokes the web service
using a SOAP request in standardized format. It does not care for the language the service is written in nor does
it care for the platform the Web Service is currently on.
Each web service can contain a Web Service Description Language (WSDL) document that provides the
potential consumer of the service with an explanation of how the service works and how to access it. The WSDL
describes how to create a SOAP request that will invoke that specific web service. If a developer wanted to
create a Web Service consumer application, they simply need to retrieve this XML document, which will
provide all the information the developer require to develop the new application to invoke the relevant functions
within that Web Service. Due to the self-describing nature of the web service it allowed developers to quickly
develop distributed applications without requiring understanding of the underlying technology or functionality of
the service.
Web Service also uses Universal Discovery, Description, and Integration (UDDI), which is a listing of web
services available within a particular network. The UDDI functions like a “yellow pages” of web services.
Potential web service consumers can search for the web services that are available for use through the UDDI
directory.
Web Services play a key role in the promotion of Service Oriented Architecture. As it is technology neutral
and uses an open-communication framework such as XML. This quality allows distributed applications to be
43
The Complete Reference To Professional SOA with Visual Studio 2005
developed, integrated and maintained with ease and most importantly it supports the reuse of existing technology
investments.
44
The Complete Reference To Professional SOA with Visual Studio 2005
Chapter 2 Implementing
Service Oriented Architecture
In order to successfully adopt SOA into enterprise architecture we must first determine its goals or destinations.
To do this we need a clear idea of where we are and a vague idea of where we want to be. In this chapter we will
continue to discuss SOA theories and concepts and most importantly we will focus on the implementation side of
SOA.
45
The Complete Reference To Professional SOA with Visual Studio 2005
There are four phases to developing your SOA roadmap: SOA Planning, SOA Maturity Assessment, SOA
Future Vision, and SOA Roadmap Definition. Once the roadmap had been defined and development begins, at
the end of each iterative development phase there must be an Iterative Quality Assurance stage to ensure that the
overall development is in sync and on track with the SOA roadmap defined.
Figure 2-1. Six-domain model for a SOA roadmap (Copyright BEA Systems - Used with permission)
In order to plan for a successful SOA implementation. Our SOA roadmap should encompass six domains Figure
2-1. These domains, while distinct, are interrelated and interdependent. Implementation on each domain is
fundamental to the success of an enterprise-wide SOA. Our SOA roadmap should clearly outline the boundaries
of our SOA initiative and establish a transparent timeline for achieving our SOA goals. Each domain’s area of
responsibility is illustrated in the table below.
Domain Focus
Business Strategy and Process SOA-enabled Business strategies
Business process architecture is derived
Architecture Reference Architectures
Manageability/Availability
Scalability
Security
Building Blocks Public Services, Logic Centric Services, Data Centric Services,
Transitional Services, and Basic Services
Projects and Applications Existing Applications
Key “in-flight” Projects
Infrastructure Construction Plans
Organization & Governance Organization Design
Funding
Skill sets
Roles and Responsibilities
46
The Complete Reference To Professional SOA with Visual Studio 2005
Standards
Operational Processes and Tools
Change Management
Cost & Benefits Constructions costs
Business & IT Benefits
Key Measures
SOA planning
Defining a plan for the implementation of SOA is vital to the success of the overall architecture. In any
organization alteration or new development needs to be justified. After all there is no point in moving to SOA
without a strategy. The return on investment in the exercise must also be justified in the long run. Planning also
allows constant monitoring of the progress as well as successful evaluation of the architecture.
During this phase, your SOA initiatives are organized and defined. Stakeholders are brought into the process
through communications and briefings and mutually agreed upon priorities and parameters are set. Because this
phase involves employees across your organization, clear and ample communication is critical. During this phase
you will:
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.
* Business Strategy and Process: Top-down view of business strategies and processes.
47
The Complete Reference To Professional SOA with Visual Studio 2005
* Projects and Applications: Review of existing systems, and in-flight and planned projects.
* Organization and Governance: Analysis of existing governance structures and policies.
* 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.
* Cost and Benefits: Roadmap of future metrics, cost structures, and benefits cases.
SOA Governance
Governance in SOA is particularly vital in its ability to assess and ensure flexibility of the enterprise
architecture. The definition of the word governance implies the action or manner of governing. Further, IT
governance is a decision and accountability framework to encourage desirable behavior in IT. Participants of the
governance body lay down policies around different categories of decisions that need to be made. That body also
decides upon the people in the enterprise who are empowered to make those decisions; that is, it carries out role
identification. The members of the governance council also identify subject matter experts who are expected to
provide input to firm up the decisions and also identify the group of people who may be held accountable for
48
The Complete Reference To Professional SOA with Visual Studio 2005
exercising their responsibilities (based on their roles). An effective IT governance council must address three
questions:
1. What decisions must be made to ensure effective management and use of IT?
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.
Basic services
These are silo like services, which access data and contain certain amount of data operations and also some basic
business logic. These services are predominantly simple services that could easily be used and reused. Basic
services that provide both data and business logic can be referred to as agile and reusable as services. For
example, a social security number validation service will access the database to find the name that the social
security number belongs to. At the same time there is some simple logic to validate the social security number
before a call is placed to the database. In this regard this service both contains basic data access and some basic
business logic.
Data-Centric Services
A data-centric service handles the storage and retrieval of data, these services also handles transaction
management. These data-centric services often retrieve data from a database; as such it acts similar to that of the
data layer. These are important part of any enterprise application development and often provide as a solution to
data ownership. It allows access to data from different data vendors. The user of the service does not care for the
vendor of the service or what kind of query language the service uses to query the database. All that the
consumer of the service need is the interface. This improves the flexibility, transparency and allows more
efficient reuse of the service.
49
The Complete Reference To Professional SOA with Visual Studio 2005
Logic-Centric Services
These are services, which contain complex business rules or business logics. In the past these functionalities in
application development are deeply nested within the application. It was difficult to reuse these encapsulated
logics as it was too tightly coupled with the application. Through the use of Logic-Centric Services complex
logic can be exposed and easily reused by any application that requires it. The Logic-Centric Service may be
sitting on a proprietary system, which does not usually interoperate with applications requesting the service.
However through the use of Web service we can expose the service and allow other users to request for its
service.
A good example of Logic-Centric Service is a bank that’s providing home loan. The home loan formula is
extremely sensitive and should not be known by its competitors, however the bank wishes to provide the home
loan service to its partners. With every request personal account details and income information are sent to the
service. The service then takes these values and calculates against the imbedded business rules to work out an
estimated loan. This amount is then returned to the requesting client. There is minimal data processing and the
service is purely business logic.
With the Logic-Centric Service exposed, the bank can easily provide the loan estimate service to its partners
whilst keeping its business logic secure and central within the bank. Because of the nature of Web service’s
interoperability, it allows this particular functionality to be integrated with internal applications as well as
utilized by external applications from its partners.
Transitional Services
These are services that are generally placed on top of an existing legacy system to allow access from external
applications. Traditionally components are not always interoperable with each other as a result it was difficult to
work with one another. These could be components that provided any level of services. They can be data centric,
logic centric components or components that provided network access. Transitional services provide access to
these components by placing a transitional layer between these legacy components and that of the outside world.
This allowed for reuse.
Transitional services provide a huge amount of flexibility, to applications and components that had already
been developed. They allow existing systems to be more robust and agile.
Public Services
These are services that were exposed to the public in the sense that they’re outside the domain of business logic.
In SOA these services are used to provide cross-enterprise integration. These can be services that are offered by
a company to its partners and customers. An example of Public Services in use would be Amazon. Amazon
provides public services to allow its partners to build applications that utilize these services to retrieve
information about books that are currently available on Amazon.
Public Services are versatile they provide a gateway for the outside world to access functionalities within a
business domain. This allows the business to sell and promote its product in this case Amazon is allowing its
partners to build applications that access Amazon’s database. Allowing them to integrate Amazon into part of
their applications. Public Services really is the face of SOA and one of the most popular and used service types.
50
The Complete Reference To Professional SOA with Visual Studio 2005
and Data. Layers, refers to the logical organization of code. Layers are primarily used to gain the benefits of
logical organization and grouping of similar functionalities. In application development logical layers offer
reuse, easier maintenance and shorter development cycles. Proper layering of software reduces the cost to
develop and maintain an application.
Tiers however, are only about where the code runs. Specifically, tiers are places where layers are deployed
and where layers run. In other words, tiers are the physical deployment of layers. Tiers refer to boundaries these
are either process or network based. A one-tier model has all of its layers running from a single memory or
processor space on the same machine. A two-tier model has two separately working memory spaces with tiers in
each of the working space. The number of boundaries for an n-tier model with can be calculated as having n-1
boundaries.
Traditionally, software that were developed were isolated and thus and layering provided all the abstraction
required for code reuse in this silo architecture. However as application development had evolved to become
more distributed, layering is no longer an adequate way to provide abstraction at the enterprise level. This is
especially the case when parts of the application are located in other regions of the world.
SOA layers should not be confused with the traditional software layers, and tiers. In SOA layers are
effectively traditional tiers. SOA layers provide a conceptual structure at the enterprise level.
Let’s have a look at SOA layers. Figure 2-2 shows different service types possible within a SOA, though
SOA is flexible enough to not to conform to this one particular model. Each service type essentially has the
ability to become a public service. Although for security reasons public services should always be documented
and noted.
51
The Complete Reference To Professional SOA with Visual Studio 2005
This trend, in its movement towards automating business processes between systems, promotes the value of
Service Oriented Architecture (SOA). Integrating and aggregating information (entities) that is present in
different systems and is essential in building solutions that will support this trend. For example, in many
businesses employees must make separate phone calls to HR, Payroll, and Benefits to have their addresses
updated in the different systems. Through SOA, however, multiple systems can become integrated and the
entities in the different systems aggregated. By automating these simple processes, employees can now make one
phone call or use a self-service portal and update their personal information seamlessly across numerous
systems.
Businesses can also reduce total cost of ownership (TCO) by connecting systems with Service Oriented
Architecture. Over time, the Enterprise IT group may plan to deliver services directly to end-users by integrating
multiple systems. This means that services, offered by applications such as enterprise resource planning (ERP)
and customer relationship management (CRM) systems, will be available to end-users, which results in an
overall reduction in the TCO for supporting the business functionalities. This is where Entity Aggregation plays
a large role.
An Entity Aggregation solution can be designed to not only act as a single point in accessing information
that exists in multiple systems, but it also provides a holistic view of an entity and the entity model. Additionally,
Entity Aggregation solutions address several design issues to ensure the success of Service Oriented
Architecture.
The underlying goal of Entity Aggregation service is to design an Entity Aggregation layer that acts as a
single point to access information that may exist in multiple systems.
There’re three main reasons why entity aggregation is important.
52
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 2-3 shows the aggregation of the employee table between the payroll system and the benefit system. Previously update
of information required users to log into both systems to update their personal information. However with entity aggregation
update to the aggregated view of the employee table will result in update of both Payroll System and the Benefit System.
Horizontal Partitions
There are cases where geographical constraints require a partitioning of entries across services. At certain times,
however, a solution may require a complete set of information to obtain a detailed picture across services. One
example of this of a distributed of stock trades as an entity that is partitioned across various geographical
locations.
Figure 2-4 shows the horizontal partitioning across services provided by a UK stock trader and a US stock trader. If a
company wished to request information on the performance logging into individual stock trader is troublesome especially if
you need to check regularly. By aggregating the available information to a higher level. We can perform queries and check
performance at the click of a button.
53
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 2-5 depicts cross system join between an ordering system and an inventory system. In Service-Oriented Architecture it
is often necessary to query independent systems to bring a more simplified, holistic view to the consumer of the service.
* Orchestration: Refers to an executable business process that may interact with both internal and external Web
services. Orchestration describes how Web services can interact at the message level, including the business
logic and execution order of the interactions. These interactions may span applications and/or organizations,
and result in a long-lived, transactional process. With orchestration, the process is always controlled from the
perspective of one of the business parties. See Figure 2-6.
* Choreography: More collaborative in nature, where each party involved in the process describes the part they
play in the interaction. Choreography tracks the sequence of messages that may involve multiple parties and
multiple sources. It is associated with the public message exchanges that occur between multiple Web services.
See Figure 2-6.
54
The Complete Reference To Professional SOA with Visual Studio 2005
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.
55
The Complete Reference To Professional SOA with Visual Studio 2005
In Figure 2-8, the messages all represent basic activities for connecting the services together. In BPEL4WS
we can predefine a number of models we can define sequential processing for workflow where services are
executed one after the other. Alternatively we can specify a parallel processing model for workflow where
messages are sent to several service at the same time for processing. A third model where conditional looping is
supported.
Coordination Services
WS-Coordination is closely associated with the WS-Transaction specification, which defines two distinct
coordinated types, both of which are relevant to enterprise integration environments. The first, atomic
transactions, enables the management of ACID like transactions. The service model for atomic transaction
56
The Complete Reference To Professional SOA with Visual Studio 2005
coordinators is the most common type of coordination service used in legacy integration architectures. The
second coordination type provides a model for long running transactions, and is represented as part of the
coordination service model.
Business service coordination is a typical characteristic of EAI solutions, which is why coordination
services for business activities are utilized exclusively for the management of business activities. Coordination
services are generally used in conjunction with logic-centric services as a means of handling success and failure
conditions related to the execution of the overall process activities.
The WS-Coordination specification provides an assembly of services with predefined interfaces that support
the management of a coordination context. Specifically, this collection of services provides separate operations
for the creation of a context, the registration for a context, and the selection of a protocol.
57
The Complete Reference To Professional SOA with Visual Studio 2005
implementation. The service interfaces should be accessed using an infrastructure that can route and transport
service requests to the correct service provider. As organizations expose more and more functions as services, it
is vitally important that this infrastructure should support the management of SOA on an enterprise scale.
One of the key enablers in a SOA enabling architecture is the Enterprise Service Bus (ESB). Enterprise
Service Bus is used by large organizations to enforce standardization on Service Oriented Architecture. The role
of the service bus is to enable the basic interactions between different service components across a range of
varied platforms. It also provides a new way to build and deploy enterprise SOA. ESB is a concept that is
increasingly gaining the attention of architects and developers, as it provides an effective approach to solving
common problems such as service orchestration, application data synchronization, and business activity
monitoring.
Enterprise Service Bus helps to support the concepts of SOA implementation through decoupling of the
consumer’s view of a service from the actual implementation of the service, decoupling the technical aspects of
service interactions, and the Integrating and managing services within the enterprise.
Decoupling the consumer’s view of a service from the actual implementation greatly increases the flexibility
of the architecture. It allows the substitution of one service provider for another (for example, because another
provider offers the same services for lower cost or with higher standards) without the consumer being aware of
the change or without the need to alter the architecture to support the substitution.
In SOA, services are described as being loosely coupled. However, at implementation time, there is no way
to loosely couple a service or any other interaction between systems. The systems must have some common
understanding to conduct an interaction. Instead, to achieve the benefits of loose coupling, consideration should
be given to how to couple or decouple various aspects of service interactions, such as the platform and language
in which services are implemented, the communication protocols used to invoke services, the data formats used
to exchange input and output data between service consumers and providers.
Traditionally, Web service interactions between consumers and providers are relatively straight forward. It
generally involves a Web service consumer requesting an operation directly by sending a message to the Web
service provider. The provider then responds with a SOAP message to the consumer with the operation results.
This sort of interaction pattern is easily maintained in small to medium architecture. However as the number of
Web services increase so does the complexity involved and a pattern using simple point-to-point link is not
sufficient. In applications that require large amount of Web service calls with spaghetti type interactions
requiring multiple security and transactional supports is where ESB’s value can be realized.
The ESB helps to provide an abstraction between the service providers and service consumers Figure 2-9.
This abstraction aids the decoupling nature between service consumers and the service providers. Requirements
as routing control, logging and monitoring and over all interaction management can be implemented easily
through the use of ESB, in an environment that would otherwise require considerable modification to
applications to implement.
58
The Complete Reference To Professional SOA with Visual Studio 2005
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.
The diagram in Figure 2-10 shows the implementation of an architecture using Web service. This results in
simplified and interoperable bindings at each component endpoint. However, as the number of components
increases, the complexity of the application also increases due to the complexity of message interactions between
components.
Figure 2-11. Architecture using Web service and Enterprise Service Bus
The diagram in Figure 2-11 shows the implementation of an architecture using Web service as well as
enterprise service bus. This results in simplified and interoperable bindings at each component endpoint. The
59
The Complete Reference To Professional SOA with Visual Studio 2005
complexities of message interactions between components are governed by the enterprise service bus. As such if
the number of components increases the application does not necessarily increase in complexity.
Mediation support
The ESB provides mediation support to enable service interactions for example, the ESB can help a consumer
service find services that provide the requested capabilities and or to help take care of a interface mismatch
between the consumers and the providers. In many ways the ESB is much more than just a transport layer. It
must support a variety of ways to get on and off the bus, such as adapter support for existing applications or
business connections, that enable external partners in business-to-business interaction scenarios. To support
these different ways to get on and off the bus, it must support service interaction with a wide variety of service
endpoints. It is likely that each endpoint will have its own integration techniques, protocols, security models and
so on. This level of complexity should be hidden from service consumers. They need to be offered a simpler
model. In order to hide the complexity from the consumers, the ESB is required to mediate between the multiple
interaction models that are understood by service providers and the simplified view that is provided to
consumers.
Protocol independence
Services can be offered by a variety of sources. Without an ESB infrastructure, any service consumer that needs
to invoke a service needs to connect directly to a service provider using the protocol, transport, and interaction
pattern that is used by the provider. With an ESB, the infrastructure shields the consumer from the details of how
to connect to the provider.
By using an ESB there is no longer a direct association between the service consumer and the service
provider. The ESB acting as a tier shields the service consumer to the location of the service provider. The
consuming service in turn accesses the ESB to invoke the required service. The ESB can then convert the request
to the appropriate protocol or format before passing the information on.
The ESB generally supports several protocols and standards. Even if it in some cases the location
information is stored in a Customer Information Control System (CICS®) transaction and using a Java 2
Enterprise Edition platform resource adapter as protocol integrated with the CICS Transaction Gateway. By
using the ESB, the consumers are unaware of how the service is invoked on the provider. ESB thus allows
applications that do not implement service interfaces to become interoperable and aid in the migration of
architectures towards SOA.
Additional, process management engines can be integrated into an ESB allowing the process management
engine to manage and monitor the interactions of services within the ESB. Unlike traditional integration brokers
these service oriented process engines can control an entire network of loosely coupled service components. This
60
The Complete Reference To Professional SOA with Visual Studio 2005
can dramatically increases the scalability of applications whilst improving business process management
throughout the architecture.
Within the ESB events are triggered whenever messages are received. With both service consumers and
service providers none the wiser about the interactions that happen between requests. An architect can easily
configure interactions between two points as point-to-point then later alter the configuration to broadcasting. All
of these changes can be made without altering the underlying application implementation or its interfaces.
Figure 2-12 shows the inner working of orchestration happening within an enterprise service bus.
Orchestration-managed messaging tends to be more sophisticated than the standard SOAP messages you
may be using in simpler integration scenarios. For instance, messages processed by EAI components can contain
routing and transaction information in addition to standard data structure. Also, messages undergo various states.
The use of orchestration will often classify an integration solution as a virtual application. Abstracting
process and business logic into orchestration workflows also results in elaborate service assemblies that
encapsulate aggregated process logic.
61
The Complete Reference To Professional SOA with Visual Studio 2005
The SOA’s inherent security problems stems from the way in which the SOA replaces traditional security
parameters with new, open standards. The security problem exists in that not only are the new standards
completely open but also the onus of which its security ownership belongs to is uncertain in a distributed world.
Web Services were developed over a period of years by industry consensus as a way to enable the creation
of reusable distributed code, simplify development, and streamline system integration. However these did not
address security. Specifically, XML, SOAP, WSDL, and UDDI are open standards that enable the transmission
and description of data and procedure calls between systems. However, none of these open standards contain any
inherent security aspects of their own. If left alone, they are completely non-secure. In fact, web services were
designed to be able to move more efficiently through firewalls. This very loose coupling and flexibility increased
its usability but decreased its security in this regard.
The main issues of any basic security infrastructure are authentication, authorization, and confidentiality.
The focus broadens where the infrastructure is exposed as in the case of SOA. In this case, concerns such as non-
repudiation, message integrity, and legally binding identity assertion become vital.
In this section, we will discuss these principles. The goal is to use security as a tool to foster and encourage
the use of Service-Oriented enterprise architecture.
Security Basics
Authentication
Authentication is used to establish that the requesting consumer is genuine and that the account is valid. The
caller must provide identity credentials such as username and password or in some cases a digital certificate. In
SOA there can be three levels of authentication:
Authentication at the application level is generally straight forward and mandatory for the business in order
protect from unauthorized access. Authentication at the infrastructure level is preferred instead of requesting
access to each Web Service. This allows security policies to be maintained more easily at a central place instead
of for each web service.
A single sign-on framework can provide credential mapping, providing the correct logon credentials for
each invoked service or even backend applications. Single Sign-on is usually straight forward and transparent to
implement.
Authorization
In security authorization refers to the process of validating that a client has the necessary security privileges to
perform certain functions, or in our instance invoke a particular method on the Web service.
Most Web services coming in over the public network to an enterprise require authentication. A payment
gateway can not provide the service to debit money from an account until it knows who is using it. So
fundamentally, authorization requires authentication.
One method for authorization to be implemented is through a set of credentials that a subject identity carries
and presents. These credentials are then mapped to allow access to certain contents.
62
The Complete Reference To Professional SOA with Visual Studio 2005
Integrity
In security integrity refers to examining a message to see if it has been tampered with since it was initially
created. In SOA generally communication is facilitated through open publicly available networks. There is every
chance that as a message is produced and put on the wire that the message is intercepted and its content altered.
The altered content is then put back on the wire and sent as the original message to the receiver. This is a form of
deception and it is a possible form of attack that is possible in an open network unless security procedures are
implemented. We can ensure the validity of message integrities through process such as encryption and hashing
we will be talking about Web service security later in Chapter 13 (Web Service Security) and Chapter 16
(Windows Communication Foundation). Message integrity check thus refers to validating the message was
received precisely as it was sent with no content altered.
Confidentiality
In security confidentiality refers to keeping a message confidential. Implementing confidentiality is important in
SOA context. This is because of the open architecture of SOA. With the necessary access to network it is
possible to intercept messages. Thus keeping information secure and confidential is especially important when
financial applications are concerned. By using encryption we can scramble the messages so that only the
authorized recipients can decrypt and view the message. Even if messages are intercepted without the decryption
key the message itself remain scrambled and useless. In XML Web service we can use a number of encryption
techniques to keep the message confidential. The most popular method is to use a Public Key Infrastructure
(PKI) where a message is encrypted using a public key and decrypted with a private key issued through a trusted
third-party authority.
Non-repudiation
Non-repudiation proves that one identity sent the data to another identity. This proves that the recipient entered
into this specific transaction, and neither party can refute or deny that it occurred later. Non-repudiation is
achieved through the use of public key cryptography. One identity prove that it had sent the data only to another
identity because the sender used the recipient’s public key, and it is only the recipient with his secret private key
who can decrypt the data. To achieve non-repudiation, separate timestamp notary is required to prove when the
transaction occurred as well as independent verification of the participant’s identities.
63
The Complete Reference To Professional SOA with Visual Studio 2005
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.
In the above diagram Figure 2-14 we’re implementing point-to-point security added with end-to-end security. Even
though data travel through networks that does not implement the necessary SSL data security (point-to-point). The data
itself is encrypted (end-to-end). Thus data protection is ensured at all stages of travel.
Another protocol for transmitting data securely over the World Wide Web is Secure HTTP (S-HTTP).
Whereas SSL creates a secure connection between a client and a server, over which any amount of data can be
sent securely, S-HTTP is designed to transmit individual messages securely. SSL and S-HTTP, therefore, can be
seen as complementary rather than competing technologies. Both protocols have been approved by the Internet
Engineering Task Force (IETF) as a standard.
However point-to-point based security has its limitations. Firstly, SSL is designed to provide point-to-point
security, which falls short for Web services because we need end-to-end security, where multiple intermediary
nodes could exist between the two endpoints. In a typical Web services environment where XML-based business
documents route through multiple intermediary nodes, it proves difficult for those intermediary nodes to
participate in security operations in an integrated fashion.
Secondly, SSL secures communication at transport level rather than at message level. As a result, messages
are protected only while in transit on the wire. For example, sensitive data on your hard disk drive is not
generally protected unless you apply a proprietary encryption technology.
64
The Complete Reference To Professional SOA with Visual Studio 2005
Thirdly, point-to-point in its current form does not support non-repudiation well. Non-repudiation is critical
for business Web services and, for that matter, any business transaction. What is non-repudiation? Non-
repudiation means that a communicating partner can prove that the other party has performed a particular
transaction. For example, if E-Trade received a stock transaction order from one of its clients and performed the
transaction on behalf of that client, E-Trade wants to ensure it can prove it completed that transaction to an
arbitration committee, for example, if a dispute arises. We need some level of non-repudiation for Web services-
based transactions.
Finally, point-to-point does not provide element-wise signing and encryption. For example, if you have a
large purchase order XML document, yet you want to only sign or encrypt a credit card element, signing or
encrypting only that element with SSL proves rather difficult. Again, that is due to the fact that SSL is a
transport-level security scheme as opposed to a message-level scheme.
Even though point-to-point provides some aspects of security such as confidentiality and authentication,
however, web services require data validation, accountability, and distributed authentication and authorization.
None of these are provided by point-to-point security. However, these security requirements can be
supplemented with the use of XML security technologies, including XML Signature and SAML, which apply
security at the message layer. Please note that point to point does not compete with end to end in fact the two
complement each other however point to point alone is not adequate enough for the purpose of providing SOA
level security.
For the purpose of this book we will focus on achieving end-to-end security.
The mechanism that we choose to use for authentication will have an affect on other security
implementations such as encryption and signatures.
65
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 2-16 depicts a direct authentication when a client and service share a trust relationship.
In Web service a consumer of a Web service can directly submit authentication information to the web service
when a client and service share a trust relationship Figure 2-16. This is regarded as Direct Authentication. This is
simplest form of authentication in terms of implementation.
In a more complex model where a client and service do not share a direct trust relationship, a mutually
trusted broker can be used to perform authentication. The client will send a request to the authentication broker
who then validates the client and sends a security token. The client then using the security token can send
requests to the Web service. Upon receiving the request the Web service then sends the token to the
authentication broker for validation. If the broker returns a valid response then the Web service will process the
request. Though, typically the Web service does not always send the token to the broker for authentication. As
receiving the token is often enough proof of the client’s relationship with the broker.
Figure 2-17 using a broker to perform authentication when client and service do not share a trust relationship.
WS-Security
WS-Security is the name given to the set of security standards that have been ratified by the Organization for the
Advancement of Structured Information Standards (OASIS). WS-Security is a conceptual model that abstracts
66
The Complete Reference To Professional SOA with Visual Studio 2005
different security technologies into “tokens”. It formalizes a way to package security tokens into SOAP
messages. WS-Security provides a set of additional roadmap specifications built on these concepts and integrated
into XML specifications. These roadmaps describe how to apply for a security token, how tokens are linked to
identity and how they’re linked to a web service and more.
XML Encryption
XML Encryption utilizes cryptography technology using shared key encryption. Shared key encryption was
selected because it allowed for the encryption of varying sized XML messages efficiently. Encryption provides
for message confidentiality (the message remains a secret from all but its recipient). The reason XML encryption
is needed over and above point-to-point encryption mechanisms like SSL is because confidentiality of messages
needs to be maintained while the message is taking multiple server hops on its way to its destination. This will
be common when shared services are utilized. We also need confidentiality when the XML message is stored
even after it reaches its final destination. This requirement is called persistent confidentiality.
There are two types of encryption typically used in Web service security these are symmetric key encryption
and asymmetric (public) key encryption otherwise known as Public Key Infrastructure (PKI), both encryptions
can be used in conjunction with one another.
Symmetric Key Encryption, refers to encrypting and decrypting a message using the same
key. The key is always kept private and only known to each of the parties that is one who
encrypt and send the message and one who receive and then decrypt the message. Symmetric
Key Encryption is simpler to implement than Asymmetric Key Encryptions and performance
wise it is faster because it requires less computation.
Asymmetric (Public) Key Encryption, also known as Public Key Infrastructure (PKI) refers
to encrypting and decrypting using two different keys a public key which is used to encrypt a
message and a private key is used to decrypt the message. When the owner of the private key
wishes to send a message to other parties the private key can be used to encrypt the message
and the public key used to decrypt the message. Today Asymmetric Key Encryption can be
implemented through X.509 certificates. A client uses the public key (of an X.509 certificate)
to encrypt his message and only the owner of the private key (of that X.509 certificate) can
decrypt the message.
Due to the open nature of Web service security is very important, since SOAP messages are essentially just
plain texts that are transported across the wire. Anyone can intercept the message and read its content. The Web
Service Extension (WSE ) specification supports both symmetric and asymmetric encryption. Using WSE, in
symmetric encryption the Web Service and the client share a secret key outside the SOAP message
communication, the client encrypts the message using this key and the Web Service decrypts the message using
the same shared key.
XML Signature
XML Signature is the foundational technology for the Web service security standard called WS-Security. XML
signature is built on top of mature digital signature technology. The purpose of digital signatures is to provide a
mechanism for message integrity (to ensure no alteration on the message) and non-repudiation (can not contest
that the transaction had occurred). XML Signature enables you to encode digital signatures into XML.
67
The Complete Reference To Professional SOA with Visual Studio 2005
the path of the SOAP messages that travel back and forth between a web services consumer and a web service.
Because of their ability to process, monitor, copy, and forward the data-rich SOAP messages. SOAP interceptors
are a very prominent element in SOA security. An SOA security solution examines the SOAP invocation
messages approaching the web service as well as the response to those service calls. It analysis the message, the
SOA security solution checks to ensure that the requesting entity is authenticated and authorized to use the web
service. The SOA security solution accomplishes this by checking the user data contained in the SOAP message
header.
Your SOA security solution should be complementing an existing security solution that you deployed to
secure your entire enterprise before beginning transitioning to an SOA. This may mean that your SOA security
solution will need to plug into existing security infrastructures to authenticate and authorize access requests.
Figure 2-18 Shows a SOAP Message interceptor, interception and authorizing messages.A vendor requires access to a
particular service from the supplier, the request is interrogated against an existing security infrastructure before it is
forwarded onto the service within the network.
The authentication and authorization of the users on the SOA occurs when their credentials are checked with
the security infrastructure of authorized users Figure 2-18. This is achieved by intercepting the SOAP messages
and comparing the users listed in the message header with those users stored in existing security infrastructure.
68
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 2-19. shows a federated authentication user database created from a Partner X with a LDAP system and a Partner Y
with an internal custom security solution system.
In Figure 2-19 a request is sent by one of the partners requesting for service from our server. The message
passes through the firewall and is received by our security infrastructure which then validates for authentication
and authorization. If the request is from a valid client then the message is forwarded on to the service. Otherwise
the message will simply be dropped
69
The Complete Reference To Professional SOA with Visual Studio 2005
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.
70
The Complete Reference To Professional SOA with Visual Studio 2005
ordering is preserved. Of course, Web service reliability does only refer to messaging. Security, transactions and
execution environments such as clustering and redundant storage all have an impact on reliability.
Reliable messaging technology requires a piece of software infrastructure deployed on both ends of
connections. The reliability-messaging agent handles errors in the transmission of messages from one computer
to another over a potentially unreliable network. Typically the agents are symmetrical implementations so that
mutual handshakes can be implemented.
The reliability-messaging agent assigns a sequence ID to a group of related messages and message IDS to
the individual messages within the group. The requester’s agent marks the last message in the group, and the
provider’s agent returns an acknowledgement to indicate whether all messages in the group were received. If one
or more message IDs are missing from the acknowledgement, the missing message is resent until the provider’s
agent returns an acknowledgement containing all the message numbers in the group.
The sequence IDs and message IDs can also be used to prevent duplicate message processing and to require
that messages be processed in the order they were sent. Reliable messaging mechanisms can be used with SOAP
Message Exchange Protocol (MEP). A MEP is a template specified for exchanging SOAP messages between
nodes to ensure reliability. Typically the message exchange between nodes is predefined synchronous data
exchange.
A reliability layer is introduced between the transport and the application that interprets and executes a
series of message acknowledgements Figure 2-21. Acknowledgement from the provider allows the consumer to
know if a message has been successfully received by the Web service. This is very important in a mission critical
system. The reliability allows both parties to temporarily store their message within a file or a database incase of
unsuccessful or missing messages. The sequence of messages is then removed from the database when
acknowledgement is received from receiving party. However if a message acknowledged as missing then it will
be retrieved from the database and resent to the receiving party.
In Web service specification both WS-ReliableMessaging and WS-Reliability establishes standard processes
for the acknowledgement of successful message deliveries and the notification of transmission failures. It can be
used in conjunction with other specifications, such as WS-Security, WS-Policy, WS-Coordination, and WS-
Transaction.
Summary
Developing for any architecture requires a great deal of requirements gathering and planning, and with it comes
a great deal of responsibility. The initial step is to plan out the roadmap that you will need to take through out the
development of your SOA. This will help you realize your long-term goals whilst keeping your short term goals
in check.
71
The Complete Reference To Professional SOA with Visual Studio 2005
Your SOA needs to be agile and flexible and structured according to business domains and business
requirements. This can be achieved through the use of several service types. These are Basic Services, Data-
Centric Services, Logic-Centric Services, Transitional Services and Public Services. These services are used to
provide SOA layer, which abstracts the constraints such as location, operating system, and language. Together
the different service types help to create a balanced SOA architecture.
If you’re developing on top of legacy systems or large enterprise systems that already has web services quite
often you will need to aggregate these entities to a higher level. This is important in maintaining abstraction at a
higher level and ensures that the overall SOA remains flexible and agile so that they do not need to consider
physical location constraints.
In SOA, Enterprise Application Integration (EAI) is aided by an integration middleware. Its role is to
connect a broad range of applications and let the organization decide how they should be logically coupled to
automate key business functionalities. The middleware provides organizations with flexibility to allow services
to publish and subscribe asynchronously. This resulted in the rise of Event-Driven Architecture (EDA) which
uses SOA based concepts to provide a more flexible and robust system of collaboration.
However due to the flexibility and openness of SOA it opens up security vulnerabilities. We have examined
various security concepts within the chapter to lock down and secure a real enterprise SOA. These techniques
include: point-to-point and end-to-end security, web service authentication, xml encryption, xml signaturing,
SOAP message monitoring, Security Assertion Markup Language and Application Proxying. Understanding of
these techniques are essential in providing your enterprise with a secure and yet flexible architecture that will
save you in the long run.
We have also discussed the importance of ensuring message reliability in a largely unreliable delivery
system. This is essential in any form of mission-critical systems where successful transmissions of message to
destinations are vital.
Overall we have examined various aspects of SOA and by now you should have a firm grasp and
understanding of SOA and the tasks involved in approaching planning, development and deployment.
72
The Complete Reference To Professional SOA with Visual Studio 2005
73
The Complete Reference To Professional SOA with Visual Studio 2005
their competitions. In order to remain efficient, partners and suppliers must regularly evaluate to find better
quality, prices and conditioned products.
Agility
We’ve constantly mentioned agile architecture. In case we’re still confused or wondering what it is, agile
architecture simply means an architecture that is responsive to the need of that of the business its serving.
However to reach agility is no simple matter. In order to fully understand the benefit of agility we must identify
74
The Complete Reference To Professional SOA with Visual Studio 2005
the different levels at which enterprise projects may be threatened by complexity. These inevitably, diminish the
effect of an agile architecture.
Technology
Technology and the ability to understand the complexity of different technologies as well as its functionalities is
always going to be an issue. Often complexity comes as a result of yearlong efforts to add patches to existing
systems which provide more functionality. Whilst other complexities come as a result of using cutting edge /
bleeding edge technologies that have not yet matured. This results in complex configuration as well as
proprietary systems that is not backward compatible in its future releases. Finding the right people to manage
these technologies will always be a key limiting issue.
Table 3-1. Outlines the difference in meaning even when they’re common words in English.
pavement (noun) paved area at side of road set paved surface of road (US)
aside for pedestrians (CA, GB, HK)
biscuit (noun) A crisp, generally sweet, confection Soft, flakey savoury pastry eaten
(AU, GB, HK, ZA) with gravy (US)
table (verb) To put forward a proposal (AU, CA, To abandon a proposal (US)
GB, HK)
Business Process
Business process complexity is not always obvious. However it is as important as the technological complexity.
Typically a complex business process will result in a complex implementation. It is often during implementation
that the real complexity comes through. Another issue with Business process complexity is that there is quite
often a lack of documentation. In any business, processes should be documented. However, realistically this is
not always the case. Quite often documentations were made at the start of a process and as the business
processes evolve the documentation is left behind. This is an inherent issue in IT as outdated business process
documentation often finds their way to an unsuspecting developer. Sometimes the issue does not become
immediately visible until solution becomes complete.
75
The Complete Reference To Professional SOA with Visual Studio 2005
Business Functionality
Business functions themselves can be complex. They can contain complex contradicting logic between different
functions. The complexity associated with any one function could exponentially explode at its component level.
A very good example of this is insurance, the complexity involved in calculating something as simple as
premium could easily become exponential based existing data. At a global level each service providing logical
functions has the potential to have its complexity increased exponentially. In this case careful planning and
detailed documentation is required at every level. This will save tremendous amount of time on future support
and maintenance.
Integration
Integration is key to any enterprise application. Typically, enterprise projects combine functionality from
existing applications. Even if the individual application is stable and has been well tested, using it in a new
context and integrating with them and other application generally can become complex and unpredictable.
Support
Supportability is vital to the on going maintenance of an application after it has been deployed and is running in
a production environment. However maintenance of a complex application can be quite difficult. It is important
to plan out trace and logging functionalities and exception handling within the application early during
development. This will save considerable time in support. Typically customers are not interested about how
complex the application is. All they’re interested is whether it takes 30mins to fix something or 3 days. Often
applications are frequently updated such as when additional functionality has been introduced or when a new
version of software has been released. Such updates can cause the complex issues similar to those encountered
during the initial integration of the application.
Without an appropriate architecture planning, all of the outlined complexity could easily get in the way of
our agile architecture. Thus preventing all the real benefits of a service-oriented architecture. SOA can help to
significantly reduce complexity at all levels. This is a key aspect of SOA which allows existing infrastructures to
react as quickly as possible to the changing business environments and offer new services to its customers.
In order to achieve SOA the following must be carefully considered.
* Decomposition. SOA decomposes large, complex systems into application frontends and services.
* Appropriate granularity. The granularity of services is well suited to gain a high-level understanding of the
entire system. Unlike other approaches SOAs do not confuse practitioners by presenting too much detail.
* Decoupling from technology. SOAs can be well understood without in-depth knowledge of technology
* Reuse. SOAs result in the high-level reuse of existing components. This streamlines the code base and reduces
complex redundancies.
* Documentation. Due to the service contracts every service is well documented, which adds to the
comprehensibility of the SOA.
76
The Complete Reference To Professional SOA with Visual Studio 2005
IT Cost Savings
SOA in an enterprise project will be able to considerably reduce project costs because it allows for more efficient
implementation and deployment. However in order to achieve reduced project costs initial SOA infrastructure
must already in place. To convert to a SOA infrastructure from a rigid infrastructure could initially be costly. For
those organizations that undergo this process the benefit will be evident in future development compared to those
that have not.
By adopting SOA early, the long-term maintenance of SOA is also reduced. This is due to the simplification
of application. Future changes can be made more easily. Maintenance efforts can be targeted to business
functionality. Side effects can also be reduced and comprehensibility can be increased due to a clear
decomposition of the application landscape within components.
Finally, correct adaptation of SOA guarantees future proof solutions. This is due to the ability for web
services to provide abstraction from the underlying technology. Thus the service itself is not tied to any
shortcomings of technology. SOA also allows the preservation of IT investments because it enables us to
integrate functionality from existing systems in an enterprise instead of replacing them. This support for
reusability is central to so much of better future IT development.
77
The Complete Reference To Professional SOA with Visual Studio 2005
Suppliers
Organizations had always longed for more development resource after all swiftness to act is the key to any
success in business. However to act quickly has always been extremely expensive and the solution produced are
often bug ridden and not always guaranteed to have rewards that were expected. As a result, businesses have
learned to be patient with technology. This meant that they’re no longer competing at the level that they like.
With SOA an entire architecture can be opened up. Organizations have the control on what component and
functionality to make available to its partners and clients. This changed the world of supply/customer
relationship in business. Previously the supplier developed applications for its customer and then in turn sold the
solution to the customer. This was rigid and the intellectual property often belonged to the supplier and therefore
the business restrained from making subtle changes to streamline business processes. This often made both
parties feel unhappy and tied down. The supplier of the system who uses its functionalities is reluctant to make
client-by-client changes. From a business perspective it was just not possible to develop and maintain for each
and every customer. While the customer was not happy with the rigidness of the application and the lack of
flexibility and support is constantly an issue for the business.
Suppliers are beginning to see the benefits of SOA as they’re able to open up their functionalities and leave
the rest to the consumers. This reduced the responsibility and maintenance costs of maintaining client side
applications. Suppliers could simply charge a service fee for each usage or its service. An example is a payment
transaction service, each time a client used the service a fee is charged to the registered client account holder.
This essentially allows consumers to build a provider’s business for them.
In fact the supplier is able to gain additional market and users through its client’s users. Which in turn
requires the supplier’s web services to function. This is an alternative strategy to expand one’s business through
the aid of others.
Opening up functionalities seems simple, and is simple. So what is the catch ? There really is none. It is
exactly the same as before but now there’s just a web service in between the client and the provider.
Consumers
The consumers of the business services are mostly the victims of rigid supplier-consumer relationships.
Consumers are nearly always given what they don’t want and functionalities that they don’t really need for a
costly price. Even after paying such high prices, support is poor.
When the suppliers opened their functionalities as web services. Their clients could programmatically
consume required functions. This gave the consumers unlimited flexibility on how they can use the
functionalities and how they can integrate their existing systems with the these services. Consumers could
quickly streamline their internal systems. This provided them with more value and control to their business.
They no longer have to purchase the pre-packaged bundle that was designed for everyone and catered for every
scenario. All they needed was to integrate the web services that their internal systems required to begin
operation. The integration process is usually straight forward and overall it’s a reduction on cost and thus better
return on investment.
Web services are the key to the platform evolution, because they provide a standard, controlled way for
outside machines to interact with corporate systems. A company can “expose” only what it wants in the form of
Web services: access to a database or product attributes, for example, or to an application such as search. Clients
“consume” these Web services by embedding them in their own applications or Web sites.
For example, instead of having to license and host a geospatial database, a site that publishes restaurant
reviews could embed a tag that calls on a third-party database when a user wants directions to a particular
restaurant. This is just like how suppliers build applications for consumers in the past. Except now the clients are
building the applications they want themselves, and thus expanding the supplier’s business by integrating
supplier functionalities within client applications.
78
The Complete Reference To Professional SOA with Visual Studio 2005
Take eBay. The online auction giant has offered APIs since 1999, as well as Simple Object Access Protocol
and Java integration capabilities to its software development kit. eBay has around 100 public Web services calls
available, while about a quarter of the money exchanged in the online marketplace is via PayPal, which is
effectively a Web service on eBay. This is a good example of an organization using third-party developers to
provide the growth that the organization need.
Organizations will often find that when outsiders build onto the platform, they often do it in surprising ways
that the mother company wouldn’t have considered. For example, when Amazon.com exposed data from its
Alexa Web Information Service (AWIS) program, it kicked off a wave of creativity as it provided aggregated,
close-to-real-time information about Web traffic, including the top sites visited and where visitors to one site go
next.
By offering web services to the public and generating a public following is like employing an army of
developers dedicated to a common course except without the cost. Third-party developers are often able to see
an aspect not seen from the business perspective. This promotes innovations but the focus is still on the
organization as it is still the public service that the third-party application is using. With this strategy in mind an
organization can quickly grow where growth was not possible previously.
79
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 3-2 illustrates that as the number of “helper” software increased the agility of development becomes inhibited.
SOA helps to shift the attention from technological issues to questions of service functionality and service
design. Allowing a more productive development cycle through the use of a range of technologies that was
frustrating and tedious to work together in the past.SOA provides an abstraction from the underlying technology
of different systems. This independence offers several benefits to an organization. Most important is the agility
that is brought to the business, subsequently allowing it to make important business decisions instead of waiting
on IT. This is all achieved through SOA’s ability to support inter-platform connections between some very
different systems.
Independence from technology also increases independence from software vendors. Applying SOA allows a
software system to choose the best of products and to combine them to formulate a well rounded solution that’s
not restricted by one software vendor.
The two most common contemporary application landscapes are characterized by two incompatible
development frameworks J2EE and .NET. This make it particularly difficult to create and maintain cross-
departmental business processes. Due to the tight coupling of business functionality to specific technology, it is
arbitrarily difficult to force different parts of the architecture to work together. SOA avoids these obstacles by
decoupling the technologies of the provider and consumer of specific business functionality. SOAs do not
interfere with the development framework itself. But rather it allows more efficiency and agility within the
application. It also promotes future reuse which allows for a reduction in development resource in future
projects.
Independence from underlying technology supports decoupling of technology lifecycles from the lifecycles
of business services. Therefore, the introduction of a new technology within an enterprise does not require a
makeover of the business processes and services. Similarly, new business service can be introduced without the
need to wait for new, innovative technology to become mature, stable and affordable.
Measuring a SOA
Determining ROI for service-oriented architecture can provide valuable information. It also justifies the
reasoning behind the push for SOA. However, putting together a realistic ROI is not a simple task and often
takes many revisions as new ROI information becomes available. Determining a ROI ahead of a project will
often shape an enterprise’s migration strategy. Whilst by examining the migration strategy also contributes to the
outcome of a ROI. Nevertheless realistically there is no real way of knowing the ROI until a project is actually
deployed. Even then measuring the real ROI will take months if not years.
Often determining ROI takes considerable research that tends to be performed for migration strategies and is
more focused on technology and implementation, rather than high-level organizational benefits. An intelligent
strategy for integrating a service-oriented architecture can lead to much greater cost benefits than an ROI can
originally predict. Even though if an ROI is used to justify the migration path of a project. The ROI can be
refined further on as new information is obtained.
The initial SOA migration phase is the most expensive phase of an enterprise-wide initiative however, the
scope of our ROI will likely always go beyond the migration phase. Further revisions to an ROI will improve the
accuracy of its predictions as they relate to subsequent phases in a long-term program. The benefits for SOA tend
to be tangible, because the interoperability enabled by the service integration layer results in immediately
recognizable savings.
To be able to measure a SOA a measurement plan must be drawn up from the start. The best method of
measuring of a SOA is to start with a small project and to expand and iterate as new information becomes
available. Make sure that the service is something that is simple and measurable such as a service which provides
access to a database. Because even small things have ROI value attached to them. The service should be
monitored and the results measured.
80
The Complete Reference To Professional SOA with Visual Studio 2005
To measure the success of a SOA it is important to draw up a projected ROI ahead of development. The real
ROI should then be tracked and monitored. By comparing the two values we can assess whether SOA
implemented is successful. Of course depending on the industry that the system is designed for the ROI will
vary, as not all industries have the same benefit from SOA. Typically Banking, Insurance, Telecommunication,
Retail and Government have the greatest ROI partly because they service such a large range of users. If we’re
not in these industry types we will still benefit from savings in asset re-use and business labor savings.
In measuring SOA we look into four areas where ROI can be examined.
1. The simplest and most straightforward is short-term, tactical ROI, which is gained from the immediate
reduction in the cost of integration. This should be able to save us money the day after we implement SOA
from an immediate savings on integration. We will be able to get rid of middleware, reduce the time in
transformational mapping and get other similar benefits. It’s easily quantifiable, because we can identify the
business processes and systems that were replaced.
2. The second ROI can be obtained through application reuse. This is a little more difficult to get than integration
costs. To achieve it, a company has to identify areas of commonality between applications, and build services
for them. That way, the total amount of design, programming and development time can be reduced, because
the service can be designed only once, instead of multiple times.
3. The third area is in business agility, and this ROI benefit can be gained in the medium to long term. This allows
an organization to make rapid changes to its IT infrastructure when required. These are necessary in today’s
environment where alliances with other organizations are quickly forged and then broken. Traditionally IT
systems have always been a limiting factor in slowing down business process. So this ROI is particularly
valuable and allows for a faster time to market.
4. The fourth area of ROI is provided in a way of reputation. By having a faster time to market value to changes
in business process an organization can slowly build up reputation in the form of reliability. Although a
company will not gain anything from the ROI however it is possible for this ROI to generate potential income.
All these areas should be iteratively analyzed through our ROI evaluation.
81
The Complete Reference To Professional SOA with Visual Studio 2005
Organizational Roadmap
Identifying Stakeholders and Conflicts
Before implementing SOA at the enterprise level, we need to examine the different stakeholders within the
organization and avoid potential conflicts of interest to ensure a successful implementation of the new
implementation.
Even though it is true that every organization is different, and as such has different stake holders. Generally
an organization contains two types of stakeholders the decision makers who make financial and high-level
strategic decisions and the end users who are often operating the systems on day to day basis. It is essential to
have open and transparent meetings where all aspects of implementation and business process can be examined.
This will provide everyone within the organization with an opportunity to address any concern they might have.
An area of impact is the CEO and the board of directors that are responsible for high-level strategic
decisions, which often will have a direct impact on IT systems and system implementations. While another area
to be mindful is the business functional requirements, they often present the IT department with conflicting
requirements because their interests sometimes may conflict.
It is therefore important to identify the stakeholders and potential conflicts early on.
Figure 3-4 represents the equal stake holders within an SOA.
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.
82
The Complete Reference To Professional SOA with Visual Studio 2005
Business and IT
After executives have completed their decision making process, it is up to the business units and the related IT
projects and departments to implement systems that meet business requirements. The daily interaction between
business and IT people has traditionally been difficult. Business people often have a difficult time
comprehending why technical issues are so complicated, while IT people often struggle with the complexity of
having to understand detailed business procedures. Typically, business requirements require a large number of
specialists who have slightly different understandings of the environment and often differing agendas and
perspectives. While external vendors with their own consultants and products add to this complexity, all of this
increased complexity of matching business requirement to their corresponding technology.
Internal Politics
Internal Politics play a large role in the decision making process. Though, typically IT people coming from a
development background are not always aware of the intricacies involved. The CIO and technology architecture
boards often have different interests in the path of individual projects. These conflicts can have various reasons
sometimes disagreement may occur from difference in position of a particular employee. But it is an area which
one should be aware of. An architect for example will introduce standards that allow for technology reuse. While
a Project manager, on the other hand, often have a bigger interest in getting their projects out the door and costs
low, instead of investing the time to examine reusability. In these situations, it is often not a matter of reasonable
decision making but a question of who has the power to enforce a particular course of action.
Similarly, project managers and operations managers can have conflicting interests. How fast the project
delivers certain business functionality often measures the success of a project. Consequently, speed is the major
concern of a project manager. In order to ensure the successful delivery of the project the project manager must
ensure all aspects of the application had been thoroughly tested. These may include System Management
Integration, exception handling, CPU and Memory consumption, Scalability and over all application
performance testing. However these tests do not have any bearings to the operations manager and take up
development time and money.
It is necessary to consult stakeholders and identify potential conflicts of interest before a project begins. It is
important to hold meetings where all key stakeholders can attend and discuss issues that concern them. In this
manner solutions or alternative resolutions can be drawn up in an open manner.
Organization Vision
Once all the stakeholders have been consulted and potential conflicts identified and resolved, the next step is to
gather the key stakeholders once again to agree on the vision of the new enterprise SOA and the role the SOA
will play within the organization. The meeting can begin by formalizing a vision statement which states the
ultimate goal and how it can be achieved. People from both the business and technology side should be involved
in formulating this vision. It is in reality that the actual technology that drives business goals and the new vision.
However it is vital for the people from business section to validate the concepts of the vision from the business
point of view.
Once the vision statement is agreed upon, the next step is to define a plan that outlines how the goals
defined in the vision can be achieved. This does not require a detailed project plan but it is more about
motivating the organization towards a common goal. The development of the vision will have future impact and
bearing on all future development and business decision making process, which will eventually lead to budget
allocations, which is so important to the maintenance and the growth of the existing infrastructure.
It is important to keep in mind that once the vision statement had been defined we should consistently check
the process of existing development and ensure that the SOA is steered towards the new vision milestones. The
83
The Complete Reference To Professional SOA with Visual Studio 2005
introduction of an SOA is not a one-off project but it is a journey and requires constant efforts to ensure that
future development projects will stand by the principles of the SOA.
Budget Consideration
With the initial introduction of SOA the starting projects must be chosen with great care. As these initial projects
is what the business often judges the success of SOA on. Even though fundamentally the success of SOA should
be judged later on as it promotes reuse and thus reduces costs with later projects. Thus it is important to select
simple initial projects that can be developed as pilots. This will slowly ease the fear of everyone else who is
afraid of change. It is important that these initial projects are equipped with sufficient time and budget to meet
any unexpected issues that may arise.
Over all the initial beginning of SOA is always more expensive and has more overhead. This is because the
reuse and agility of the infrastructure still does not exist; as a result reuse simply does not occur. Thus instead of
merely focusing on the immediate challenges, potential future applications must be taken into account to ensure
maximum reusability and cost reduction in future.
After implementing SOA, Verizon Communications claims it averages about 2.5 million to three million
Web services transactions a day. The company claims that it was through implementing its internal application
IT Workbench, which was constructed on SOA principles and is built on XML and SOAP messaging. The
system became operational in 2004 and Verizon says it was able to slash its IT budget by 50% by eliminating
redundant systems inherited from the merger of Bell Atlantic and GTE. By adopting SOA, the company claims
that it also helped integrate the operations of some 7,000 developers. Verizon’s SOA covers about 250 services,
and the company says it plans to eventually support 33 million Web services transactions per year.
84
The Complete Reference To Professional SOA with Visual Studio 2005
MSF provides a flexible and scalable framework that can be adapted to meet the needs of any organizations
with projects that varied in size and complexity. It also focuses on the planning, building and deploying of
business driven technology solutions. MSF can be applied to improve success rates for the following types of
projects:
* Software development projects, including mobile, Web and e-commerce applications, Web services,
mainframe, and n-tier.
* Infrastructure deployment projects, including desktop deployments, operating system upgrades, enterprise
messaging deployments, and configuration and operations management systems deployment
* Packaged application integration projects, including personal productivity suites, enterprise resource planning
(ERP), and enterprise project management solutions.
* Any complex combination of the above.
* Lack of training or documentation after a complex system has been deployed resulting in misunderstanding
over system functions.
Generally organizations that have development processes in place avoid the need to overcome these issues
and thus derive better results for their business through higher product and service quality. This also improves
customer satisfaction and business reputation, which always leads to wining more projects through word of
mouth. These factors translate into a positive influence on bottom line and improvements in the organization’s
strategic effectiveness. MSF was designed and built to provide organizations with a clear roadmap towards
successful project planning and development.
MSF Tracks
The MSF Tracks describe a generalized sequence of activities for building and deploying enterprise solutions.
This process is flexible and can accommodate the design and development of a broad range of enterprise
projects. The MSF Tracks is a track-based, milestone-driven, and iterative model that can be applied to
developing and deploying enterprise solutions for SOA. There are two sets of tracks following MSF 4.0 for
Agile Software Development (MSF Agile), and MSF 4.0 for CMMI Process Improvement (MSF CMMI).
85
The Complete Reference To Professional SOA with Visual Studio 2005
MSF CMMI
The MSF CMMI represented in Figure 3-5 consists of seven distinct tracks:
* Governance
* Envision
* Planning
* Building
* Stabilizing
* Deploying
* Operational Management
MSF Agile
The MSF CMMI represented in Figure 3-6 consists of six distinct tracks:
86
The Complete Reference To Professional SOA with Visual Studio 2005
* Envision
* Planning
* Building
* Stabilizing
* Deploying
* Continuous
Envisioning Track
The MSF process begins with the envisioning track. It is in this track where a broad description of the goals and
constraints of the project is defined. Here we identify the team and what the team must accomplish for the
organization. The purpose of the envisioning track is to build a shared vision of the project among all the key
stakeholders of the project.
* Setting up the team. Creation of a project team that represents all roles within the SOA. When setting up a
team, it is important to consider the skills, experience, and performance level of the team members. In addition,
there are practical considerations such as availability of resources and project budget.
* Defining the project structure. Identifying the administrative structure for the project team and the standards for
managing the project.
* Defining the business goals. Analysis of the business problem and opportunities in order to identify the
objectives for the solution.
Planning Track
Following Envision is the planning track, during this track the team determines what to develop and plans how to
create the solution. The team prepares the functional specification, creates a design of the solution, and prepares
work plans, cost estimates, and schedules for the various deliverables.
It is during this track analysis of requirements is performed. These requirements can be: Business
requirements
* User requirements
* Operational requirements
* System requirements.
Obtaining requirements are important because they in turn are used to design the solution and its features and to
validate the correctness of the design.
During the planning track, the team performs multiple tasks. The milestones of the planning track are:
* Technology validation. During technology validation, the team evaluates the products and technologies that
will be used to create or deploy the solution. The team also audits the customer’s current production
environment.
* Functional Specification. The functional specification is completed and submitted for review to the customers
and stakeholders. Remember that the design document is different from the functional specification. The design
document is written for the project team and describes the internal workings of the solution.
87
The Complete Reference To Professional SOA with Visual Studio 2005
* Mast Plan & Schedule. The mast plan is a combination of plans of various roles on the team. The master
project schedule includes all detailed milestone project schedules and the solution release date.
Developing Track
During the developing track, the project team creates the solution. This process includes creating the code that
implements the solution and documenting the code. In addition to developing code, the team also develops the
infrastructure for the SOA solution.
The team performs the following tasks during the developing track:
* Starting the development cycle. Verification that all tasks identified during the envisioning and planning track
have been completed so that the team can begin developing the solution.
* Creating a prototype application. Verification of the concepts of the solution design in an environment that
resembles the environment to which the solution will be eventually deployed.
* Building the solution. Developing the core functionalities, within the requirement for the project.
Stabilizing Track
During this track, the solution progresses from the state of all features being complete as defined in the
functional specification for this version to the state of meeting the defined quality level. On the completion of
this track the solution must be ready for deployment to the business. During this track the team will need to
perform integration, load testing on the solution. The teams also need to address any issues that may arise to
prepare for the project release.
During the stabilizing track the following milestones are reached:
* Bug Convergence. A milestone of the stabilizing track that marks the point at which the team makes
measurable progress against the active issue and bug count.
* Release. A series of milestones of the stabilizing track that reflects the incremental improvements in the
reduction of the issue and bugs.
* Zero-bug release. A goal of stabilizing track that marks the point at which the issue and bug count has met the
zero-defect metric for this particular point in time in the project.
Deploying Track
The team deploys the solution to the organization. The team transfers the skills and support to the relevant
department members, and obtains final customer approval of the project. After deployment, the team conducts a
project review and a customer satisfaction survey.
During the Deployment Track the following milestones are reached:
* Major components are deployed. Successful deployment of sites depends on these components.
* Site deployment complete. At the completion of this milestone, all intended users must be able to access the
solution. Leading developers for each component within the SOA must confirm that their sites are operating.
* Deployment stable. At this milestone, the customer and team agree that the sites are operating as required.
Issues may arise and will be tracked and resolved by relevant parties.
88
The Complete Reference To Professional SOA with Visual Studio 2005
Governance
Is a continuous track through out the lifecycle of MSF CMMI usually performed by people in the role of
Auditor. System governance and supports covers subprojects focusing on the transition of system wide structures
to govern and support the delivery of direct services. There are governance structures being developed to
facilitate inter-Authority communication and coordination.
Governance requires the continuous process of:
* Identify Inconsistencies
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:
Continuous Track
The continuous track is used by the MSF Agile track model. It is performed by people of the roles of Business
Analyst and Project Manager through out the life cycle of the project.
* Define Personas
* Refine Personas
* Review Objective
* Assess Progress
* Triage Bugs
* Identify Risk
Project Teams
MSF provides the MSF Team Model for organizing project teams. The MSF Team Model emphasizes the
importance of clear roles, responsibilities, and goals of individual members to the success of the project. This
model also increases the accountability of each team member. The flexibility of the MSF Team Model helps us
to adapt it to the scope of the project, the size of the team, and the skills of the team members. This forms the
basis of creating effective, resilient, and successful project teams.
89
The Complete Reference To Professional SOA with Visual Studio 2005
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:
* Develop Documentation
* Establish Project Process
* Manage Issues
* Plan an Iteration
* Plan Project
* Manage Risk
90
The Complete Reference To Professional SOA with Visual Studio 2005
Architecture
The architect role is to advocate for the architecture constituency in the MSF Team Model. The architect is
responsible for maintaining the architectural integrity of the product and ensuring the success of the project by
designing the foundations upon which all the value can be realized. This includes defining both the
organizational structure of the application and the physical structure of its deployment. In these endeavors, the
architect’s goal is to reduce complexity, decrease coupling and regression effects, and increase the cohesiveness
of components by partitioning the system into parts which can be built and tested independently. The resulting
architecture is extremely important because it not only dictates how the system will be built going forward but
also establishes whether the application will exhibit the many traits that are essential for a successful project.
These include its usability, whether it is reliable and maintainable, whether it meets performance and security
standards, and whether it can be evolved easily in the face of changing requirements.
The architect’s responsibilities are as follows:
Analysis
* Establish Environments
Development
The developer advocates for the development constituency in the MSF Team Model. The developer is
responsible for the bulk of the work of building the product. Other development roles such as the lead developer
and development manager have additional communication and project management responsibilities. The
developer should suffer a minimum of communication overhead allowing for a maximum effort on construction
of code. In addition, during the early stages of a project, developers may be expected to help specify product
requirements not included in the customer requirements and to work on analysis and architecture activities as
part of a multi-disciplinary team. A lead developer's role is to lead and to communicate on behalf of other
developers. A lead developer advocates for the development constituency in the MSF Team Model. A lead
developer lends experience and skill and shows leadership by coaching fellow developers. Lead developers carry
responsibility for code reviews, design, and unit testing coverage. Lead developers act as a conduit to the rest of
the project for the developers. As an aid to productivity, lead developers funnel communications between the
wider project team and external organizations, and shield developers from noise and random interference in their
daily schedules. Because of this, lead developers can seldom dedicate themselves to development tasks.
Typically, they spend about 50% of their time on communication and split the remainder between leading and
coaching the developers on their team, and actually writing code for development tasks.
The developer’s responsibilities are as follows:
* Analysis
* Create Solution Architecture
91
The Complete Reference To Professional SOA with Visual Studio 2005
* Develop Documentation
* Establish Environments
* Establish Project Process
* Fix a Bug
* Implement a Development Task
* Release a Product
Test
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:
92
The Complete Reference To Professional SOA with Visual Studio 2005
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
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:
1. Risk identification, individuals are encouraged to identify risks so that other team members are aware of any
potential problems.
2. Risk analysis, in this step risks identified during risk identification are investigated these risks are assigned a
priority by the team.
93
The Complete Reference To Professional SOA with Visual Studio 2005
3. Risk planning, uses the information obtained from risk analysis to formulate strategies, plans, and actions.
4. Risk tracking, monitors the status of specific risks and document the progress of risk in their respective
development plans.
5. Risk control occurs when we are required to execute relevant risk management action plans, detailed status
report of the risk and its progress is then required.
6. The last step in the MSF risk management is, risk learning, the learning process will give teams an opportunity
to reflect upon the risk so that the knowledge can be formalized into documentation as a reusable form for
future use within the team and by the enterprise.
94
The Complete Reference To Professional SOA with Visual Studio 2005
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.
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 () {
95
The Complete Reference To Professional SOA with Visual Studio 2005
//InitializeComponent();
}
[WebMethod]
public string HelloWorld() {
return "Hello World";
}
}
If we had selected Visual Basic then the following code would be generated.
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.
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 () {
96
The Complete Reference To Professional SOA with Visual Studio 2005
[WebMethod]
public string HelloWorld(string param1) {
return "Hello " + param1;
}
}
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.
97
The Complete Reference To Professional SOA with Visual Studio 2005
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.
98
The Complete Reference To Professional SOA with Visual Studio 2005
If we enter our name in the text box and click the Invoke button, the Web service will be called, passing
whatever we typed as the parameter to the HelloWorld method. The results may be seen in Figure 3-12 if we
enter the name Kim.
Another thing that Visual Studio 2005 does for us is that it generates the WSDL document that describes our
Web services. If we look back to Figure 3-10, we will see a hyperlink to the Service Description at the top of the
page. Clicking this will navigate us to the page containing the WSDL, which of course will also indicate to us
the URL that we can use to consume the WSDL. We can see an example of this WSDL in Figure 3-13.
Figure 3-13. Shows the WSDL document generated by Visual Studio for the Hello World web method
We can see that the URL for the WSDL is the URL for the Web service with the ?WSDL appended to it. For
example, Service.asmx?wsdl.
99
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 3-14. New project template for windows application. (please note that Visual Studio 2005 comes with a range of
editions catering to different roles in development. The screen shot that you see may differ slightly depending on the edition
that you use.)
Once the project has generated the windows form for us. We can drag and drop a button and label onto the
form (see Figure 3-15).
100
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 3-15. Windows form designer allows drag and drop to add controls.
Now we can establish contact with the web service by adding a reference to the web service we created earlier.
101
The Complete Reference To Professional SOA with Visual Studio 2005
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.
Now when that we had entered the above code into the code behind we can compile and run the code. We will see the result of the
execution in Figure 3-17.
102
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 3-18. Windows application result from invoking the Web service.
From the example above we can easily see why developing with .NET is so simple. Visual Studio helps us
take care of all the subtleties so that we don’t need to touch them. The job of a developer is simplified. .NET
Framework takes care of the web service requests as well as response by marshalling of SOAP information to
and from the wire. Visual Studio also generates a Proxy class from the information obtained from the WSDL of
the web service. This allows the developer to access development information from the Web service. Developers
can use the proxy class created by Visual Studio to map to the Web service that they’re currently accessing. To
aid the developer’s development effort all functions accessible via the Web service can be accessed through
Visual Studio’s intellisense.
Summary
Through this chapter we have focused on various areas in the domain of business adaptations of SOA. These are:
Role of SOA within the organization
Opening our private infrastructure
Lastly we looked at the ease of creating Web service using .NET and Visual Studio 2005.
103
The Complete Reference To Professional SOA with Visual Studio 2005
.NET Framework
The .NET Framework was developed to work with the Windows operating system. It is an integral part of
Windows components and will play a further role with the release of the Vista operating system. The framework
supports building and running various types of Windows applications such as console applications, Winform
applications as well as support for Web based applications such as Webforms and also support for the
104
The Complete Reference To Professional SOA with Visual Studio 2005
development and running of the next generation of XML Web service developed for .NET. The .NET
Framework aims to:
* To ensure a consistent object-oriented programming environment.
* To ensure a consistent development experience across different type of applications, such as Windows-based
applications and Web-based applications.
* To provide a consistent framework where developer are free to choose their favorite programming language.
The heart of .NET Framework consists of two main components: the Common Language Runtime and the
.NET Framework class libraries. The Common Language Runtime is fundamental principle of runtime. It works
as the agent that manages the execution of code while also governs the type safety and other code securities.
Code that is managed by the .NET Framework runtime is known as managed code while code running outside of
the runtime management is known as unmanaged code. The other main component of the .NET Framework is
the class library. The class library is an object oriented collection of reusable types that we can use to develop
different types of .NET applications. These .NET applications range from traditional command-line applications
to graphical user interface (GUI) applications to Web based applications such as ASP.NET Web form and XML
Web service.
The .NET Runtime was designed with performance in mind. Managed code is never interpreted. A feature
called just-in-time(JIT) compiling enables all managed code to run in native machine language of the system on
which it is executing. The memory manager also helps to remove possible memory fragments to increase
memory locality-of-reference to further improve performance.
The .NET Framework provides several runtime hosts which allow hosting of managed and unmanaged
components. These hosts can be Microsoft SQL Server and Internet Information Services (IIS). The host loads
the common language runtime into their process and handle the managed code execution. By doing so the
runtime can access both managed and unmanaged features of the components. This infrastructure allows
developers to develop applications with managed code whilst still enjoying the superior performance of the
.NET Runtime.
105
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 4-1 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.
106
The Complete Reference To Professional SOA with Visual Studio 2005
advantage of the full features of the .NET Framework. This greatly eases the migration process for developing
new and existing applications.
The runtime also maintains interoperability with legacy applications through the support for the use of
unmanaged code components such as COM and DLLs. The runtime is also optimized for enhanced performance.
Unlike script based languages the managed code is never interpreted by using features like Just-In-Time (JIT) all
managed code are compiled into native machine language for that particular system on which it is execution.
This greatly improves the performance and execution of applications. While memory management reduces
fragmentation to increase the locality of reference to further increase performance.
Lastly the .NET runtime is now integrated to other high performance applications such as Microsoft® SQL
Server™ and Internet Information Services (IIS). We can now develop and embed SQL stored procedures, SQL
data types, SQL Triggers in .NET code. This is very exciting.
Managed Development
In .NET managed applications are implemented through the .NET runtime hosts. In development such as
applications for ASP.NET the unmanaged host in our case the Internet Information Services (IIS) hosts the
common language runtime, which allows us to manage code. This is a proven model which give us all the
capabilities of the common language runtime and class library. This also allows us to gain the performance and
scalability benefit of utilizing the host server.
Figure 4-2 shows a basic network schema with managed code running in different server environments.
Servers such as IIS and SQL Server can perform standard operations while our application logic executes
through the managed code.
Web Forms together with XML Web services both use ASP.NET and IIS to host its deployed applications.
ASP.NET is more than just a managed runtime host. ASP.NET is a complete architecture from which developers
can build web based applications and Internet based distributed applications such as XML Web services.
XML Web services is a type of distributed server side application. In some ways it is similar to a web sites
in terms of requiring to be hosted on IIS and developing using the same managed environment. However it
differs in that XML web service do not require user interfaces they are essentially much like COM components
or simply a DLL providing functionalities to all that required its services. Despite the requirement to be hosted
on IIS XML Web services do not target browsers such as Internet Explorer and Netscape. Instead it offers its
service to the public through a description document called Web Server Description Language (WSDL) which
details all the functionalities provided by the web service. XML Web service technology is rapidly evolving
because of its distributed nature and its separation between interface and implementation it is fast becoming the
choice of many who implement SOA.
107
The Complete Reference To Professional SOA with Visual Studio 2005
The .NET Framework supports the development of XML Web services with a collection of classes and
tools. The .NET Framework has internal support for Simple Object Access Protocol (SOAP) a remote procedure
protocol and Extensible Markup Language (XML) the framework also helps to generate the WSDL document
which describes the Web service. All of this greatly reduces the workload of a developer. The .NET Framework
with internal support using these standards to help promote interoperability with applications with even non-
Microsoft solutions.
The .NET Framework has built-in WSDL tool so it can parse the WSDL document of another Web service
and produce C# or Visual Basic source code. This is called a Web service proxy. The proxy can then be used to
invoke the functions on the Web service.
If we develop and publish our own XML Web service, the .NET Framework provides a set of classes that
conform to all the underlying communication standards, such as SOAP, WSDL, and XML. Using those classes
enables us to focus on the logic of our service, without concerning ourselves with the communications
infrastructure required by distributed software development.
The best thing is unlike other script languages the XML Web service will be able to utilize the managed
environment the code will be compiled to native machine language for performance.
108
The Complete Reference To Professional SOA with Visual Studio 2005
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:
109
The Complete Reference To Professional SOA with Visual Studio 2005
developers will get the static code analyzer (much like FxCop), unit testing (like NUnit), code coverage (like
NCover), and code profiler. Some of the features share with the Visual Studio 2005 Team Edition for Software
Testers. Figure 4-3. It is expected that as a developer some basic testing would be done before the component is
passed onto the software testers.
110
The Complete Reference To Professional SOA with Visual Studio 2005
Similar to the professional editions of the previous versions of Visual Studio, this is the edition for serious
development in Visual Studio. This edition is for consultants, solo professionals, and those who work in small
teams for which team System may be more than they need. The professional edition also differs from the
standard edition in that it has all the features required to build distributed applications.
* 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.
111
The Complete Reference To Professional SOA with Visual Studio 2005
TIP: We don’t use Visual Studio’s File -> New Project command. That is because web applications are regarded as separate to traditional
windows based applications such as WinForm and Console application projects.
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:
We will be working with Web based applications which include both ASP.NET Web Site and ASP.NET Web
Service. So determining what we type of project we will be creating first is essential to selecting the right
templates. The Web Site and Web Service applications are actually compiled and executed in the same way. We
can also add Web pages to a Web service application and vice versa. The only difference is that by selecting a
template we are asking Visual Studio to create specific pre-defined files for us. In a Web service application we
will start with a sample service whilst in Web Site application we start with a sample Web page.
Location: The location section determines where we will be storing the working files. Previously in Visual
Studio 2003 we could only specify HTTP locations this meant that we could only save files to a Web service
with IIS. However in Visual Studio 2005, we can take advantage of a number of modes. We can now save our
working files to the File System or store the files to a network address. We can also save our project to a FTP or
112
The Complete Reference To Professional SOA with Visual Studio 2005
a HTTP location. The best part is that Visual Studio 2005 now comes with an integrated Web server called
ASP.NET Development Server. This server is launched when our Web based projects are stored on the file
system. However if we want to work on a live remote website we should use the Remote Site option, though care
should be taken when working on a production server as changes can be irreversible.
Rather than typing the location details in we can alternatively use the browse button which will show a
Choose Location dialog window. There are four types of locations that we can select here File System, Local IIS,
FTP Site.
Language: We have the option of selecting Visual Basic, Visual C# and Visual J# (In the following example we
will be using Visual C#)
File System: The file system is preferred by most developers because its easily accessible we can save to
any particular location we like figure 4-5. In Visual Studio 2005 when execution occurs an Integrated Web server
called ASP.NET Development Server will be launched. This environment is essentially what hosts the Web
application during execution. If we want to create a new directory for our application, just click the Create New
Folder icon above the top right corner of the directory tree. We can also specify a new directory to create by
adding a new directory name to the end of our path.
113
The Complete Reference To Professional SOA with Visual Studio 2005
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.
FTP Site : By selecting FTP Site we are essentially connecting to a FTP server from where our working files
will be stored figure 4-7. To do this we need to specify the server details, credential information as well as the
directory we want to store the files in.
114
The Complete Reference To Professional SOA with Visual Studio 2005
Remote Web Server: Selecting the Remote Site means that we will be storing the files on a remote IIS
server with FrontPage Extension installed figure 4-8. We will be prompted for username and password
information upon successful connection to the site.
Language: The language option allows us to select between Visual Basic, Visual C# and Visual J#. The
language that we choose will become the default language for the project. We can explicitly add Visual Basic
web pages to a J# website, and vice versa. And if the project is in a solution we can also add other projects that is
using different language to our project.
Once we have completed our selection simply click Open Visual Studio returns us to the Create Web Site
dialog box. Click OK, and Visual Studio will create the new web service application. The new Web Service
starts with the file called Service.asmx.
115
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 4-9 A newly generated Web Service from the ASP.NET Web Service template.
116
The Complete Reference To Professional SOA with Visual Studio 2005
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:
This report shows the steps taken to convert your Web application from ASP.NET 1.1 to ASP.NET 2.0.
There may be some unresolved conversion issues you will need to manually fix.
For more information, please refer to http://go.microsoft.com/fwlink/?LinkId=46995 or search for the help topic "Converting from Visual
Studio .NET 2002 or 2003".
Conversion Started on project file WebService1.csproj at March 14 2006, 13:17:48.
=========================ERRORS===================
=========================WARNINGS=================
Warning: This web project was converted as a file-based web application. If your site contained any IIS meta-information, e.g. sub-folders
marked as virtual directories, it is recommended that you close this web site and re-open it using the Open Web Site command and
selecting the Local IIS tab.
=========================COMMENTS=================
Web.Config: Added 'xhtmlConformance' attribute.
Removed attribute Codebehind from file Global.asax.
Added folder App_Code.
Moved file Global.asax.cs to the App_Code\ directory.
Moved file Service1.asmx.cs to the App_Code\ directory.
Moved file AssemblyInfo.cs to the App_Code\ directory.
Changed HTML validation schema for all projects to 'Internet Explorer 6.0'.
117
The Complete Reference To Professional SOA with Visual Studio 2005
118
The Complete Reference To Professional SOA with Visual Studio 2005
Windows Description
Solution Explorer Lists all of the files that are used in the project directory.
Toolbox Shows built-in controls and any third-party controls or custom controls that we have
built ourselves and added to the Toolbox. These controls can be used to build user
interface quickly or to implement certain actions such as retrieving data from a
database. To use these control simply drag and drop or double click. Controls can be
written in any language and used in any language.
Server Explorer Server Explorer provide details on Servers that are accessible these could include
database connections to SQL Server or to Crystal Reports Services, Event Logs,
Message Queues, Managed Classes, other Services on the System and Performance
Counters. From the Server Explorer we can have direct connection to the SQL
Database allowing to perform live queries and test commands.
Properties Allows us to configure the currently selected element, whether it’s a file in the
Solution Explorer or a control on the design surface of a web form. To access the
properties window we can right click on any object on the design surface and then
select properties.
119
The Complete Reference To Professional SOA with Visual Studio 2005
Error List During development Visual Studio helps us to keep track of potential issues that may
arise. This occurs while we develop or after we have built an application. These issues
are reported in the Error List window.
Task List Task List can list comments that are predefined through aliases through out the code.
For example if we wanted to leave a comment about a section of code that we’re still
yet to implement we can use the //TODO: <comment> syntax to leave a message.
This message will then be populated under Task List.
Document The document window or otherwise known as the source code window allow us to
modify the actual code behind a web based application. The document window can
also support file types, such as static HTML and XML files.
Class View The Class View window organizes a code in a class into a logical tree with methods,
properties and events represented in different nodes.
Solution Explorer
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.
File Description
Ends with .asmx All files represented with .asmx are used as ASP.NET Web Services. When a
request is received to a .asmx file the request is passed to the .NET Runtime where
it is handled. Depending on the request for example ?WSDL a request for a WSDL
document ?DISCO for discovery files a response is generated. A direct request to
the .asmx from a browser could result in the generation of a web based test page
which we can use to invoke the Web service.
120
The Complete Reference To Professional SOA with Visual Studio 2005
web.config This is the XML-based configuration file used for our ASP.NET application. It
includes settings for customizing security, state management, memory
management, and much more. Visual Studio adds a web.config file when we need
it. (For example, it adds a web.config file that supports debugging if we attempt to
run our web application.) When we first create a website, we don’t have a
web.config file. We can nest one web.config in each of the directory the web.config
within the directory will overwrite settings of the higher level web.config.
Generally only one web.config is maintained for a project for ease maintenance.
global.asax The global.asax file is used to define global events that occur in an application. This
could be when an error from a specific web application occurs in this case a custom
error handler will then be invoked to process the error.
Ends with .vb These are files that contain Visual Basic 2005 code classes.
Ends with .cs These are files that contain C# code classes.
Within a project we can include other resources that are not ASP.NET file types. These can be XML, XSLT
and XSD file types that are used by our Web service application. Visual Studio can also distinguish between
different file types there are associated tools that help us to modify specific file types. We can view these tools
by simply right click on the specific files. For example right mouse click on a XML file will give us the option of
viewing the file in a browser.
The solution explorer is incredibly handy in development it allows us to add predefined file types into the
project figure 4-14 below. To add a new item to a project simply right click on the solution explorer and select
“Add New Item”. We can add different types of files these range from HTML Page to DataSet to Class files to
XML Schemas.
121
The Complete Reference To Professional SOA with Visual Studio 2005
To add an existing item simply right click and select “Add Existing Item” from which we can browse for a
particular file that we want to add to the project. We also have the ability to drag and drop files in and out of the
solution explorer.
One of the features of Solution Explorer is that it allows us to exclude certain items from the project. This
means that even though the specific item exist in the project it is not compiled and evaluated. This is handy when
we’re working on a piece of code that we know will cause errors. We can simply exclude that specific CS or VB
file from the project temporally to compile the project and see if the rest of the code is working.
Visual Studio also helps us to keep track of files modified. If a file is changed outside of Visual Studio,
Visual Studio will prompt us to either refresh or keep our changes. This is important when we need to modify a
particular file in the solution outside of Visual Studio using possibly a third-party tool.
Document Window
The document window is what allows us to modify changes to the design of an application. Not all applications
have a Graphical User Interface (GUI) for example windows service, console applications and XML Web
service. However each file type has a default editor assigned to it for example an ASPX file would open the
Visual Studio HTML editor which can be used to modify HTML code and as well as view the visual
representation of the HTML. We can view or change the default editor by selecting the file in solution explorer
and then right click on the file to bring up the context menu. For example selecting a Web service .asmx file and
then selecting the “Open With” option will bring up an Open With dialog window figure 4-15 below.
The default editor used by that file type will be labeled with a (Default) after the editor name. Also
depending on the applications that we have installed we may also see additional editors appearing in the Open
With dialog window.
Toolbox
The Toolbox window works in conjunction with the designer window. The toolbox stores a number of controls.
These controls are either internal to the .NET Framework or they can be custom controls that we have developed
and included onto the toolbox. Simply by selecting the tool and drag and drop onto the design surface will create
the tool on the designer surface. The content of the Toolbox depends on the context of the current designer
window that we are working in as well as the current project type.
122
The Complete Reference To Professional SOA with Visual Studio 2005
In the toolbox we can add/remove tools as well as add tabs and remove tabs. We can also drag and drop
tools from one tag group to another.
Error List
The Error List manages the error and the warning information that’s generated by Visual Studio during
development. Each entry in the Error List contains a description column, a file column to show which file the
error is located in, a line column to shown which line the error is on, a code column is also shown to show the
location of the error, lastly a project column is also shown incase we have more than one project in the solution.
We can select whether we want to see each of the column by right click on the Error List window Figure 4-16
below.
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.
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.
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
123
The Complete Reference To Professional SOA with Visual Studio 2005
{
public () {
[WebMethod]
public string HelloWorld() {
return "Hello World
}
Task List
There are two lists of tasks that exists these are User Tasks and Comments. User tasks are entries that we have
added specifically to the list. These are things that we want to do but have not quite started. To create a User
Task simply click the icon next to the drop down list in the Task List window. There are three things we can
assign to a User Task item we can specify the priority of the item, add a description to the item, and select to
indicate whether the item has been complete Figure 4-19.
124
The Complete Reference To Professional SOA with Visual Studio 2005
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.
125
The Complete Reference To Professional SOA with Visual Studio 2005
By default Visual Studio comes with several aliases for Task List comments. There is Hack, TODO,
UNDONE and UnresolvedmergeConflict. However we can always add more. Simply enter a name under the
Tokens section and select Add button to add the token.
Server Explorer
The Server Explorer provides an integrated means for us to access different resources all from the comfort of
Visual Studio. It allows us to access databases, establish a connection to services such as Crystal reports
Services, Event Logs, Management Classes, management Events, Message Queues, Performance Counters, and
other Services on the system figure 4-22.
The Server Explorer allows us to interact with the above server resources. For example we can execute
database queries and display the result all from the Server Explorer in much the same way as we would
otherwise use SQL Server’s Management Studio To find out what we can do with a server item on the server
explorer, simply right-click it. In the example below we are opening a table definition in a database. We can then
add/modify/remove definition from the table just as we would from the Enterprise Manager Figure 4-23.
126
The Complete Reference To Professional SOA with Visual Studio 2005
Code Window
The code window is where majority of our development will be done in. It is here that we will spend majority of
our time developing ASP.NET XML Web services. To start developing we can select a particular file in the
solution explorer right click then select View Code.
Outlining
Outlining is a very useful function as it provides as an indicator where a class or a method starts and ends. We
can also collapse the outline to reduce the clutter in the code window. It allows us to view only the code that
interests us whilst blocking out the rest. To collapse a block of code simply click on the [-] minus outline to the
left of the code. To expand a block of code simply click on the [+] plus outline to expand the section see Figure 4-
24.
127
The Complete Reference To Professional SOA with Visual Studio 2005
128
The Complete Reference To Professional SOA with Visual Studio 2005
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.
129
The Complete Reference To Professional SOA with Visual Studio 2005
If an error is detected during the compiling stage Visual Studio will prompt us whether we want to continue. If
we choose to continue Visual Studio will use the last successful build of our application to execute because it can
not build a program with error. It is always a good habit to correct the error as soon as we are made aware.
Summary
In this chapter we have examined the role of the 2.0 version of the .NET Framework and the role that Visual
Studio 2005 plays in helping developers develop their service-oriented web applications.
* .NET is a comprehensive and yet flexible framework that allows developers to develop Console Application,
Windows GUI Application, ASP.NET Application, XML Web Service Application, Windows Service
Application and Mobile Applications. It is further enhanced with the release of .NET 2.0. All this is possible
from the Visual Studio 2005 IDE.
* .NET is more than just one language it is a framework that can be developed using different languages.
* .NET uses Common Language Runtime to provide the execution environment to .NET applications. All .NET
language compiles into MSIL code.
* .NET has a common type system where common data types, value and object types are common regardless the
.NET language we use to develop. This means all languages are equally powered.
* .NET ensures type safety, .NET Framework ensures that operations to be performed on one value or object are
performed on that value or object only.
* .NET manages code execution. The .NET Framework manages the state of objects during the program
execution. The Framework ensures automatic memory allocation and garbage collection.
* .NET supports side-by-side execution, allowing us to develop multiple versions of an application on a system
by using assemblies.
130
The Complete Reference To Professional SOA with Visual Studio 2005
131
The Complete Reference To Professional SOA with Visual Studio 2005
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
public Service () {
[WebMethod]
public string HelloWorld(string param1)
{
return "Hello " + param1;
}
Listing 5-2. Demonstrates a simple web service using Visual Basic .NET
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class Service
Inherits System.Web.Services.WebService
<WebMethod()> _
Public Function HelloWorld(ByVal param1 As String) As String
Return "Hello " & param1
End Function
End Class
Using the HelloWorld Web service example in listing 5-1 and listing 5-2. The process of invoking a web
service involves sending a message to the Web service itself. When a request first enters into IIS for the
HelloWorld (WebMethod), SimpleWebService (Web service) we had constructed earlier, it looks something like
this:
132
The Complete Reference To Professional SOA with Visual Studio 2005
This flow of the message to the Web service itself is shown below in figure 5-2.
1. IIS examines the request and determines that it is being sent a request that ends with the extension .asmx. The
ASP.NET handler is registered with IIS as handling this extension; therefore, the request in its entirety is
handed over to the ASP.NET process.
2. At this point, the ASP.NET worker process examines the request and discovers that it has a handler registered
in machine.config, the system-level .NET configuration file, for a request for resources with the extension
.asmx. It therefore kicks up this handler and passes the request onto it.
3. Next, the handler creates an instance of the class defined in the handler, and uses reflection to examine which
operations the class supports and how those operations should be routed. By default, operations are mapped to
methods using the SOAPAction HTTP header, but this can be changed to map to the first child element of the
SOAP body.
4. Once the message is routed, the handler uses the XML Serializer to deserialize the request XML into the
parameters that the method is expecting. Once the method returns, this return value and any out parameters are
mapped back into XML with the XML Serializer. Then, a response SOAP message is created that wraps this
XML, and the response is sent back, via ASP.NET’s HttpResponse context.
5. If an exception is thrown, then it is wrapped inside of a SoapException, and a SOAP fault is returned instead,
with the HTTP status code set to 500. (For non-error responses, the status code is 200, or OK.). These
messages typically transferred through HTTP.
133
The Complete Reference To Professional SOA with Visual Studio 2005
HTTP
Hyper Text Transfer Protocol (HTTP) is a World Wide Web Consortium (W3C) standard protocol for
transferring documents on the Internet. XML Web services use HTTP for communication. It is a generic,
stateless, protocol, which can be used for many tasks in addition its original use for hypertext.
A resource location is specified in HTTP through a mechanism known as a Uniform Resource Locator
(URL). Strictly speaking, the mechanism that is used in HTTP is a Uniform Resource Identifier (URI), but we
can also think of it as a URL.
The syntax of a URL is as follows:
http://host[:port][path[?querystring]]
The following is an example of a URL:
http://www.mswcf.com/url.aspx?id=23
In the preceding example, www.mswcf.com is the host, url.aspx is the path and id=23 is the query string. If
the port number is not specified (as in the preceding example), the default port for HTTP, which is port 80, is
used.
HTTP is a stateless protocol. This means that whenever the client makes a request, the connection to the
server is closed after the client receives the response. Therefore, if any state must be maintained between the
client and the server, the server must pass on state information with the response to the client. This will enable
the server to recover this information from the client when it receives the next request. For example, if we
implement a Web site that displays user-specific content, we would have to implement a mechanism that retains
information about the current user to display personalized content.
Id=23
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 75
* OPTIONS
* GET
* HEAD
* POST
* DELETE
134
The Complete Reference To Professional SOA with Visual Studio 2005
* TRACE
* CONNECT
* extension-method
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 75
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.
id=23
135
The Complete Reference To Professional SOA with Visual Studio 2005
The GET and POST request methods are ideal for communicating with an XML Web service. These
methods are designed specifically for submitting data to a Web server and retrieving a specified resource from a
Web server. This makes it possible to layer a function call model on top of these methods, which is exactly the
model that XML Web services requires.
HTTP GET uses an URL request to communicate information to a Web Page or an XML Web Service. The
most important feature of the request line is the querystring. The querystring is the portion of the URI that
follows the question mark, and consists of a set of URL-encoded name/value pairs.
In an HTTP-GET request, there is typically no message body. The response for an HTTP-GET request is
just a standard HTTP response.
id=23
In the preceding code, notice that there is no querystring as part of the URI. This is because the information
about the request is contained in the message body. This feature of an HTTP-POST request makes it a very
convenient way of passing larger sets of data to the server in contrast to an HTTP-GET where the size of the
querystring is restricted to 1024 bytes. Also, transmitting the data as part of the message body imposes fewer
restrictions on the kind of data that is sent to the server.
Tip: Both HTTP GET and POST can be applied to web applications as a standard form of execution. However in .NET 2.0 GET is disabled
as form of security precaution. To enable GET we must insert the below configurations into Web.Config.
<configuration>
<system.web>
<webServices>
<protocols>
<add name="HttpGet"/>
</protocols>
</webServices>
</system.web>
</configuration>
Alternatively, we can enable the GET protocol for all Web services on the computer by editing the
<protocols> section in Machine.config. The <protocols> section is located under the <webServices> section.
The following example enables HTTP GET, HTTP POST, and also SOAP and HTTP POST from localhost:
<protocols>
<add name="HttpSoap"/>
<add name="HttpPost"/>
<add name="HttpGet"/>
<add name="HttpPostLocalhost"/>
<add name="Documentation"/>
136
The Complete Reference To Professional SOA with Visual Studio 2005
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
This will produce the same result as clicking the Invoke button.
The HttpWebRequest and HttpWebResponse classes, which are derived from WebRequest and WebResponse
respectively, encapsulate the HTTP-specific aspects of the communications with a Web server. Most
importantly, they provide easy access to the HTTP headers, and the underlying request and response streams.
The StreamReader and StreamWriter classes are two utility classes that are used to read and write streams by
using a specific encoding (UTF-8/UTF-16, etc.).
Let’s create a simple console application to call the Web Service we had created earlier using HTTP POST.
TIP: Normally we do not need to call a Web service in this manner. As Visual Studio will automatically create a proxy for us which will
manage all Web service calls for us.
Having launched Visual Studio 2005, select File menu ~TRA New ~TRA Project. We will be presented
with the New Project dialog box, as shown in Figure 5-4. Simply select the language that we want to develop with
under the Project Types section. Then select Console Application from the Templates section.
137
The Complete Reference To Professional SOA with Visual Studio 2005
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.
Listing 5-8. Demonstrates a console application to send a HTTP POST request to a Web service using Visual C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
namespace CSHTTPRequest
138
The Complete Reference To Professional SOA with Visual Studio 2005
{
class Program
{
static void Main(string[] args)
{
string url = "http://localhost/soawebservice/" +
"firstservicecs/service.asmx/HelloWorld";
string contentType = "application/x-www-form-urlencoded";
string method = "POST";
string content = "";
HttpWebRequest req =
(HttpWebRequest)WebRequest.Create(url);
req.ContentType = contentType;
req.Method = method;
req.ContentLength = content.Length;
Stream s;
s = req.GetRequestStream();
StreamWriter sw = new StreamWriter(s, Encoding.ASCII);
sw.Write(content);
sw.Close();
Listing 5-9. Demonstrates a console application to send a HTTP POST request to a Web service using Visual Basic .NET
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Net
Imports System.IO
Namespace VBHTTPRequest
Module Program
Sub Main()
Dim url As String = "http://localhost/soawebservice/" + _
"firstservicecs/service.asmx/HelloWorld"
139
The Complete Reference To Professional SOA with Visual Studio 2005
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.
To use HttpWebRequest simply use WebRequest.Create the return value is converted to HttpWebRequest.
140
The Complete Reference To Professional SOA with Visual Studio 2005
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.
Stream s;
s = req.GetRequestStream();
StreamWriter sw = new StreamWriter(s, Encoding.ASCII);
sw.Write(content);
sw.Close();
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.
XML
XML is used to implement XML Web services in a number of ways. This includes the use of XML as the wire
format between an XML Web service consumer and the XML Web service, and the use of XML to describe the
XML Web service interface. XML is a big topic and full coverage is out of scope of this book. If you’re
unfamiliar with XML it is highly recommended that you find additional information on XML. We will cover
some basic notion of XML here, while later in the book we will focus on XML data manipulation with .NET 2.0.
It is recommended that the XML Web service developer have a solid understanding of XML.
XML is a complete tag-based language which uses tagged syntax to structure data. Documents that conform
to XML schema is structured from a variety of elements, namespace declarations, and attributes. Let’s have a
closer look.
141
The Complete Reference To Professional SOA with Visual Studio 2005
Elements
<tagname></tagname>
<tagname/>
<tagname>Value</tagname>
Elements make up majority of the XML document. There exist exactly one top level element known as the
document element. Elements have a name and may also contain child elements.
<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.
<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 _.
Since XML allows us to define our own tagname for elements it is thus possible to define the same tagname
twice. To be able to distinguish between the two tagnames XML offers namespaces as a means to distinguish
142
The Complete Reference To Professional SOA with Visual Studio 2005
between the two elements. This is done by associating an element with a namespace. A namespace acts as the
scope containing all the elements that have been associated to it.
A namespace name is defined by a uniform resource identifier (URI). URI serves as an ideal unique
identifier string. The namespace name and the local name together forms a globally unique name called
“Qualified Name”.
Namespace declarations associated with the element will be defined within the element’s start tag. A
typically shorter string known as the “namespace prefix” will be used. The syntax for the namespace declaration
will be xmlns:prefix='URI'. It is also possible not to map a namespace declaration to a prefix. We can use the
default namespace declaration. The syntax for a default namespace declaration is xmlns='URI'. In eiher cases
only one default namespace declaration may appear on an element. The URI can be defined by either single
quotes ‘ or double quotes “. It is also possible to map the same namespace to more than one prefix.
All namespaces have a scope to which is applied for the element on which it is declared and all of the
element’s descendants. The mapping of a given prefix for a namespace can be overridden by associating the
prefix with a new mapping for the element’s descendants. The in-scope default namespace if not using a prefix
can also be overridden by providing a new namespace declaration.
All names of elements in a XML document that conform to the Namespace are regarded as qualified names
(QNames).
In the following example an element with a local name of Person and a prefix of pre is mapped to a namespace URI of
urn:example-org:People. The element person has decendents or child elements of name and age. Both child elements are
assigned to the prefix of pre with the namespace URI of urn:example-org:People.
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
The namespace URI of an unqualified element is defined by the empty string “”. If a default namespace
declaration is defined and in scope then an unqualified namespace is required. We can overwrite the default
namespace declaration by defining the URI as an empty string in the form of xmlns=”” on the element.
The example below demonstrates using default namespace declaration. An element with the local name of person is assigned
a default namespace uri of urn:example-org:People. The element has two decendents or child elements of name and age.
143
The Complete Reference To Professional SOA with Visual Studio 2005
Both elements are not assigned to any prefix. As such they both automatically fall under the namespace of its parent element
of urn:example-org:People. This example is equivalent to the previous example
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.
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.
Attribute names are also Qualified Names (QNames). The namespace of an attribute is defined in the in-
scope namespace declaration for the prefix. Attributes that are not defined in the namespace declaration are
considered to be unprefixed even if default namespace is declared in the scope.
In the following example an element of person contains an child element of name and age. The age element contains
attributes of base and units. Base attribute is associated to the namespace of urn:example-org:People:base through a prefix
of ‘b’ while the Units attribute is associated with the namespace of urn:example-org:units with a prefix of ‘u’.
<Person xmlns='urn:example-org:People'
xmlns:b='urn:example-org:People:base'
xmlns:u='urn:example-org:units' >
<name>John Doe</name>
<age b:base='10' u:units='years' >44</age>
</Person>
Comments
<!-- comment text -->
In XML, document comments are also supported. Comments are used to provide additional human readable
information about the XML content. The comments begin with <!--followed by the comments and end with the -
->. Comments are never used as data and they can appear anywhere in the XML document. The text in the
144
The Complete Reference To Professional SOA with Visual Studio 2005
comment itself is situated between the start <!-- sequence and the end --> sequence. Character sequences such as
– may not appear within the comments.
<!-- this is a comment about xml -->
Whitespace
In XML whitespace characters refer to space characters, tabs, or carriage return and line feed characters. XML
requires that attributes and namespace declarations are separated from each other using whitespace. Whitespace
is also required between the text section of the XML comment and that of the comment’s closing sequence -->.
Other than the above requirements we can use whitespaces anywhere else in the document. These can be inside
element contents, processing instructions, comment texts and attribute values. Whitespace can also be used
within attribute name and namespace declarations. We can not use white space in an element between the
opening angle bracket < and its tag name. It also can not be used between the prefix colon local name sequence.
In the below example whitespace is used in various locations in the XML document. We can use whitespace between element
values, attribute value and separation of namespace and attribute.
* < - 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
* > - 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.
* & - 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.
* ' - 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.
* " - Stands for double quote “. Similar to apostrophe double quote can not be used in strings that already
are encapsulated within double quotes. The quote cannot be used because it would signal the end of the value.
If we need to use these characters then we should use entity reference to represent these characters.
145
The Complete Reference To Professional SOA with Visual Studio 2005
CDATA sections
<![CDATA[ text content possibly containing literal < or & characters ]]>
All text contained in a XML document will be parsed by the parser. Though only text contained in the CDATA
section will be ignored by the parser. As such the CDATA section is quite useful at blocking the requirement to
escape literal texts when using the prohibited characters such as <, >, and &. A CDATA section begins with the
sequence of <![CDATA[ followed by the text area in which the literal characters are ignored followed by the
closing sequence of ]]>. As such the character sequence ]]> which ends the CDATA section must not appear
within the section.
<sometext>
<![CDATA[ They're saying "x < y" & that "z > y" so I guess
that means that z > x ]]>
</sometext>
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.
Well-formed XML
A well formed XML document is a XML document that adheres to the strict syntactical rules. These rules are:
All tags must have a corresponding close tag or use shorthand close element syntax.
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.
146
The Complete Reference To Professional SOA with Visual Studio 2005
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.
From here on we can enter a new xml document or modify an existing document. Visual Studio has a
number of tools that will help format and modify the XML document.
147
The Complete Reference To Professional SOA with Visual Studio 2005
When editing an XML file Visual Studio provides context-sensitive intellisense. In the example below
figure 5-9, the drop down list contains various valid encoding types. Similarly when editing a XML file that has
a schema attached to it, the XML editor will provide context-sensitive intellisense based on the Schema.
Figure 5-9. Visual Studio 2005 XML Intellisense tool tip, smart indenting and syntax coloring
Once the user starts editing, the XML editor checks the well-formedness for errors in the XML and provides
live feedback to the user via two mechanisms. In the example in the screen shots below, the <xs:sequence> tag is
not closed, the end tag for <xs:sequence> does not match.
148
The Complete Reference To Professional SOA with Visual Studio 2005
The first mechanism is the red squiggly under the sequence of characters that is the cause of the errors. A
yellow vertical line is present next to the region of area. If the user's mouse pointer hovers over the section with
the error, a tool tip will provide the actual error text see figure 5-10.
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.
The Visual Studio XML editor also allows you collapse and expand XML outlines. This is particularly
handy when editing large xml documents.
149
The Complete Reference To Professional SOA with Visual Studio 2005
Datatypes
XML Schema provides a set of built-in datatypes. Some of these types are primitives, described in the
specification, whereas others are derived types described in a schema. Both primitive and derived types are
available to schema authors to use as is or to derive new types from.
Numeric types
Table 5-1.
150
The Complete Reference To Professional SOA with Visual Studio 2005
Type Description
Table 5-2.
Type Description
date A Gregorian calendar date
dateTime An instant in time
duration A duration in time
gDay A Gregorian day-long monthly recurring period
gMonth A Gregorian month
gMonthDay A Gregorian day-long annually recurring period
gYear A Gregorian calendar year
gYearMonth A Gregorian month-long annually recurring period
151
The Complete Reference To Professional SOA with Visual Studio 2005
Table 5-3.
Type Description
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).
Byte
The byte datatype represents the range of integer values that can be stored in an 8-bit signed field.
Value space: +127 to –128.
<num>+12</num>
<num>-127</num>
<num>0000056</num>
<num>0</num>
Date
The date datatype represents a Gregorian calendar date.
Value: Any date.
A normal date, and a date with negative time zone modifier
<date>2001-02-13</date>
<date>2001-02-13-05:00</date>
dateTime
The dateTime datatype represents an instant in time as a combination of Gregorian date and time-of-day values.
152
The Complete Reference To Professional SOA with Visual Studio 2005
Value: Any instant in time as a combination of Gregorian date and time-of-day values.
An instant in time
<instant>2001-02-13T22:20:00</instant>
<instant>2001-02-13T17:20:00-05:00</instant>
decimal
The decimal datatype represents arbitrary precision decimal numbers.
Value: The infinite set of all decimal numbers.
<num>123456</num>
<num>1.23456</num>
<num>+12.3456</num>
<num>0000123456.0000</num>
double
The double datatype represents IEEE double-precision 64-bit floating point numbers.
Value: +253 x 2970 to –253 x 2970.
<num>123456</num>
<num>1.23456E5</num>
<num>+12.3456E72</num>
<num>0000123456.0000</num>
duration
The duration datatype represents a duration of time in Gregorian years, months, days, hours, minutes, and
seconds according to ISO 8601.
Value: Any duration of time per ISO 8601.
<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.
<day>---13</day>
gMonth
The gMonth datatype represents a Gregorian month that recurs every year.
Value: Any month-long, annually recurring period.
153
The Complete Reference To Professional SOA with Visual Studio 2005
<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.
<monthDay>--02-13</monthDay>
gYear
The gYear datatype represents a Gregorian calendar year.
Value space: Any Gregorian calendar year.
<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.
<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.
<num>1234567890</num>
<num>42</num>
<num>+12</num>
<num>-273</num>
154
The Complete Reference To Professional SOA with Visual Studio 2005
integer
The integer datatype represents arbitrary integer values.
Value: The infinite set of all integers.
<num>123456</num>
<num>42</num>
<num>+12</num>
<num>-273</num>
language
The language datatype represents natural language identifiers according to RFC 1766.
Value: The set of all strings that are language identifiers.
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.
<name val='Person'/>
<name val='age'/>
<name val='height.units'/>
NCName
The NCName datatype represents XML noncolonized names, typically used for the local names of namespace-
qualified elements and attributes; that is, the part after the prefix and the colon.
Value: The set of all strings that match NCName production in XML Recommendation
XML NCNames
<name val='Person'/>
<name val='age'/>
<name val='height.units'/>
155
The Complete Reference To Professional SOA with Visual Studio 2005
negativeInteger
The negativeInteger datatype represents integer values of –1 or less.
Value: The infinite set of all integers with values of –1 or less.
negativeInteger values
<num>-42</num>
<num>-273</num>
<num>-0000056</num>
nonNegativeInteger
The nonNegativeInteger datatype represents the integer values zero or more.
Value: The infinite set of all integers with values of zero or more.
<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.
positiveInteger
The positiveInteger datatype represents integer values of 1 or more.
Value: The infinite set of all integers with values of 1 or more.
<num>42</num>
<num>+273</num>
<num>0000056</num>
156
The Complete Reference To Professional SOA with Visual Studio 2005
QName
The QName datatype represents qualified names in XML according to Namespace in XML.
Value: The set of pairs of a namespace name and a local name where a namespace name is a URI reference
and a local name is an NCName.
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
<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
157
The Complete Reference To Professional SOA with Visual Studio 2005
unsignedByte
The unsignedByte datatype represents the range of integer values that can be stored in an 8-bit unsigned field.
Value: +255 to zero.
<num>255</num>
<num>+12</num>
<num>0000056</num>
unsignedInt
The unsignedInt datatype represents the range of integer values that can be stored in a 32-bit unsigned field.
Value: +4,294,967,295 to zero.
unsignedInt values
<num>1234567890</num>
<num>42</num>
<num>+12</num>
unsignedLong
The unsignedLong datatype represents the range of integer values that can be stored in a 64-bit unsigned field.
Value: 18,446,744,073,709,551,615 to zero.
<num>1000000000000</num>
<num>1234567890</num>
<num>42</num>
<num>+12</num>
unsignedShort
The unsignedShort datatype represents the range of integer values that can be stored in a 16-bit unsigned field.
Value: +65,535 to zero.
<num>4242</num>
<num>+12</num>
<num>0000056</num>
Facets
Facets are used to restrict the set of values a datatype can contain, thus allowing types with different value ranges
to be derived from other types. The new value range must be equal to or narrower than the value range of the
base type. It is not possible to expand the value space of a type using facets.
Multiple facets can be specified in a single type definition, in which case the value space of the type is
constrained by all the facets listed. Any values appearing in the instance must conform to all the listed facets.
There are 12 facet elements, all of which share a common syntax. They each have a mandatory value
attribute that specifies the value for the facet. Although this attribute is of type xs:string, the value must typically
be a valid value of the type to which the facet is applied. For example, if a minExclusive facet is being used to
constrain the decimal datatype then the value must be numerical. Facets also have an optional fixed attribute of
type boolean. If the value of this attribute is true, then the facet cannot be respecified in a derived type. Lastly,
facets have an optional id attribute of type ID that is for application use.
158
The Complete Reference To Professional SOA with Visual Studio 2005
enumeration
<xs:enumeration value='string' fixed='boolean' id='ID' />
Defines a fixed value that the type must match. Multiple enumeration facets can be used to specify multiple legal
values. Thus, multiple enumeration facets have a cumulative effect, allowing multiple possible values.
Values: Any value that matches the type of the base type
<xs:simpleType name='sizes'>
<xs:restriction base='xs:string' >
<xs:enumeration value='small' />
<xs:enumeration value='medium' />
<xs:enumeration value='large' />
</xs:restriction>
</xs:simpleType>
fractionDigits
<xs:fractionDigits value='positiveInteger' fixed='boolean' id='ID' />
Specifies the maximum number of digits to the right of the decimal point for types derived from number. If
totalDigits and fractionDigits facets both appear, the value of the fractionDigits facet must be less than or equal
to the value of the totalDigits facet.
Values: positiveInteger
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
maxExclusive
<xs:maxExclusive value='number' fixed='boolean' id='ID' />
Specifies an exclusive upper bound on the value space of the type. The value specified by the facet is not
part of the value space of the new type. The maxExclusive facet may not be combined with the maxInclusive
159
The Complete Reference To Professional SOA with Visual Studio 2005
facet. If the maxExclusive facet appears with either the minInclusive or minExclusive facets, then the value of
the maxExclusive facet must be greater than or equal to the valueof the minInclusive or minExclusive facet.
Values: A value in the value space of the base type
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
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
160
The Complete Reference To Professional SOA with Visual Studio 2005
minExclusive
<xs:minExclusive value='number' fixed='boolean' id='ID' />
Specifies an exclusive lower bound on the value space of the type. The value specified by the facet is not
part of the value space of the new type. The minExclusive facet may not be combined with the minInclusive
facet. If the minExclusive facet appears with either the maxInclusive or maxExclusive facets, then the value of
the minExclusive facet must be less than or equal to the value of the maxInclusive or maxExclusive facet.
Values: A value in the value space of the base type
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
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
161
The Complete Reference To Professional SOA with Visual Studio 2005
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
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
whiteSpace
<xs:whiteSpace value='preserve|replace|collapse' fixed='boolean' id='ID' />
Defines rules for whiteSpace normalization. A value of preserve specifies that whitespace should be left
unchanged. A value of replace specifies that all occurrences of carriage return (#xD), line feed (#xA), and tab
(#x9) characters be converted to space (#x20) characters. A value of collapse specifies that all preceding or
trailing space (#x20) characters be removed; all carriage return (#xD), line feed (#xA), and tab (#x9) characters
be converted to space characters; and all sequences of two or more space characters be converted to a single
space character. Although strictly speaking the whiteSpace facet can be applied to any datatype for list types and
restricted datatypes with a base that is other than string or normalizedString the whiteSpace facet has a value of
collapse and may not be changed. For types derived from string any of the three possible values may be used.
For types derived from normalizedString, either replace or collapse may be used. Because of these limitations on
the use of the facet it is not generally used in schema documents because any derived type that required
particular whitespace normalization would be derived from string, normalizedString, or token as appropriate.
Values: preserve, replace, or collapse
162
The Complete Reference To Professional SOA with Visual Studio 2005
Language constructs
The XML Schema language provides support for defining simple datatypes based on existing simple datatypes.
New types can be defined to be a restriction of a type, a list of a type, or a union of two or more types.
In this section the language constructs for defining simple types, the simpleType, restriction, list, and union
elements, are listed each with syntax, description, list of attributes, list of children, and, in the case of the latter
three, examples.
simpleType
<xs:simpleType id='ID' final='list of token' name='NCName' >
<!-- annotation list restriction union -->
</xs:simpleType>
The simpleType element is used to define new types based on existing simple types. Simple type definitions
appearing as children of a schema element are named types available for use elsewhere in the schema and in
other schemas. Simple types may also appear as the children of element or attribute declarations or of other
simple type definitions, in which case they are anonymous types local to the context in which they appear.
restriction
<xs:restriction id='ID' base='QName' >
<!-- annotation enumeration fractionDigits length
maxExclusive maxInclusive maxLength minExclusive
minInclusive minLength pattern simpleType
totalDigits whiteSpace -->
</xs:restriction>
The restriction element appears as a child of the simpleType element and denotes that the simple type is a
restriction of some other simple type; that is, it has a narrower set of legal values than the base type. The simple
type on which the restricted type is based may be referred to using the base attribute or provided as an inline
anonymous type in a simpleType child element.
list
<xs:list id='ID' itemType='QName'>
<!-- annotation simpleType -->
</xs:list>
The list element appears as a child of the simpleType element and denotes that the simple type is a
whitespace-delimited list of some other, atomic simple type. The simple type on which the list is based may be
referred to using the itemType attribute or may be provided as an inline anonymous type in a simpleType child
element.
A list type
163
The Complete Reference To Professional SOA with Visual Studio 2005
Union
<xs:union id='ID' memberTypes='List of QName' >
<!-- annotation simpleType -->
</xs:union>
The union element appears as a child of the simpleType element and denotes that the simple type is a union
of two or more other simple types. The simple types on which the union is based may be referred to using the
memberTypes attribute and/or may be provided as inline anonymous types in simpleType child elements.
A numerical union
164
The Complete Reference To Professional SOA with Visual Studio 2005
The validity of an XML document is determined by a Document Type Definition (DTD) or an XML
Schema. There are several formats for data validation to choose from. A good listing for XML validation formats
can be found at http://www.oasis-open.org/cover/schemas.html. However, for the purpose of focusing on Web
service we will only be focusing on XML Schema validation.
The W3C Schema is the officially sanctioned Schema definition. Unlike DTDs, the format of W3C Schemas
follows the rules of well-formed XML documents. The Schema also allows for much more granular control over
the data that is being described. Because of the XML format and the detailed format controls, Schemas tend to be
very complex and often much longer than the XML documents that they are describing. Paradoxically, Schemas
are often much more easy for developers to read and follow, due to the less cryptic nature of the references in
Schemas compared to DTDs.
XML documents are evaluated against the rules defined in a XML schema. A well formed XML documents
that meet these rules are regarded as a valid XML document.
TIP: XML documents do not validate themselves. XML validation takes place when a document is parsed. Parsers or parser classes that
don’t support validation are called nonvalidating parsers, and parsers or classes that support validation are called validating parsers.
<rootelement xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"
xsi:noNamespaceSchemaLocation="examplexmlschema.xsd">
<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.
165
The Complete Reference To Professional SOA with Visual Studio 2005
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.
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.
166
The Complete Reference To Professional SOA with Visual Studio 2005
<xs:element ref="level1"/>
</xs:sequence>
<xs:attribute name="position" type="xs:boolean"
use="required"/>
</xs:complexType>
</xs:element>
The next element describes the level1 element, that it is an optional element (minOccurs=”0”), and that the
level1 element can occur an unlimited number of times in the document (maxOccurs="unbounded"). Nested in the
level1 element is a reference to the level2 element, just as it is in the document. Next, the children attribute is
specified as required, and defined as a simple Schema data type called NMTOKEN value for the base attribute,
which is, for the purposes of this schema, a string. The children string must be one of two predefined values, "0"
and "1", as defined by the enumeration values nested inside of the restriction element.
<xs:element name="level1">
<xs:complexType mixed="true">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="level2"/>
</xs:choice>
<xs:attribute name="children" use="required">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="0"/>
<xs:enumeration value="1"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
Even though the element level2 is defined separately to the element level1 we can still reference level2
within the level1 element as a nested element via the ref= reference.
In the following example, a schema named rootelement exists. The rooteleement must have both firstelement
and xelement nested under it to be considered a valid XML when using this schema.
<xs:element name="rootelement">
<xs:complexType>
<xs:sequence>
<xs:element ref="firstelement"/>
<xs:element ref="xelement"/>
</xs:sequence>
</xs:complexType>
</xs:element>
In the following example the required schema for the xelement is defined. The xelement contains a
complexType definition. The complexType defines a requirement for a nested element called level1 within
xelement. The xelement must also have an attribute named position of type byte value defined.
<xs:element name="xelement">
<xs:complexType>
<xs:sequence>
<xs:element ref="level1"/>
</xs:sequence>
<xs:attribute name="position" type="xs:byte"
167
The Complete Reference To Professional SOA with Visual Studio 2005
use="required"/>
</xs:complexType>
</xs:element>
Lastly we must close the schema with a equivalent schema close tag.
</xs:schema>
Figure 5-14. XSD designer helps to simplify development and designing of XSD
Figure 5-15. Intelligent XSD designer also allows customization of each and every element and attribute.
168
The Complete Reference To Professional SOA with Visual Studio 2005
SOAP
Simple Object Access Protocol (SOAP) is a simple and light weight protocol based on XML. SOAP relies on
XML to provide a structure for exchanging information on the Web. SOAP was designed to be kept as simple as
possible so that it can provide a messaging framework without defining the application or transport semantics.
SOAP thus is modular and very flexible because it is not tied down to any particular technological
implementation.
Due to SOAP’s simplistic definition on application and technology it can easily travel over standard
transport protocols. Commonly SOAP is used over the Web as it provides an excellent means to navigate
existing open architectures and work through firewalls between enterprises. Thus it can be easily supported and
implemented by any system capable of the basic Internet standards.
SOAP is a one-way message, a request from a client, or a response from a server is officially referred to as a
SOAP message. Every SOAP message has a mandatory Envelope element, an optional Header element, and a
mandatory Body element. Each of these elements has an associated set of rules, and understanding the rules will
help us debug our own SOAP applications.
Figure 5-16. shows the SOAP Message structure and how each element is contained within the structure.
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/"
SOAP:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP:Header>
<t:Transaction xmlns:t="some-URI" SOAP:mustUnderstand="1">
5
</t:Transaction>
</SOAP:Header>
<SOAP:Body>
<m:Deposit xmlns:m="Some-URI">
<m:amount>200</m:amount>
169
The Complete Reference To Professional SOA with Visual Studio 2005
</m:Deposit>
</SOAP:Body>
</SOAP:Envelope>
SOAP envelope
The envelope defines the SOAP message and is the basic unit required to facilitate exchange between two SOAP
services. It defines the specific rules required for the encapsulation of data being transferred between the
computers. The example below shows a SOAP envelope.
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/"
SOAP:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
.
.
</SOAP:Envelope>
Every SOAP message has a root Envelope element. In contrast to other specifications, such as HTTP and
XML, SOAP does not define a traditional versioning model based on major and minor release numbers (e.g.,
HTTP 1.0 versus HTTP 1.1). Rather, SOAP uses XML namespaces to differentiate versions. The version must
be referenced within the Envelope element. For example: <SOAP-ENV:Envelope xmlns:SOAP-
ENV="http://schemas.xmlsoap.org/soap/envelope/" The SOAP 1.1 namespace URI is
http://schemas.xmlsoap.org/soap/envelope/, whereas the SOAP 1.2 namespace URI is
http://www.w3.org/2001/09/soap-envelope. If the Envelope is in any other namespace, it is considered a versioning
error.
SOAP Header
The Header element is the first immediate child element of the SOAP Envelope element. All immediate child
elements of the Header element are known as header entries. The SOAP Header element is optional. It is used to
pass data that might be inappropriate to be encoded in the body. This can include transactional information,
routing information, security credential details or encoding information. The header is required if for example
the message is encoded however when the service receives the message it needs to know how to decode the
information in the body. Embedding the encoding information in the body doesn’t make sense as the body is
already encoded. An example of the SOAP header is shown below:
<SOAP:Header>
<t:Transaction xmlns:t="some-URI" SOAP:mustUnderstand="1">
5
</t:Transaction>
</SOAP:Header>
SOAP Body
The SOAP Body contains the content of the message. There is no restriction on how the body can be encoded.
The message body can be a simple string or an array of encoded bytes. An example of the SOAP body is shown
below:
<SOAP:Body>
<m:Deposit xmlns:m="Some-URI">
<m:amount>200</m:amount>
</m:Deposit>
</SOAP:Body>
170
The Complete Reference To Professional SOA with Visual Studio 2005
All immediate child elements of the Body element are called body entries and each body entry is a separate
element within the SOAP Body element. In the context of Web services, the Body element comprises the data
specific to the actual method call, such as the Web service method name and parameters and/or return values for
the method invocation.
SOAP Fault
The SOAP Fault element is used to transport error or status information or both, within a SOAP message. The
SOAP specification specifies the format for error reporting. The fault message must follow the following
structure.
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.
171
The Complete Reference To Professional SOA with Visual Studio 2005
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Body>
<ns1:getTemp
xmlns:ns1="urn:xmethods-Temperature"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<zipcode xsi:type="xsd:string">10016</zipcode>
</ns1:getTemp>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
There are a couple of important elements to note. First, the request includes a single mandatory Envelope
element, which in turn includes a mandatory Body element.
Second, a total of four XML namespaces are defined. Namespaces are used to disambiguate XML elements
and attributes, and are often used to reference external schemas. In our sample SOAP request, we’ll use
namespaces to disambiguate identifiers associated with the SOAP Envelope
(http://schemas.xmlsoap.org/soap/envelope/), data encoding via XML Schemas
(http://www.w3.org/2001/XMLSchema-instance and http://www.w3.org/2001/XMLSchema), and application
identifiers specific to XMethods (urn:xmethods-Temperature). This enables application modularity, while also
providing maximum flexibility for future changes to the specifications.
The Body element encapsulates the main “payload” of the SOAP message. The only element is getTemp ,
which is tied to the XMethods namespace and corresponds to the remote method name. Each parameter to the
method appears as a subelement. In our case, we have a single zip code element, which is assigned to the XML
Schema xsd:string data type and set to 10016. If additional parameters are required, each can have its own data
type.
SOAP Response
Here is the SOAP response from XMethods:
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.
172
The Complete Reference To Professional SOA with Visual Studio 2005
Quite logically, SOAP requests are sent via an HTTP request and SOAP responses are returned within the
content of the HTTP response. While SOAP requests can be sent via an HTTP GET, the specification includes
details on HTTP POST only. (HTTP POST is preferred because most servers place a character limit on GET
requests.)
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
173
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 5-17. shows the auto-generated SOAP for the WebMethod in the Web Service
Invoking Web Method using .NET HTTP POST, GET and SOAP.
In listing 5-14 and listing 5-15 below, we will demonstrate Web service request using HTTP GET, POST
and SOAP. Using these different methods we will invoke the HelloWorld WebMethod which takes in a string
parameter.
Note: The URL for the listing below may vary depending on the location that it was setup in.
Listing 5-14. Demonstrates invoking a Web service through HTTP GET, POST and SOAP using Visual C#
using System;
using System.Net;
using System.IO;
using System.Text;
using System.Xml;
using System.Collections.Specialized;
using System.Diagnostics;
namespace Technology
{
/// <summary>
/// Summary description for Main.
/// </summary>
class WebMethodCall
{
static void Main(string[] args)
{
174
The Complete Reference To Professional SOA with Visual Studio 2005
Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));
Trace.AutoFlush = true;
//send the relevant information to the service and then display the
//result from the service call
public static void GetData(string url,
string contentType, string method,
string content, params string[] headers)
{
Stream stream;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
foreach (string header in headers)
req.Headers.Add(header);
if (method.Length > 0)
req.Method = method;
if (contentType.Length > 0)
req.ContentType = contentType;
if (content.Length > 0)
{
req.ContentLength = content.Length;
stream = req.GetRequestStream();
StreamWriter sw = new StreamWriter(stream);
sw.Write(content);
sw.Close();
175
The Complete Reference To Professional SOA with Visual Studio 2005
}
DisplayRequest(req);
HttpWebResponse res = (HttpWebResponse)req.GetResponse();
DisplayResponse(res);
}
176
The Complete Reference To Professional SOA with Visual Studio 2005
string str;
byte[] buffer;
st = new MemoryStream(1024);
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
177
The Complete Reference To Professional SOA with Visual Studio 2005
"CSSimpleWebService/Service.asmx/HelloWorld?param1=kim"
Dim urlPost As String = "http://localhost/SOAWebService/" + _
"CSSimpleWebService/Service.asmx/HelloWorld"
Dim urlSoap As String = "http://localhost/SOAWebService/" + _
"CSSimpleWebService/Service.asmx"
Trace.Listeners.Add(New TextWriterTraceListener(Console.Out))
Trace.AutoFlush = True
'send the relevant information to the service and then display the
'result from the service call
Public Shared Sub GetData(ByVal url As String, _
ByVal contentType As String, ByVal method As String, _
ByVal content As String, ByVal ParamArray headers As String())
Dim stream As Stream
Dim req As HttpWebRequest = _
CType(WebRequest.Create(url), HttpWebRequest)
For Each header As String In headers
req.Headers.Add(header)
Next
If method.Length > 0 Then
req.Method = method
End If
If contentType.Length > 0 Then
req.ContentType = contentType
End If
If content.Length > 0 Then
req.ContentLength = content.Length
stream = req.GetRequestStream
Dim sw As StreamWriter = New StreamWriter(stream)
sw.Write(content)
sw.Close()
End If
178
The Complete Reference To Professional SOA with Visual Studio 2005
DisplayRequest(req)
Dim res As HttpWebResponse = _
CType(req.GetResponse, HttpWebResponse)
DisplayResponse(res)
End Sub
179
The Complete Reference To Professional SOA with Visual Studio 2005
tr.WriteStartElement("soap", "Envelope", _
"http://schemas.xmlsoap.org/soap/envelope/")
tr.WriteAttributeString("xmlns", "xsi", Nothing, _
"http://www.w3.org/2001/XMLSchema-instance")
tr.WriteAttributeString("xmlns", "xsd", Nothing, _
"http://www.w3.org/2001/XMLSchema")
tr.WriteAttributeString("xmlns", "soap", Nothing, _
"http://schemas.xmlsoap.org/soap/envelope/")
tr.WriteStartElement("Body", _
"http://schemas.xmlsoap.org/soap/envelope/")
tr.WriteStartElement(Nothing, "HelloWorld", _
"http://tempuri.org/")
tr.WriteElementString("param1", "kim")
tr.WriteEndElement()
tr.WriteEndElement()
tr.WriteEndDocument()
tr.Flush()
buffer = st.GetBuffer
Dim d As Decoder = Encoding.UTF8.GetDecoder
Dim chars(buffer.Length) As Char
d.GetChars(buffer, 2, buffer.Length - 2, chars, 0)
str = New String(chars)
tr.Close()
st.Close()
Return str
End Function
End Class
End Namespace
The main code responsible is the GetData function which is used send data to the web service as well as
retriving a response. This is achieved through the use of HttpWebRequest. We use WebRequest.Create(url) to
create an object of request to the Web service. Through this HttpWebRequest request object we’re able to set the
actual method of request whether its GET or POST. As well as the content type of the actual request. By using
GetRequestStream() we are able to obtain a reference to the actual request stream itself. Through the request
stream we can write everything that we wanted to send to Web service into the stream.
Once the request is sent we can use the same request object’s GetResponse() to obtain the HttpWebResponse
object. This will contain all the response information returned by the web service.
180
The Complete Reference To Professional SOA with Visual Studio 2005
req.ContentLength = content.Length;
stream = req.GetRequestStream();
StreamWriter sw = new StreamWriter(stream);
sw.Write(content);
sw.Close();
}
DisplayRequest(req);
HttpWebResponse res = (HttpWebResponse)req.GetResponse();
DisplayResponse(res);
}
181
The Complete Reference To Professional SOA with Visual Studio 2005
<HelloWorld xmlns="http://tempuri.org/">
<param1>string</param1>
</HelloWorld>
</soap:Body>
</soap:Envelope>
The BuildSOAPMessage function return a string that is used as the SOAP request. The end result of this is a
SOAP request that is shown below:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<HelloWorld xmlns="http://tempuri.org/">
<param1>kim</param1>
</HelloWorld>
</soap:Body>
</soap:Envelope>
tr.WriteStartElement("Body",
"http://schemas.xmlsoap.org/soap/envelope/");
tr.WriteStartElement(null, "HelloWorld",
"http://tempuri.org/");
tr.WriteElementString("param1", "kim");
tr.WriteEndElement();
tr.WriteEndElement();
tr.WriteEndDocument();
tr.Flush();
buffer = st.GetBuffer();
Decoder d = Encoding.UTF8.GetDecoder();
char[] chars = new char[buffer.Length];
d.GetChars(buffer, 2, buffer.Length - 2, chars, 0);
str = new String(chars);
182
The Complete Reference To Professional SOA with Visual Studio 2005
tr.Close();
st.Close();
return str;
}
Listing 5-19. Demonstrates building a SOAP request message using Visual Basic .NET
183
The Complete Reference To Professional SOA with Visual Studio 2005
184
The Complete Reference To Professional SOA with Visual Studio 2005
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://tempuri.org/">Hello kim</string>
*** Response End ***
185
The Complete Reference To Professional SOA with Visual Studio 2005
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body>
<HelloWorldResponse xmlns="http://tempuri.org/">
<HelloWorldResult>Hello kim</HelloWorldResult></HelloWorldResponse>
</soap:Body></soap:Envelope>
*** Response End ***
By using WSDL, a client application can locate a Web service and invoke any method that is defined in the
WSDL. Visual Studio comes with WSDL to code tool which we can use to convert these public methods defined
in the WSDL into code. This is called proxying and it allows us to integrate new Web services with little or no
manual code. WSDL is an critical part of the success of XML Web service this is because it provides a common
language to describe the implementation.
In the case of .NET, WSDL generation is automatic, having defined our code and what we want to expose in
the Web service. We can simply access the .asmx web service and use the ?wsdl syntax to retrieve the WSDL
document for example http://localhost/adventureworks/service.asmx?wsdl.
The WSDL specification defined by The World Wide Web Consortium (W3C)
(http://www.w3.org/TR/wsdl) defines six major elements:
definitions
The definitions element is the first element. It must be the root element of the entire WSDL document. It
defines the name of the Web service and holds information about the service and its attributes. It also defines
multiple namespaces that are used throughout the WSDL document. The use of namespaces is important for
differentiating between different elements, and it enables the document to reference multiple external
specifications, including the WSDL specification, the SOAP specification, and the XML Schema specification.
In the case of demonstrating the definitions element in WSDL from the Adventure works. The definitions
element specifies that the WSDL document is the AdventureWorks Service. It also specifies numerous
namespaces that will be used throughout the remainder of the document:
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:tns="http://tempuri.org/"
xmlns:s="http://www.w3.org/2001/XMLSchema"
186
The Complete Reference To Professional SOA with Visual Studio 2005
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
targetNamespace="http://tempuri.org/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
types
The types element is used to describe the data types that are used to exchange messages between the client and the
server. WSDL uses the W3C XML Schema specification as its default specification.
<wsdl:types>
<s:schema elementFormDefault="qualified"
targetNamespace="http://tempuri.org/">
<s:element name="GetProductName">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1"
name="productId" type="s:int" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="GetProductNameResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1"
name="GetProductNameResult" type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="string" nillable="true" type="s:string" />
</s:schema>
</wsdl:types>
message
The message element serves as a cross reference between the message and its definition within the schema.
Because we can use multiple schema definition formats within a WSDL document, it is necessary to have a
common way of identifying the messages. The message element provides this common level of abstraction that
will be referenced in other parts of the WSDL document.
<wsdl:message name="GetProductNameSoapIn">
<wsdl:part name="parameters" element="tns:GetProductName" />
</wsdl:message>
<wsdl:message name="GetProductNameSoapOut">
<wsdl:part name="parameters" element="tns:GetProductNameResponse" />
</wsdl:message>
<wsdl:message name="GetProductNameHttpGetIn">
187
The Complete Reference To Professional SOA with Visual Studio 2005
.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.
<wsdl:portType name="ServiceSoap">
<wsdl:operation name="GetProductName">
<wsdl:input message="tns:GetProductNameSoapIn" />
<wsdl:output message="tns:GetProductNameSoapOut" />
</wsdl:operation>
</wsdl:portType>
<wsdl:portType name="ServiceHttpGet">
<wsdl:operation name="GetProductName">
<wsdl:input message="tns:GetProductNameHttpGetIn" />
<wsdl:output message="tns:GetProductNameHttpGetOut" />
</wsdl:operation>
</wsdl:portType>
188
The Complete Reference To Professional SOA with Visual Studio 2005
<wsdl:portType name="ServiceHttpPost">
<wsdl:operation name="GetProductName">
<wsdl:input message="tns:GetProductNameHttpPostIn" />
<wsdl:output message="tns:GetProductNameHttpPostOut" />
</wsdl:operation>
</wsdl:portType>
In the above example the portType element defines a single operation, called GetProductName. The
operation itself consists of a single input message GetProductNameSoapIn or GetProductNameHttpGetIn or
GetProductNameHttpPostIn and a single output message of GetProductNameSoapOut or
GetProductNameHttpGetOut or GetProductNameHttpPostOut.
binding
The binding element contains binding definitions for binding a protocol such as SOAP to a particular
bindingType. The binding definitions specify message formatting and protocol details. For example, the binding
information specifies whether you can access an instance of a portType in an RPC-like manner.
The binding definitions also indicate the number of network communications required to perform a
particular action. For example, a SOAP RPC call over HTTP might involve one HTTP communication
exchange, but that same call over SMTP would involve two discrete SMTP communication exchanges.
<wsdl: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>
189
The Complete Reference To Professional SOA with Visual Studio 2005
</wsdl:port>
<wsdl:port name="ServiceHttpGet" binding="tns:ServiceHttpGet">
<http:address
location="http://localhost/SOAWebService/adventureworks/service.asmx" />
</wsdl:port>
<wsdl:port name="ServiceHttpPost" binding="tns:ServiceHttpPost">
<http:address
location="http://localhost/SOAWebService/adventureworks/service.asmx" />
</wsdl:port>
</wsdl:service>
UDDI v3
UDDI is a technical specification for describing, discovering, and integrating web services. UDDI is therefore a
critical part of the emerging web service protocol stack, enabling companies to both publish and find web
services.
At its core, UDDI consists of two parts:
* UDDI was originally developed as a distributed directory for businesses and web services. The directory has a
set of API to allow searching existing data and publishing new data.
* The UDDI Business Registry is a fully operational implementation of the UDDI specification. Launched in
May 2001 by Microsoft and IBM.
In 2005 UDDI v3 was launched. UDDI Version 3 (http://uddi.org/pubs/uddi_v3.htm) builds on the previous
vision of a “meta service” for locating web services by enabling robust queries against rich metadata. With a vast
190
The Complete Reference To Professional SOA with Visual Studio 2005
array of enhancements, including multi-registry topologies, increased security features, improved WSDL
support, a new subscription API and core information model advances. The Version 3 specification offers clients
and implementers a comprehensive and complete blueprint of a description and discovery foundation for a
diverse set of Web services architectures.
The data captured within UDDI is divided into three main categories:
White pages: This includes general information about a specific company - for example,
business name, business description, contact information, address and phone numbers. It can
also include unique business identifiers, such as a Dun & Bradstreet D-U-N-S® Number.
Yellow pages: This includes directory for the company and the service offered as well as their
contact details. For example, this information can include business, industry, product, or
geographic codes can all be searched on.
Green pages: This category contains technical information about a web service. Generally,
this includes a pointer to an external specification and an address for invoking the web
service. UDDI is not restricted to describing web services based on SOAP. Rather, UDDI can
be used to describe any service, from a single web page or email address all the way up to
SOAP, CORBA, and Java RMI services.
UDDI SDK
Microsoft provides a UDDI SDK for developing UDDI-enabled applications. The UDDI SDK includes both a
.NET and a COM-based object model for simplifying interaction with the registry. It also includes a standalone
UDDI registry for development purposes.
As at the time of writing, the UDDI SDK v2.0 is still in beta and is distributed as a separate download.
Microsoft currently does not have plans to ship the release to manufacture (RTM) version of the SDK in
conjunction with the .NET Framework. Instead, it plans to ship the RTM version of the UDDI .NET object
model on a release schedule separate from that of the .NET Framework..
The UDDI .NET SDK V2.0 Beta 1 can be downloaded from Microsoft.
191
The Complete Reference To Professional SOA with Visual Studio 2005
WS-* Standards
The WS-* family of standards provides a set of XML and Web Services standard formats, grammars, and
message sequences for communicating policy information and addressing the various security challenges across
different types of networks. This family of standards was introduced in 2002 by IBM and Microsoft as part of
their overall Web Services roadmap. The roadmap introduced WS-Security, which built on XML encryption and
XML signature to create a foundation layer. It also introduced several higher-level standards including:
WS-Policy: Defines the syntax and grammar for communicating policies as a set of
assertions.
WS-Security: Defines the syntax and grammar for communicating security tokens, digital
signatures, and message encryption information
WS-Trust: Defines the syntax and grammar for establishing trust relationships and
communicating with third-party trust brokers
WS-SecureConversation: Improves the efficiency of exchanges by defining a way to
exchange multiple messages within a single context or session
WS-Federation: Lays the foundation for creating federated trust relationships across multiple
domains
Since the initial roadmap was introduced, a number of supporting standards and standards proposals have
been introduced. These Include:
We will be focusing on the coverage of these standards using WSE and WCF in later chapters.
Summary
The HTTP is a World Wide Web Consortium (W3C) standard protocol for transferring documents on the
Internet. XML Web services use HTTP for communication. It is a generic, stateless, protocol, which can be used
for many tasks in addition its original use for hypertext.
192
The Complete Reference To Professional SOA with Visual Studio 2005
A resource location is specified in HTTP through a mechanism known as a Uniform Resource Locator
(URL). Strictly speaking, the mechanism that is used in HTTP is a Uniform Resource Identifier (URI), but we
can also think of it as a URL.
Web services use xml to provide interoperability between different platforms. This is achieved through the
use of SOAP, XML and XSD. Considering the central role that XML plays in XML Web services, it is useful to
review some of its important concepts:
* All XML documents must be well-formed. For a document to be well-formed, it must adhere to the following
rules:
* There must be a single root element.
* All elements must be closed, unlike HTML, where many elements (example: <BR>) are not required to be
closed.
The service description is created by using the Web Service Description Language (WSDL), which is an
XML-based language. Within the WSDL documents, we can define the XSD schemas that describe the data
types and document structures that are allowed in XML documents. XSD schemas validate XML documents in a
mechanical way. This frees the programmer from the error-prone task of correctly parsing and validating a
complex document structure.
193
The Complete Reference To Professional SOA with Visual Studio 2005
Chapter 6 Database
Programming with ADO.NET
As application development has evolved, new applications have become loosely coupled, often based on the
Web application model. Many applications today rely on XML to encode and transport data over the network.
Web applications are also beginning to rely on HTTP to communicate between tiers. This new model is very
different to the connected and tightly coupled style of programming that represents the client/server relationships
of the past.
Retrieving and processing data seems like a fairly straightforward task in a client/server model, but over the
past decade the way applications use data has changed repeatedly. Developers have moved from simple client
applications that use local databases to distributed systems that rely on centralized databases on dedicated
servers. At the same time, data access technologies have evolved. If you’ve worked with Microsoft languages for
some time, you’ve most likely heard of (and possibly used) a stream of data access technologies that includes
ODBC, DAO, RDO, RDS, and ADO.
In order to meet today’s needs Microsoft has recognized the need for a new programming model for data
access and built it upon the .NET Framework. The Framework would ensure that the data access technology
would remain consistent, as components could be easily shared amongst common type system, design patterns
and naming conventions. ADO.NET was created to address these issues and meet the need of today’s
programming model.
In this chapter we will be covering ADO.NET in detail and how to interact with the database using
DataSets. ADO.NET is an important area as in our Web service development we undoubtedly will be using
database at some stage.
ADO.NET
ADO.NET enables data-centric applications to connect to various data sources and retrieve, manipulate, and
update data. ADO.NET uses XML to transfer data across applications and data sources. ADO.NET provides
consistent access to data sources such as Microsoft SQL Server and XML, as well as to data sources exposed
through OLE DB and ODBC. Data-sharing consumer applications can use ADO.NET to connect to these data
sources and retrieve, manipulate, and update the data that they contain.
One of the advantages of ADO.NET is that it supports a disconnected architecture. Using a disconnected
architecture, applications connect to a database server only to retrieve or update the data. This allows us to
reduce the number of open connections to various database servers. ADO.NET also provides a common data
representation that enables us to access data from multiple and various types of data sources and have it appear
as one entity.
ADO. NET consists of managed classes that allow .NET applications to connect to data sources (usually
relational databases), execute commands, and manage disconnected data. The advantage of ADO.NET is that it
allows us to write the same data access code in web applications that we write for client-server desktop
applications.
ADO.NET provides a separation between data access and data manipulation. ADO.NET includes .NET
Framework data providers for connection to different databases, executing commands on these databases and
retrieving the results. The results retrieved can either be processed directly as it is being retrieved through using
ADO.NET DataReaders or placed into an ADO.NET DataSet object so that it can be returned to the user and
194
The Complete Reference To Professional SOA with Visual Studio 2005
processed later. We can also combine data from multiple sources or data that are from other applications. The
ADO.NET DataSet can also be used to manage data local to the application or sourced from a XML file.
The ADO.NET classes are defined in the System.Data namespace. This namespace contains classes such as
DataSet and DataTable which are all part of the ADO.NET architecture. To use ADO.NET is a simple matter of
adding a reference to the System.Data namespace within our application. In a later section we will be discussing
the ADO.NET architecture in detail.
Metadata Schemas
When we use Visual Studio 2005 to configuring ADO.NET 2.0 to talk to a live database within our application,
the IDE can pre-populate many of the database access parameters. This is because ASP.NET 2.0 and its data
providers can access metadata about that database, which the IDE can take advantage of to help us with drag-
and-drop functionality as we link the database to our app. The result is that Visual Studio 2005 is more helpful,
when it comes to database development, than any previous version.
By using that metadata, our app can become more flexible, such as being able to link dynamically to
databases and automatically configure itself to discover and use the appropriate tables, columns, stored
procedures and triggers. Alternatively, we can use the metadata to help our users customize their interactions
with databases, such as by creating reports that take advantage of tables or columns that we didn't know about
when we had built our application.
This metadata comes from the database engine itself. Every modern relational database or data source has its
own way of expressing metadata to its access clients. SQL Server 2005, for example, uses a different metadata
system than SQL Server 2000, but both are understood by SqlClient. Oracle has its own metadata system, which
is read the OracleClient data provider.
In ADO.NET 2.0 there is the System.Data.Common.DbMetaDataCollectionNames class which is used to store
the metadata information. Each data provider can import metadata information from the database and populate
the class. The SqlClient and OracleClient data providers included with ADO.NET 2.0 do this. These new
195
The Complete Reference To Professional SOA with Visual Studio 2005
metadata classes work with all data sources supported by ADO.NET 2.0 data providers, and not limited to just
SQL Server 2005.
Query Notification
A lot of applications use databases to store lookup information. This information includes product codes, product
categories, branch locations, state abbreviation, or even office locations. These items don’t often change, so to
improve performance we like to cache this information within the application. However in the past with
Framework 1.0 and 1.1 it was not possible to know when one of those rarely changed tables had actually
changed, so that we could reload the cache.
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.
196
The Complete Reference To Professional SOA with Visual Studio 2005
ADO.NET enables data transfer between components, such as data sources, DataSets, and the applications that
request data. Together, all of these components constitute the ADO.NET architecture. Figure 6-2 displays the
ADO.NET architecture.Data Sources
A data source is a database server for which the .NET Framework provides a data provider or an XML file.
To access a data source, we create a connection to the data source using the data providers of ADO.NET. The
ADO.NET data providers enable us to establish a connection with a data source and perform other tasks, such as
executing SQL commands on data sources. We will learn more about data providers later in this lesson.
.NET DataSets
The datacentric applications that we create usually need to access data from multiple tables. In addition, we
might need to process data from multiple tables as one entity. For example, an organization might need to access
the names of all its customers and the quantity of each product supplied to them.
The DataSet was explicitly designed so that data access is independent of the data source. As a result the
DataSet can work with multiple and differing data sources or using XML data or managed data local to the
application. It can contain a collection of one or more DataTable objects that is made up of rows and columns of
data. The Datatable object also supports primary key, foreign key and constraint and relation information about
the data.
197
The Complete Reference To Professional SOA with Visual Studio 2005
Data Providers
.NET data providers form the interface between the application and the data source. The data providers that the
.NET Framework provides allow us to connect to a data source, execute commands, and retrieve results. We can
either directly work with the data retrieved by a data provider or store it in an ADO.NET DataSet object.
The .NET Framework provides several data providers these are OLE DB Data Provider, .NET SQL Data
Provider, .NET Oracle Data Provider and ODBC Data Provider. Each provider is designed to be used with a
specific database see figure 6-3.
Connection
This is the object that allows us to establish a connection with the data source. Depending on the actual .NET
data provider involved, connection objects automatically pool database connections for us. It’s important to
realize that they don’t pool connection object instances, but they try and recycle database connections. Examples
of connection objects are OleDbConnection, SqlConnection, OracleConnection, and so on.
Command
This object represents an executable command on the underlying data source. This command may or may not
return any results. These commands can be used to manipulate existing data, query existing data, and update or
even delete existing data. In addition, these commands can be used to manipulate underlying table structures.
Examples of command objects are SqlCommand, OracleCommand.
DataReader
This class reads a forward-only stream of rows from a data source, and the rows can be accessed one at a time.
The connection must stay open while we’re reading the rows from the DbDataReader because the rows are read
directly from the data source when requested. However, the DataReader object allows us to store only one row of
data in memory at any point in time.
There are DataReaders derived from DbDataReader for every data provider:
198
The Complete Reference To Professional SOA with Visual Studio 2005
* If we were accessing a SQL Server database using the .NET SQL Provider then we would use the
SqlDataReader,
* OracleDataReader for the .NET Oracle Provider
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.
XML
XML is an important component of the ADO.NET architecture. ADO.NET uses XML internally to store and
transfer data. We need not explicitly convert data to the XML format or the XML format to data. XML is
integrated with ADO.NET as DataSets. The structure of the DataSet, including table definitions, columns, data
types, and constraints, is defined by using an XML schema. We can serialize the data within a DataSet as XML.
Similarly, we can serialize the structure of the DataSet as an XML schema.
Interoperability
Interoperability is one of the key benefits provided by ADO.NET. Because ADO.NET uses XML to exchange
data, any component that understands XML can receive data from ADO.NET. For example, we can transfer data
between ADO.NET and an application that is running on any platform. The integration of XML and ADO.NET
allows ADO.NET to operate easily with the applications that support XML.
Maintainability
Applications created using ADO.NET are easier to manage and scale than applications created using ADO. For
example, after developing an application, we might need to change its architecture to improve its speed or
increase the number of people who can access the application. Consider the example of an e-commerce site. As
the e-commerce site becomes popular, the number of hits on the site increases. If the number of hits increases,
we might need to change the architecture of the application and increase the number of tiers. However,
increasing the number of tiers in a deployed application is a difficult and time-consuming task. In addition,
problems might occur during data exchange or data transfer between the tiers. ADO.NET enables us to easily
increase tiers in a deployed application because ADO.NET uses XML to transfer data between tiers. This
enables the objects in new tiers to exchange data seamlessly.
199
The Complete Reference To Professional SOA with Visual Studio 2005
Programmability
ADO.NET simplifies programming for various tasks, such as executing SQL commands. This enables us to
increase productivity and minimize the number of errors. For example, we can use the ADO.NET data
commands to execute SQL statements or stored procedures. The actual task of building and executing a SQL
statement is abstract and performed by ADO.NET. In addition, the ADO.NET data classes enable us to use typed
programming to write code. Typed programming allows automatic statement completion. Therefore, it becomes
easy to write code. In addition, typed programming increases the safety of the code and reduces the number of
compilation errors.
Performance
In the past the traditional ADO disconnected recordsets model use COM marshaling to transfer data between
applications. This required a conversion process for COM to recognize the data type. This diminishes the
performance of an application. Alternatively ADO.NET uses XML to transfer data. Therefore, the requirement
to convert the data type does not exist, which increases the performance of an application.
Scalability
With the increase in data and the change in the business models of organizations, the demand for data has
increased rapidly. Consider a Web site that sells sporting goods. When a prospective buyer wants to view
product information, the information is available in the Products database. If several prospective customers
accessing the Web site simultaneously want to view information about the same product, the demand for data
from the Products database increases. ADO.NET enables our applications to scale according to requirements
because it uses disconnected architecture. This enables us to reduce the open connections to the database and
results in optimum usage of resources.
200
The Complete Reference To Professional SOA with Visual Studio 2005
* 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.
Figure 6-4 SQL data provider and Oracle data provider provides better performance than OLE DB data provider.
201
The Complete Reference To Professional SOA with Visual Studio 2005
using System.Data.OleDb;
Imports System.Data.OleDb
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.
using System.Data.SqlClient;
Imports System.Data.SqlClient
202
The Complete Reference To Professional SOA with Visual Studio 2005
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.
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-6. Opening and Closing Connections using Visual Basic .NET
203
The Complete Reference To Professional SOA with Visual Studio 2005
Finally
If conn.State = System.Data.ConnectionState.Open Then
conn.Close()
End If
End Try
Alternatively we could in C#
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.
204
The Complete Reference To Professional SOA with Visual Studio 2005
myCommand.CommandText = mySQL;
Console.WriteLine(myCommand.ExecuteScalar().ToString());
myConnection.Close();
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 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:
This SQL statement returns just one value that is part of a single row and single column.
205
The Complete Reference To Professional SOA with Visual Studio 2005
myCommand.CommandText = mySQL.Trim();
OleDbDataReader myReader;
myReader = myCommand.ExecuteReader();
Console.WriteLine(myReader.FieldCount.ToString());
myConnection.Close();
myCommand.CommandText = mySQL
Console.WriteLine(myReader.FieldCount.ToString())
myConnection.Close()
myCommand.Connection = myConnection;
myCommand.CommandText = mySQL.Trim();
206
The Complete Reference To Professional SOA with Visual Studio 2005
int NoOfRows = 0;
NoOfRows = myCommand.ExecuteNonQuery();
Console.WriteLine("({0}) rows affected.", NoOfRows);
myConnection.Close();
myCommand.CommandText = mySQL
myCommand.Connection = myConnection;
myCommand.CommandText = mySQL;
Console.WriteLine(myCommand.ExecuteScalar().ToString());
207
The Complete Reference To Professional SOA with Visual Studio 2005
myConnection.Open()
myCommand.Connection = myConnection
myCommand.CommandText = mySQL
Console.WriteLine(myCommand.ExecuteScalar().ToString())
The usage of the SqlCommand object is very similar to the usage of the OleDbCommand object. However,
we need not specify the name of the provider in the ConnectionString property.
The SqlCommand object consists of four Execute methods: ExecuteScalar, ExecuteReader,
ExecuteNonQuery, and ExecuteXMLReader. The syntax and functionality of these methods are identical to the
syntax and functionality of the OleDbCommand object.
208
The Complete Reference To Professional SOA with Visual Studio 2005
Listing 6-15. Demonstrates how to use the SelectCommand, InsertCommand, UpdateCommand, and DeleteCommand
properties using Visual C#
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;
209
The Complete Reference To Professional SOA with Visual Studio 2005
myConnection.Close();
Listing 6-16. Demonstrates how to use the SelectCommand, InsertCommand, UpdateCommand, and DeleteCommand
properties using Visual Basic .NET
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.
210
The Complete Reference To Professional SOA with Visual Studio 2005
DataReader is an efficient means of accessing large amount data. We can create a DataReader object by executing the
ExecuteReader() method of the Command object. There are two data readers the SqlDataReader class and the
OleDbDataReader class. The following sections discuss these two data readers in detail.
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();
211
The Complete Reference To Professional SOA with Visual Studio 2005
myReader.Close()
' Close the connection when done with it.
myConnection.Close()
In the code above, the SqlDataReader object is initialized to the object returned by the ExecuteReader() method.
We use the Read() method of the SqlDataReader object to read a row from the data source. Observe that the
DataReader object has just one row at any given time. We can call the Read() method of the SqlDataReader
object to fetch subsequent rows. After reading from the SqlDataReader object, we can close the SqlDataReader
object. After closing the SqlDataReader object, we can call the IsClosed() method and the RecordsAffected
property.
212
The Complete Reference To Professional SOA with Visual Studio 2005
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.
Selecting “Add Connection” will raise a dialog box. We can specify the Server that we want to connect to as
well as the database and the security information required for access here see figure 6-7.
213
The Complete Reference To Professional SOA with Visual Studio 2005
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.
214
The Complete Reference To Professional SOA with Visual Studio 2005
Again depending on the Edition of Visual Studio that is used the screenshots may differ slightly.
By selecting a new windows application Visual Studio 2005 will automatically generate a Windows Form
on the designer see figure 6-10.
To display the information that we wanted to display we can drag and drop a DataGridView control from
under the Data tab in the toolbox onto the screen. The DataGridView is typically used to display information in a
tabular format. Select the little arrow on the top right corner of the DataGridView control. This will bring out a
context menu which shows a list of predefined DataGridView Tasks see figure 6-11.
215
The Complete Reference To Professional SOA with Visual Studio 2005
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.
Once we have selected the “Add Project Data Source” option we will be prompted to either add a data
source to a Database, Web Service or an Object see Figure 6-13. In this particular example we will be selecting
Database as the source of information.
216
The Complete Reference To Professional SOA with Visual Studio 2005
By selecting the next option since we have selected the Database as the source location for information we
will prompted to select the source Database location see figure 6-14.
Figure 6-14: select the DataSource from the drop down list or create a new data source connection.
Visual Studio will prompt us whether we wanted to save the connection string into the configuration file. It
is particularly important to keep all connection information in a configuration file. As it will simplify the task of
migrating applications from a development environment to a production environment.
217
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 6-15: Save the connection string as a specified name so that it can be called within the application
Once the we have saved the connection string into the Application configuration file Visual Studio will
connect to the database and retrieve relevant database information see Figure 6-16.
Figure 6-16 Visual Studio will retrieve database information from the specified connection string.
We will be prompted where to retrieve information from in the database. These could include Tables, Views,
Stored Procedures and Functions. The information will then be saved to a DataSet. In this case we have named it
“AdventureWorksDataSet” see Figure 6-17.
218
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 6-17: select the table that we are interested to retrieve the table.
In this particular example we will be retrieving information from the database table Employee. To do this
we must first expand the Tables node. By browsing to the relevant table in this case Employee and then
expanding the Employee table and selecting the relevant columns of interest we can indicate to visual studio
which columns we would like to retrieve from the Employee database table see Figure 6-18.
Figure 6-18 select the table and the columns that we are interested in
Once the selection is made select the Finish button. We will be brought back onto the context menu for the
DataGridView. But notice that from the meta information gathered from the database column that we had
selected Visual Studio will automatically create the Columns for us in the DataGridView. We can also
219
The Complete Reference To Professional SOA with Visual Studio 2005
automatically specify to Enable Adding, Enable Editing and Enable Deleting by checking the boxes see figure 6-
19.
Figure 6-19 DataGridView is now populated with the column information that we had selected
We can run the application by simply clicking on F5 to (Start Debugging) or Ctrl+F5 to (Start without Debugging)
Figure 6-20 shows the end result from the application after it is compiled and ran.
We have seen how simple it is to connect to a database and retrieve information using Visual Studio’s
DataGridView Smart databinding.
Internally Visual Studio 2005 has generated the necessary codes to achieve this. The following code is
placed into the Form_Load event so that the application can use the DataAdapter to populate the dataset at
runtime.
this.employeeTableAdapter.Fill(this.adventureWorksDataSet.Employee);
220
The Complete Reference To Professional SOA with Visual Studio 2005
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.
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
221
The Complete Reference To Professional SOA with Visual Studio 2005
using System.Data.SqlClient;
namespace CSOleDbCommand2
{
class Program
{
static void Main(string[] args)
{
string mySQL =
"Select * from HumanResources.Department";
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);
//update a row.
222
The Complete Reference To Professional SOA with Visual Studio 2005
//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)
223
The Complete Reference To Professional SOA with Visual Studio 2005
myDataSet.Tables(0).Rows.Add(newdr)
Console.WriteLine("Row count after adding row: " + _
myDataSet.Tables(0).Rows.Count.ToString)
myAdapter.Update(myDataSet)
Console.ReadLine()
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.
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;
Console.WriteLine(builder.GetInsertCommand().CommandText);
Console.WriteLine(builder.GetUpdateCommand().CommandText);
Console.WriteLine(builder.GetDeleteCommand().CommandText);
224
The Complete Reference To Professional SOA with Visual Studio 2005
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#
225
The Complete Reference To Professional SOA with Visual Studio 2005
Listing 6-24. Demonstrates inserting a record into the database using DataSet in Visual Basic .NET
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-26. Demonstrates updating a database record using DataSet in Visual Basic .NET
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-28. Demonstrates deleting a database record using DataSet in Visual Basic .NET
226
The Complete Reference To Professional SOA with Visual Studio 2005
myDataSet.Tables(0).Rows.Remove(deldr)
myAdapter.Update(myDataSet)
myConnection.Close()
A DataTable also contains the Constraints collection. The Constraints collection allows DataSets to
implement all constraints including the constraints at the database level. When we modify the data of a table in a
DataSet, the DataSet implements all the constraints at the client level. Therefore, when a DataSet connects to a
database to perform an update operation, data is updated quickly; the round trip from the database server to the
client is avoided.
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.
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.
227
The Complete Reference To Professional SOA with Visual Studio 2005
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-36. Demonstrates adding Primary key to a DataTable using Visual Basic .NET
As mentioned earlier, a DataSet object can contain multiple tables. We can also create relationships between the
tables in a DataSet. We can use various methods of the DataRelation object to create and manage relationships
between the tables in a DataSet.
To create a relationship between two tables in a DataSet, we use the Add method of the DataRelation object.
The Add method takes a name for the relationship being created, and the DataColumn references of the columns
that we want to define as the parent and child columns in the relationship. The following code shows how to
create relationships between two tables in a DataSet.
228
The Complete Reference To Professional SOA with Visual Studio 2005
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"))
Preserve Changes
When we merge a DataSet, DataTable, or DataRow object with a DataSet, we can specify whether to preserve
the changes in the existing DataSet and how to manage the new schema elements in the incoming data. We can
use the PreserveChanges property to specify whether to preserve the changes in the existing DataSet. If the
PreserveChanges property is set to True, the existing values in the table receiving data are not overwritten with
the incoming values. However, if the PreserveChanges flag is set to False, the existing values are overwritten by
the incoming values in the current row version of the existing row.
229
The Complete Reference To Professional SOA with Visual Studio 2005
Apply Constraints
When we merge the contents of two DataSets, constraints are not checked when the Merge method is executed.
After we add the data to a receiving table, constraints are enforced on the current values in the DataSet.
Therefore, we need to ensure that we can handle the exceptions in our code.
We use the Merge method of a DataSet object to combine the contents of a DataSet, DataTable, or DataRow
object with another DataSet, DataTable, or DataRow object.
DBConn.Open();
Listing 6-40. Demonstrates using DataSet’s Merge using Visual Basic .NET
In the listing above we first load the values into our EmpDS DataSet. We also load values from a
Employee.xml file into a second DataSet. We then merge the EmpDS2 DataSet into the EmpDS DataSet using
the merge function. Notice we have used MissingSchemaAction.AddWithKey this will adds the necessary
columns and primary key information to complete the schema of EmpDS if it does not already exist.
230
The Complete Reference To Professional SOA with Visual Studio 2005
Listing 6-42. Demonstrates using DataSet’s Merge using Visual Basic .NET
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-44. Demonstrates using DataSet’s GetChanges using Visual Basic .NET
Listing 6-46. Demonstrates DataSet’s clone function using Visual Basic .NET
231
The Complete Reference To Professional SOA with Visual Studio 2005
default constructor of the DataView class and pass a table name as an argument. The following code shows how
to create a DataView object using the DataView constructor.
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-50. Demonstrates DataView’s Sort and Filter using Visual Basic .NET
232
The Complete Reference To Professional SOA with Visual Studio 2005
{
Console.WriteLine("Merge failed for table " + args.Table.TableName);
Console.WriteLine("Conflict = " + args.Conflict);
}
Listing 6-52. Demonstrates using the MergeFailed event using Visual Basic .NET
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
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.
233
The Complete Reference To Professional SOA with Visual Studio 2005
variables, the strongly typed DataSets allow us to access tables and columns using user-friendly names and
strongly typed variables.
A typed DataSet is a class that derives from a DataSet. The strongly typed DataSet inherits all the methods,
events, and properties of a DataSet. In addition, a typed DataSet provides us with strongly typed methods,
events, and properties. Therefore, we can access tables and columns by their names instead of using collection-
based methods. This feature of strongly typed DataSets improves the readability of our code and allows the
Visual Studio 2005 code editor to provide the IntelliSense technology, which automatically completes the
statements as we type. The IntelliSense technology increases the quality of our code because it corrects type
mismatch errors at compile time rather than at run time.
We can create a strongly typed DataSet using the command-line utility XSD.exe. The following command
creates a strongly typed DataSet:
xsd.exe /d /l:CS XSDSchemaFileName.xsd /n:XSDSchema.Namespace
We can also use Visual Studio to create Typed DataSet.
Notice the AdventureWorksDataSet.xsd in the solution explorer. This is the Typed Dataset Visual Studio had
automatically generated for the for the data access example we had just gone through in the previous section.
This allows for IntelliSense to do the grunt of the work for us and thus avoiding mistyping table and column names see
Figure 6-22:
234
The Complete Reference To Professional SOA with Visual Studio 2005
Open Visual Studio 2005 select File->New->Project. Select the programming language of choice and select Windows
Application as the template of choice. Enter TypedDataSet as the name for the project and select a location to save the
project to see figure 6-23.
235
The Complete Reference To Professional SOA with Visual Studio 2005
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.
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.
236
The Complete Reference To Professional SOA with Visual Studio 2005
Right click on the DataSet designer and select Add->TableAdapter. The TableAdapter will help us with
handling the SELECT, INSERT, UPDATE, DELETE operations for the DataSet see figure 6-26.
Tip: To see all of the files associated with the TypedDataSet.xsd file you will need to make sure that the Show All Files button is selected in
the solution explorer.
Once we have selected TableAdapter from the context menu we will be prompted on the location of the
database. Either select an existing ConnectionString or define a new ConnectionString by selecting the New
Connection button see figure 6-27.
237
The Complete Reference To Professional SOA with Visual Studio 2005
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”.
We can select the Tables, Views or Functions that we’re interested in. In this case select the Employee table
which is under Human Resources see figure 6-29 and select Add.
238
The Complete Reference To Professional SOA with Visual Studio 2005
We can use Visual Studio’s internal query builder to design the query we need to select from the table see
figure 6-30.
We can execute our query to validate the result by clicking the Execute Query button. When the wizard has
completed we will have our DataTable see figure 6-31.
239
The Complete Reference To Professional SOA with Visual Studio 2005
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.
240
The Complete Reference To Professional SOA with Visual Studio 2005
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.
We could change the properties of each column by selecting the Column and altering the properties in the properties
window.
241
The Complete Reference To Professional SOA with Visual Studio 2005
242
The Complete Reference To Professional SOA with Visual Studio 2005
Alternatively if data relationships do not exist we could simply drag and drop the from the Parent key column of one
table to the Foreign key column of another table to establish a new relationship.
Just as in the database we could specify the type of constraint to apply to the relationship.
try
{
...
}
catch (Exception ex)
{
243
The Complete Reference To Professional SOA with Visual Studio 2005
...
}
catch (SqlTypeException sqlTypeEx)
{
...
}
catch (SqlTruncateException sqlTruncateEx)
{
...
}
Listing 6-54. Demonstrates the incorrect order of Exception Handling in Visual Basic .NET
Try
...
Catch ex as Exception
...
Catch sqlTypeEx as SqlTypeException
...
Catch sqlTruncateEx as SqlTruncateException
...
End Try
try
{
...
}
catch (SqlTruncateException sqlTruncateEx)
{
...
}
catch (SqlTypeException sqlTypeEx)
{
...
}
catch (Exception ex)
{
...
}
Listing 6-56. Demonstrates the correct order of Exception Handling in Visual Basic .NET
Try
...
Catch sqlTruncateEx as SqlTruncateException
...
Catch sqlTypeEx as SqlTypeException
...
Catch ex as Exception
...
244
The Complete Reference To Professional SOA with Visual Studio 2005
End Try
Thus, to write effective exception-handling code, we have to understand the various levels of exception classes
that exist within ADO.NET and use them accordingly.
Listing 6-58. Demonstrates setting Context Connection using Visual Basic .NET
* By doing so, SQL server skip over the Tabular Data Stream (TDS) protocol layer and the TCP/IP or Named
Pipes protocol layer, and directly get a hold of the connection inside the database.
* We do not need to reauthenticate this saves redundant authorization lookup.
* We have the ability to latch on to a currently running transaction easily.
* Any external noncontext connections created by specifying a full ADO.NET connection string would
automatically try to enlist themselves in the active running transaction and thus be promoted to Microsoft
Distributed Transaction coordinator (MSDTC). The exception to this rule being loop-back connections into the
same SQL Server 2005 database. Such connections cannot enlist themselves in the same transaction and must
use enlist=false in their connection strings to work.
However, there are certain restrictions placed on a context connection as well. These are listed here:
* We can have at most only one open SqlConnection object within the same execution scope.
245
The Complete Reference To Professional SOA with Visual Studio 2005
* Multiple Active Resultsets (MARS) does not work with context connections. (In short, MARS lets us execute
multiple statements and maintain their results on the same connection. It’s important to note that, in reality, the
statements are not executing in parallel, they are only executing on the same connection.)
246
The Complete Reference To Professional SOA with Visual Studio 2005
Alternatively, if we do not have a database reference already set up in our IDE, Visual Studio will prompt us to
create a new database reference.
We can create a series of SQL Server 2005 items these are, User-Defined Function, Stored Procedure,
Aggregate, Trigger, User-Defined Type.
247
The Complete Reference To Professional SOA with Visual Studio 2005
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.
[Microsoft.SqlServer.Server.SqlProcedure]
public static void GetEmployeeByID(int empid)
{
248
The Complete Reference To Professional SOA with Visual Studio 2005
<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
249
The Complete Reference To Professional SOA with Visual Studio 2005
And deploy
250
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 6-46
Now we can execute our first .NET stored procedure. By selecting a new query in SQL Server 2005 Management
Studio and executing it.
Execution of user code in the .NET Framework is disabled. Enable "clr enabled"
configuration option.
Tip: In the following example > is used to indicate the command that should be typed.
In order to enable the execution of .NET code inside SQL Server, just issue the following command:
251
The Complete Reference To Professional SOA with Visual Studio 2005
Now after we had configured SQL Server 2005 to allow .NET CLR we can execute our .NET store procedure
via.
>exec dbo.storedprocedure1 "1"
[Microsoft.SqlServer.Server.SqlProcedure]
public static void GetEmployeeHireDateByTitle(string Title)
252
The Complete Reference To Professional SOA with Visual Studio 2005
{
// Put your code here
using (SqlConnection contextConnection =
new SqlConnection("context connection = true"))
{
SqlCommand contextCommand =
new SqlCommand(
"Select HireDate from HumanResources.Employee " +
"where Title = @title", contextConnection);
contextCommand.Parameters.AddWithValue("@title", Title);
contextConnection.Open();
// first, create the record and specify the
// metadata for the results
SqlDataRecord rec = new SqlDataRecord(
new SqlMetaData("HireDate", SqlDbType.VarChar, 50)
);
// start a new result set
SqlContext.Pipe.SendResultsStart(rec);
// send rows
SqlDataReader rdr = contextCommand.ExecuteReader();
while (rdr.Read())
{
Listing 6-59. Demonstrates using embed .NET code using Visual Basic .NET
<Microsoft.SqlServer.Server.SqlProcedure()> _
Public Shared Sub GetEmployeeHireDateByTitle(ByVal Title As String)
' Using
Dim contextConnection As SqlConnection = _
New SqlConnection("context connection = true")
Try
Dim contextCommand As SqlCommand = _
New SqlCommand
("Select HireDate from HumanResources.Employee " + _
"where Title = @title", contextConnection)
contextCommand.Parameters.AddWithValue("@title", Title)
contextConnection.Open()
Dim rec As SqlDataRecord = _
New SqlDataRecord(New SqlMetaData("HireDate",
SqlDbType.VarChar, 50))
SqlContext.Pipe.SendResultsStart(rec)
Dim rdr As SqlDataReader = contextCommand.ExecuteReader
While rdr.Read
253
The Complete Reference To Professional SOA with Visual Studio 2005
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.
SqlContext.Pipe.SendResultsStart(rec);
// send rows
SqlDataReader rdr = contextCommand.ExecuteReader();
while (rdr.Read())
{
SqlContext.Pipe.SendResultsStart(rec)
Dim rdr As SqlDataReader = contextCommand.ExecuteReader
254
The Complete Reference To Professional SOA with Visual Studio 2005
While rdr.Read
rec.SetString(0, "Hired on: " + _
rdr.GetDateTime(0).ToShortDateString)
SqlContext.Pipe.SendResultsRow(rec)
End While
SqlContext.Pipe.SendResultsEnd()
Figure 6-49: shows the result set from executing the stored procedure.
TIP: .NET 2.0 and Sql Server 2005 is not only restricted to allowing .NET code running in stored procedure. We could also create Stored
Procedure, User-Defined Function, Trigger, Aggregate and User-Defined Type. Unfortunately we can not cover all of these within this
book.
Summary
In this chapter we have learned that ADO.NET enables datacentric applications to connect to various data
sources and retrieve, manipulate, and update data. ADO.NET uses XML to transfer data across applications and
data sources. This enables us to use ADO.NET to access any data source including SQL Server and other
database servers that use OLE DB to expose data.
We have also learned about .NET data providers and that it forms the interface between the application and
the data source. The data providers that the .NET Framework provides allows us to connect to various data
sources such as SQL Server 7.x or later and OLE DB. A data adapter forms an interface between the application
255
The Complete Reference To Professional SOA with Visual Studio 2005
and the data source for retrieving and saving data. The OleDbDataAdapter, SqlDataAdapter and OracleDataAdapter
object represents a connection and a set of Command objects that help populate a DataSet object.
To use ADO.NET we can use an ADO.NET DataReader. The ADO.NET DataReader allows us to read the
read-only, forward-only data from a data source. To create a DataReader object, we can execute the
ExecuteReader() method of the appropriate class.
We have also looked at ADO.NET DataSets and investigated the difference between strongly Typed
Datasets and Untyped DataSets. Strongly Typed Datasets provide typed support to our data structure. The typing
also allows Visual Studio 2005 to provide intellisense support whilst we program. This helps to avoid errors with
names during development.
An ADO.NET DataSet is a collection of tables and information about the relationships between tables. Both
Typed and Untyped DataSets provide a disconnected view of a data source. ADO.NET DataSets enable us to
store data from multiple data sources. We can create relationships between the tables in a DataSet, even though
the relationships might not exist between the tables in the data sources. In addition, We can create different data
views from the data contained within the DataSets.
With the introduction of Visual Studio 2005 and MS SQL Server 2005 we can now execute .NET code
within MS SQL Server 2005. This allows for more flexibility in data manipulation within the database.
256
The Complete Reference To Professional SOA with Visual Studio 2005
Chapter 7 Accessing
Manipulating XML with .NET
XML is central to data exchange between applications in the .NET Framework. We need to know the XML
Document Object Model (DOM) and how to access XML data in our applications. The Microsoft .NET
Framework version 2.0 includes many design and functionality changes to the XML Manipulation. The changes
will provide better efficiency.
In this chapter will be learning how to read and write data to and from an XML document. We will also be
looking at performing operations on XML documents using XPATH. We will also learn how to validate a XML
document against its XML Schema (XSD) using .NET. Lastly we will look at how to populate a DataSet with
data from a XML file and how to write data back into the XML file.
257
The Complete Reference To Professional SOA with Visual Studio 2005
</CD>
</CATALOG>
In the above example the XML code contains CD information for a record catalog information for three
CDs. The XML document is a well-formed XML document. A well-formed XML document contains an end tag
for every begin tag. For example, for every < CD > tag, a </ CD > tag should be present. A well-formed XML
document can have an associated document type definition (DTD) or an XML Schema that describes the data
and the relationship between the data within an XML document.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="ARTIST">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="CATALOG">
<xs:complexType>
<xs:sequence>
<xs:element ref="CD" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="CD">
<xs:complexType>
<xs:sequence>
<xs:element ref="TITLE" />
<xs:element ref="ARTIST" />
<xs:element ref="COUNTRY" />
<xs:element ref="COMPANY" />
<xs:element ref="PRICE" />
<xs:element ref="YEAR" />
258
The Complete Reference To Professional SOA with Visual Studio 2005
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="COMPANY">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="COUNTRY">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="PRICE">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="TITLE">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="YEAR">
<xs:complexType mixed="true" />
</xs:element>
</xs:schema>
The DTD similar to a XML Schema specifies the syntax of an application of XML. DTDs have a syntax that
is different from XML. The difference between DTD and XML Schema is that XML Schema uses XML
document syntax. Even though using XML doesn’t necessarily improve the quality of the description. However
it does improve the extensibility. Because of this XML Schemas can have a richer and more complex internal
structure than that of DTD.
Both DTD and XML Schema can be used to validate XML documents.
Using the DOM an XML document is read into memory and a tree of nodes is formed. The node types for
the nodes are decided as they are created. There are several kinds of node types that had been defined by the
World Wide Web Consortium (W3C) for DOM. The following table lists the node types, the object assigned to
that node type, and a short description of each.
Table 7-1. The XML DOM contains different types of nodes. The table below contains the most commonly used nodes and
their descriptions.
259
The Complete Reference To Professional SOA with Visual Studio 2005
There is also another of way of reading XML documents that is using Simple API for XML (SAX) to read
data from XML documents. The difference between SAX and DOM is that SAX does not load the entire XML
document into memory. The content is rather read in a sequential manner. Using SAX we can program events to
occur as the XML document is being read. Since SAX does not load the XML document into memory, it is more
efficient for reading larger XML documents. However the limitation of using SAX is that SAX does not
maintain a structure that can be used in more complex operations. We also can not use SAX when we need to
modify the XML document.
We can also read XML documents using .NET Framework’s XmlReader class. The XmlReader class
provides forward only and read only access to XML documents. Unlike the DOM the XmlReader does not load
the XML document into memory.
In the DOM the XML document is structured. The document is represented by the XmlDocument object.
The XmlDocument object is part of the System.Xml namespace.
The XmlDocument object can be used to load and save XML documents. Using the XmlDocument object will provide
us with access to all the nodes in the document. The following example demonstrates using XmlDocument to load a
XML document.
Listing 7-4. Demonstrates loading a XML document using XmlDocument using Visual C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
namespace CSLoadDOM
{
class Program
{
static void Main(string[] args)
{
XmlDocument myDocument = new XmlDocument();
myDocument.Load("cd_catalog.xml");
Console.WriteLine(myDocument.InnerXml.ToString());
Console.ReadLine();
}
}
}
Listing 7-5. Demonstrates loading a XML document using XmlDocument using Visual Basic .NET
Imports System.Xml
260
The Complete Reference To Professional SOA with Visual Studio 2005
Module Program
Sub Main()
Dim myDocument As XmlDocument = New XmlDocument
myDocument.Load("cd_catalog.xml")
Console.WriteLine(myDocument.InnerXml.ToString)
Console.ReadLine()
End Sub
End Module
This code snippet uses the XmlDocument object and loads the XML document into the variable
myDocument (the cd_catalog.xml file is shown in Listing 7-1). There are two ways of loading the XML
document into a variable. We can use the Load method and specify the file name as the parameter. Sometimes
the XML content is not always readily available in a file. Alternatively, we can use the LoadXml method and
specify the XML data as the parameter. The following code snippet shows the usage of the LoadXml method.
Listing 7-6. Demonstrates loading an XML document from a string using Visual C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
namespace CSLoadDOM2
{
class Program
{
static void Main(string[] args)
{
XmlDocument myDocument = new XmlDocument();
myDocument.LoadXml(
@"<?xml version=""1.0"" encoding=""ISO-8859-1\""?>
<CATALOG>
<CD>
<TITLE>Empire Burlesque</TITLE>
<ARTIST>Bob Dylan</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>Columbia</COMPANY>
<PRICE>10.90</PRICE>
<YEAR>1985</YEAR>
</CD>
<CD>
<TITLE>Hide your heart</TITLE>
<ARTIST>Bonnie Tyler</ARTIST>
<COUNTRY>UK</COUNTRY>
<COMPANY>CBS Records</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1988</YEAR>
</CD>
<CD>
<TITLE>Greatest Hits</TITLE>
<ARTIST>Dolly Parton</ARTIST>
<COUNTRY>USA</COUNTRY>
261
The Complete Reference To Professional SOA with Visual Studio 2005
<COMPANY>RCA</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1982</YEAR>
</CD>
</CATALOG>");
Console.WriteLine(myDocument.InnerXml.ToString());
Console.ReadLine();
}
}
}
Listing 7-7. Demonstrates loading an XML document from a string using Visual Basic .NET
Imports System.Xml
Module Module1
Sub Main()
Dim myDocument As XmlDocument = New XmlDocument
myDocument.LoadXml("<?xml version=""1.0"" encoding=""ISO-8859-1""?> " & _
"<CATALOG> "&_
" <CD> "&_
" <TITLE>Empire Burlesque</TITLE> "&_
" <ARTIST>Bob Dylan</ARTIST> "&_
" <COUNTRY>USA</COUNTRY> "&_
" <COMPANY>Columbia</COMPANY> "&_
" <PRICE>10.90</PRICE> "&_
" <YEAR>1985</YEAR> "&_
" </CD> "&_
" <CD> "&_
" <TITLE>Hide your heart</TITLE> "&_
" <ARTIST>Bonnie Tyler</ARTIST> "&_
" <COUNTRY>UK</COUNTRY> "&_
" <COMPANY>CBS Records</COMPANY> "&_
" <PRICE>9.90</PRICE> "&_
" <YEAR>1988</YEAR> "&_
" </CD> "&_
" <CD> "&_
" <TITLE>Greatest Hits</TITLE> "&_
" <ARTIST>Dolly Parton</ARTIST> "&_
" <COUNTRY>USA</COUNTRY> "&_
" <COMPANY>RCA</COMPANY> "&_
" <PRICE>9.90</PRICE> "&_
" <YEAR>1982</YEAR> "&_
" </CD> "&_
"</CATALOG> ")
Console.WriteLine(myDocument.InnerXml.ToString)
Console.ReadLine()
End Sub
End Module
The XmlDocument object can also be used to write XML data into files. To write XML data, you can use
the Save method. The following example shows how to use XmlDocument Save method listing 7-8.
262
The Complete Reference To Professional SOA with Visual Studio 2005
Listing 7-8. Writing an XML document from a string of XML using Visual C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
namespace CSSaveDOM
{
class Program
{
static void Main(string[] args)
{
XmlDocument myDocument = new XmlDocument();
myDocument.LoadXml(
@"<?xml version=""1.0"" encoding=""utf-8"" ?>
<CATALOG>
<CD>
<TITLE>Empire Burlesque</TITLE>
<ARTIST>Bob Dylan</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>Columbia</COMPANY>
<PRICE>10.90</PRICE>
<YEAR>1985</YEAR>
</CD>
<CD>
<TITLE>Hide your heart</TITLE>
<ARTIST>Bonnie Tyler</ARTIST>
<COUNTRY>UK</COUNTRY>
<COMPANY>CBS Records</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1988</YEAR>
</CD>
<CD>
<TITLE>Greatest Hits</TITLE>
<ARTIST>Dolly Parton</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>RCA</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1982</YEAR>
</CD>
</CATALOG>");
myDocument.Save("Catalgue.xml");
Console.WriteLine("Document had been saved.");
Console.WriteLine(myDocument.InnerXml.ToString());
Console.ReadLine();
}
}
}
Listing 7-9. Writing an XML document from a string of XML usingVisual Basic .NET
Imports System.Xml
263
The Complete Reference To Professional SOA with Visual Studio 2005
Module Module1
Sub Main()
Dim myDocument As XmlDocument = New XmlDocument
myDocument.LoadXml("<?xml version=""1.0"" encoding=""utf-8"" ?> " & _
"<CATALOG> "&_
" <CD> "&_
" <TITLE>Empire Burlesque</TITLE> "&_
" <ARTIST>Bob Dylan</ARTIST> "&_
" <COUNTRY>USA</COUNTRY> "&_
" <COMPANY>Columbia</COMPANY> "&_
" <PRICE>10.90</PRICE> "&_
" <YEAR>1985</YEAR> "&_
" </CD> "&_
" <CD> "&_
" <TITLE>Hide your heart</TITLE> "&_
" <ARTIST>Bonnie Tyler</ARTIST> "&_
" <COUNTRY>UK</COUNTRY> "&_
" <COMPANY>CBS Records</COMPANY> "&_
" <PRICE>9.90</PRICE> "&_
" <YEAR>1988</YEAR> "&_
" </CD> "&_
" <CD> "&_
" <TITLE>Greatest Hits</TITLE> "&_
" <ARTIST>Dolly Parton</ARTIST> "&_
" <COUNTRY>USA</COUNTRY> "&_
" <COMPANY>RCA</COMPANY> "&_
" <PRICE>9.90</PRICE> "&_
" <YEAR>1982</YEAR> "&_
" </CD> "&_
"</CATALOG> ")
myDocument.Save("Catalgue.xml")
Console.WriteLine("Document had been saved.")
Console.WriteLine(myDocument.InnerXml.ToString)
Console.ReadLine()
End Sub
End Module
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
namespace CSXmlParser
{
264
The Complete Reference To Professional SOA with Visual Studio 2005
class Program
{
static void Main(string[] args)
{
try
{
XmlDocument myDocument = new XmlDocument();
myDocument.Load("cd_catalog.xml");
int i;
int count;
count = 0;
i = 1;
XmlNode node = myDocument.ChildNodes[1];
foreach (XmlNode node1 in node.ChildNodes)
{
Console.WriteLine("\n");
Console.WriteLine(
"The elements under node number: {0}", i);
Console.WriteLine(
"------------------------------------------");
foreach (XmlNode node2 in node1.ChildNodes)
{
Console.WriteLine(
myDocument.DocumentElement.FirstChild.
ChildNodes[count].Name + ": " +
node2.FirstChild.Value);
count = count + 1;
}
i = i + 1;
count = 0;
}
Console.WriteLine("\n");
Console.WriteLine("Press <Enter> to quit...");
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.ReadLine();
}
}
}
}
Listing 7-11. Demonstrates Parsing an XML document using Visual Basic .NET
Imports System.Xml
Module Module1
Sub Main()
265
The Complete Reference To Professional SOA with Visual Studio 2005
Try
Dim myDocument As XmlDocument = New XmlDocument
myDocument.Load("cd_catalog.xml")
Dim i As Integer
Dim count As Integer
count = 0
i=1
Dim node As XmlNode = myDocument.ChildNodes(1)
For Each node1 As XmlNode In node.ChildNodes
Console.WriteLine("")
Console.WriteLine(
"The elements under node number: {0}", i)
Console.WriteLine(
"------------------------------------------")
For Each node2 As XmlNode In node1.ChildNodes
Console.WriteLine(myDocument.DocumentElement _
.FirstChild.ChildNodes(count).Name + ": " + _
node2.FirstChild.Value)
count = count + 1
Next
i=i+1
count = 0
Next
Console.WriteLine("")
Console.WriteLine("Press <Enter> to quit...")
Console.ReadLine()
Catch e As Exception
Console.WriteLine(e.Message)
Console.ReadLine()
End Try
End Sub
End Module
In the code above we’re accessing the first child node in the XML through myDocument.ChildNodes[1].
Then once we have the node object we can iterate through the child nodes and access the node’s Name
myDocument.DocumentElement.FirstChild.ChildNodes[count].Name as well as its Value node2.FirstChild.Value.
266
The Complete Reference To Professional SOA with Visual Studio 2005
Methods Description
Methods Description
267
The Complete Reference To Professional SOA with Visual Studio 2005
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> ")
268
The Complete Reference To Professional SOA with Visual Studio 2005
End Sub
End Module
The following code shows how to read data from an XML file using the XmlTextReader class.
Listing 7-14. Reading an XML document from file using XMLTextReader. We then iterate through the different node types
using Visual C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
namespace CSXMLReader3
{
class Program
{
static void Main(string[] args)
{
XmlTextReader reader = new XmlTextReader("cd_catalog.xml");
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
Console.Write("<" + reader.Name);
while (reader.MoveToNextAttribute())
{
Console.Write(" " + reader.Name + "='" +
reader.Value + "'");
}
Console.Write(">");
if (reader.HasAttributes)
{
while (reader.MoveToNextAttribute())
Console.Write(" " + reader.Value + " ");
}
break;
case XmlNodeType.Text:
Console.Write(reader.Value);
break;
case XmlNodeType.EndElement:
Console.WriteLine(("</" + reader.Name + ">"));
break;
}
}
Console.ReadLine();
}
}
}
269
The Complete Reference To Professional SOA with Visual Studio 2005
Listing 7-15. Reading an XML document from file using XMLTextReader. We then iterate through the different node types
using Visual Basic .NET
Imports System.Xml
Module Module1
Sub Main()
Dim reader As New XmlTextReader("cd_catalog.xml")
While reader.Read()
Select Case reader.NodeType
Case XmlNodeType.Element
Console.Write("<" + reader.Name)
While (reader.MoveToNextAttribute())
Console.Write(" " & reader.Name & "='" & _
reader.Value & "'")
End While
Console.Write(">")
If reader.HasAttributes Then
While reader.MoveToNextAttribute
Console.Write(" " & reader.Value & " ")
End While
End If
Case XmlNodeType.Text
Console.Write(reader.Value)
Case XmlNodeType.EndElement
Console.WriteLine(("</" & reader.Name & ">"))
End Select
End While
Console.ReadLine()
End Sub
End Module
In the code above we’re using XmlTextReader to read in our cd_catalog.xml file. We’re reading one row at a
time by examining reader.NodeType we can determine if the XmlTextReader is currently reading an element
XmlNodeType.Element or the text between the elements XmlNodeType.Text or an end element tag
XmlNodeType.EndElement.
270
The Complete Reference To Professional SOA with Visual Studio 2005
The XmlTextWriter class has the following commonly used properties and methods that can be used to save
XML to file or stream.
Methods Description
WriteState Gets the state of the writer. The valid values for WriteState
include Start, Element, Attribute, Content, Prolog, and Closed.
Methods Description
WriteStartDocument Writes the following XML declaration to the start of the document: <?xml
version="1.0" ?>
271
The Complete Reference To Professional SOA with Visual Studio 2005
The following code shows how we can use XmlTextWriter to write XML to a file.
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();
}
}
}
272
The Complete Reference To Professional SOA with Visual Studio 2005
Listing 7-17. Writing XML using XmlTextWriter with Visual Basic .NET
Imports System.Xml
Module Module1
Sub Main()
Dim textWriter As XmlTextWriter =
New XmlTextWriter("catalog_out.xml",
System.Text.Encoding.UTF8)
textWriter.Formatting = Formatting.Indented
textWriter.WriteStartDocument(False)
textWriter.WriteDocType("CATALOG", Nothing, Nothing, Nothing)
textWriter.WriteComment("XML Catalog output")
textWriter.WriteStartElement("CATALOG")
textWriter.WriteStartElement("CD", Nothing)
textWriter.WriteElementString("TITLE", "Empire Burlesque")
textWriter.WriteElementString("ARTIST", "Bob Dylan")
textWriter.WriteElementString("COUNTRY", "USA")
textWriter.WriteElementString("COMPANY", "Columbia")
textWriter.WriteElementString("PRICE", "10.90")
textWriter.WriteElementString("YEAR", "1985")
textWriter.WriteEndElement()
textWriter.WriteEndElement()
textWriter.Flush()
textWriter.Close()
Console.WriteLine("Press <Enter> to exit.")
Console.Read()
End Sub
End Module
In listing 7-16 and listing 7-17 we’re writing out a xml document of the CD catalog. We specify a encoding
type of UTF8 System.Text.Encoding.UTF8 then we ask the text writer to take care of our Xml indenting
Formatting.Indented. Following that we create an Xml DOCTYPE of CATALOG by using WriteDocType. Using
WriteStartElement and WriteEndElement we can write our XML document’s start and end tags. In between the
Xml document’s start and end tags we use WriteElementString to insert the xml elements.
XmlTextWriter also provides WriteComment which allows us to embed an Xml comment anywhere within
the document.
The above xml document shows the output from listing 7-16 and listing 7-17.
273
The Complete Reference To Professional SOA with Visual Studio 2005
XPathNavigator
In the previous section we had examined how to read and write XML Documents. In this section we will
examine how to use XPath to access a node or a set of nodes. The .NET Framework provides the
XPathNavigator class which contains the methods that we use to perform XPath queries on an XML document.
XPath allows us to perform specific operations on a XML document through specific XPath expressions.
These operations can manipulate strings, perform calculations and check for conditions. XPath treats a XML
document as a tree that contains different types nodes of elements and attributes. We can create XPath
expressions that identify specific nodes in the document based on their type, name and value. In addition, XPath
expressions can identify relationships between nodes in a document.
XPath
To execute XPath queries we need to first select a set of nodes to perform the XPath queries against. The Select
method provided by the XPathNavigator object is used to select a set of nodes. The Select method is used to
select a particular node which then returns an object of XPathNodeIterator class. We can use then use the
XPathNodeIterator object to iterate through the selected nodes. In addition there are also several other select
methods that can be used these are SelectChildren, SelectAncestors, SelectDecendents. The following example
demonstrates how to iterate a set of nodes using the the XPathNavigator object.
Listing 7-18. Demonstrates how to use XPath query to select a node usingVisual C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.XPath;
namespace CSXMLXpath
{
class Program
{
static void Main(string[] args)
{
XPathDocument Doc = new XPathDocument("cd_catalog.xml");
XPathNavigator navigator = Doc.CreateNavigator();
XPathNodeIterator iterator = navigator.Select("/CATALOG/CD/TITLE");
while (iterator.MoveNext())
{
Console.WriteLine(iterator.Current.Name + " -> " +
iterator.Current.Value
);
}
Console.ReadLine();
}
}
}
Listing 7-19. Demonstrates how to use XPath query to select a node using Visual Basic .NET
Imports System.Xml.XPath
Module Module1
274
The Complete Reference To Professional SOA with Visual Studio 2005
Sub Main()
Dim Doc As XPathDocument = New XPathDocument("cd_catalog.xml")
Dim navigator As XPathNavigator = Doc.CreateNavigator
Dim iterator As XPathNodeIterator = _
navigator.Select("/CATALOG/CD/TITLE")
While iterator.MoveNext
Console.WriteLine(iterator.Current.Name + " -> " + _
iterator.Current.Value)
End While
Console.ReadLine()
End Sub
End Module
Figure 7-2. shows the output from listing 7-18 and listing 7-19
Aside from the Select method, the XPathNavigator class also provide additional methods which can be used
to select a set of nodes. These methods allow us to retrieve nodes faster than retrieving nodes using the
corresponding XPath query. The optimized methods are:
* SelectChildren, which selects all the child nodes of the current node that match the selection criteria.
* SelectAncestors, which selects all the ancestor nodes of the current node that have a matching
XPathNodeType.
* SelectDescendants - which selects all the descendant nodes of the current node that match the selection criteria.
* and IsDescendant - Determines whether the specified XPathNavigator is a descendant of the current
XPathNavigator.
Calling the above methods will not affect the state or position of the XPathNavigator object. All the methods
return an XPathNodeIterator object with exception of IsDescendant which returns a Boolean value.
275
The Complete Reference To Professional SOA with Visual Studio 2005
Method Description
MoveTo This method allows us to move the XPathNavigator object to another node and make
it the current position. The MoveTo method returns a Boolean value to indicate the
success or failure of the movement.
MoveToNext This method allows us to move the XPathNavigator object to the next sibling of the
current node.
MoveToPrevious This method allows us to move the XPathNavigator object to the previous sibling of
the current node.
MoveToFirst This method allows us to move the XPathNavigator object to the first sibling of the
current node.
MoveToFirstChild This method allows us to move the XPathNavigator object to the first child of the
current node. We can use the MoveToFirstChild method only when the current node
is the root node or is a node that has child nodes. If no child nodes exist then a
Boolean value is returned indicating that the move had failed.
MoveToParent This method allows us to move the XPathNavigator object to the parent node of the
current node. We cannot call the MoveToParent method when the root node is the
current node because the root node does not have a parent node.
MoveToRoot This method allows us to move the XPathNavigator object to the root node.
MoveToId This method allows us to move the XPathNavigator object to the node that has an ID
attribute. You need to specify the ID of the node to which you want the
XPathNavigator to move.
The XPath expression needs to be compiled first using the Compile method to convert the string
representation to an XPathExpression object. Compiling allow us to cache the expression for improved
performance and it also allows for verification to ensure the expression is valid. Once the expression is compiled
we can pass in the compiled XPath expression object and use the Evaluate method. The Evaluate method takes
the XPath expression and executes the expression against the XML document. It returns a typed result. We can
use Evaluate to perform calculations. In the following example we have created an expression to calculate the
sum of all prices in an XML document using Evaluate to execute.
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.XPath;
namespace CSXMLXpath2
{
class Program
{
static void Main(string[] args)
276
The Complete Reference To Professional SOA with Visual Studio 2005
{
XmlDocument XPathDocument = new XmlDocument();
XPathDocument.Load("cd_catalog.xml");
XPathNavigator navigator =
XPathDocument.CreateNavigator();
XPathExpression XPathExpr =
navigator.Compile("sum(//PRICE/text())");
Console.WriteLine(navigator.Evaluate(XPathExpr));
Console.ReadLine();
}
}
}
Listing 7-21. Demonstrates executing an XPath expression using Visual Basic .NET
Imports System.Xml
Imports System.Xml.XPath
Module Module1
Sub Main()
Dim XPathDocument As XmlDocument = New XmlDocument
XPathDocument.Load("cd_catalog.xml")
Dim navigator As XPathNavigator =
XPathDocument.CreateNavigator
Dim XPathExpr As XPathExpression =
navigator.Compile("sum(//PRICE/text())")
Console.WriteLine(navigator.Evaluate(XPathExpr))
Console.ReadLine()
End Sub
End Module
In listing 7-20 and listing 7-21 we load the cd catalog xml document into XPathDocument. We then ask it to
calculate the sum of all prices for the XML Document by compiling and evaluating through the query
sum(//PRICE/text()).
277
The Complete Reference To Professional SOA with Visual Studio 2005
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="ARTIST">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="CATALOG">
<xs:complexType>
<xs:sequence>
<xs:element ref="CD" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="CD">
<xs:complexType>
<xs:sequence>
<xs:element ref="TITLE" />
<xs:element ref="ARTIST" />
<xs:element ref="COUNTRY" />
<xs:element ref="COMPANY" />
<xs:element ref="PRICE" />
<xs:element ref="YEAR" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="COMPANY">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="COUNTRY">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="PRICE">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="TITLE">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="YEAR">
<xs:complexType mixed="true" />
</xs:element>
</xs:schema>
We can also programmatically create schemas using the Schema Object Model (SOM). SOM part of the
System.Xml.Schema namespace consists of a set of classes that allow us to read and manipulate schema
278
The Complete Reference To Professional SOA with Visual Studio 2005
definitions. When we manipulate the schema, it resides in memory. We need to validate and compile the schema
before we can write it to a file.
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.IO;
namespace CSXMLXsd
{
class Program
{
static void Main(string[] args)
{
try
{
XmlTextReader reader =
new XmlTextReader("cd_catalog.xsd");
XmlSchema myschema = XmlSchema.Read(reader, null);
myschema.Write(Console.Out);
Console.WriteLine("Press <Enter> to exit.");
Console.Read();
FileStream file = new FileStream("New.xsd",
FileMode.Create, FileAccess.ReadWrite);
XmlTextWriter xwriter = new XmlTextWriter(file,
new UTF8Encoding());
xwriter.Formatting = Formatting.Indented;
myschema.Write(xwriter);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
}
Listing 7-24. Demonstrates creating a Schema programmtically using Visual Basic .NET
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Xml
Imports System.Xml.Schema
Imports System.IO
Module Module1
Sub Main()
279
The Complete Reference To Professional SOA with Visual Studio 2005
Try
Dim reader As XmlTextReader =
New XmlTextReader("cd_catalog.xsd")
Dim myschema As XmlSchema =
XmlSchema.Read(reader, Nothing)
myschema.Write(Console.Out)
Console.WriteLine("Press <Enter> to exit.")
Console.Read()
Dim file As FileStream = _
New FileStream("New.xsd",
FileMode.Create, FileAccess.ReadWrite)
Dim xwriter As XmlTextWriter =
New XmlTextWriter(file, New UTF8Encoding)
xwriter.Formatting = Formatting.Indented
myschema.Write(xwriter)
Catch e As Exception
Console.WriteLine(e)
End Try
End Sub
End Module
XML Validation
We can ensure that the XML documents that we create are well formed. Any XML parser can read a well-
formed XML document. We should also ensure that the XML document matches its schema or conforms to the
constraints defined by its DTD. For example, if we specify a specific data type or a specific range for a record
then we need to ensure that the XML document must conform to the condition or it will be considered invalid.
We can ensure the validity of a XML document by using the XmlValidatingReader class. The
XmlValidatingReader class is a derived class of the XmlReader class and adds validation support to the
XmlTextReader class. The XmlValidatingReader class provides the DTD, XML-Data Reduced (XDR), and XSD
schema validation services that allow us to validate an XML document or a fragment of an XML document. The
XmlValidatingReader class takes XmlTextReader as the input and applies the properties that we specify in the
XmlTextReader class.
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Schema;
namespace CSXMLValidate
{
class Program
{
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create("cd_catalog.xml");
280
The Complete Reference To Professional SOA with Visual Studio 2005
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.
281
The Complete Reference To Professional SOA with Visual Studio 2005
<YEAR>1982</YEAR>
</CD>
</CATALOG>
In our CD catalog schema file we have not catered for this new SubTitle element as a result it will fail the
validation.
Listing 7-28. cd_catalog.xsd schema file for the cd_catalog Xml documents
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="ARTIST">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="CATALOG">
<xs:complexType>
<xs:sequence>
<xs:element ref="CD" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="CD">
<xs:complexType>
<xs:sequence>
<xs:element ref="TITLE" maxOccurs="1" />
<xs:element ref="ARTIST" minOccurs="1" />
<xs:element ref="COUNTRY" />
<xs:element ref="COMPANY" />
<xs:element ref="PRICE" />
<xs:element ref="YEAR" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="COMPANY">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="COUNTRY">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="PRICE">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="TITLE" nillable="false">
<xs:complexType mixed="true" />
</xs:element>
<xs:element name="YEAR">
<xs:complexType mixed="true" />
</xs:element>
</xs:schema>
Listing 7-29. Validating the XML document against the Schema using Visual C#
using System;
using System.Collections.Generic;
282
The Complete Reference To Professional SOA with Visual Studio 2005
using System.Text;
using System.Xml;
using System.Xml.Schema;
namespace CSXMLValidate2
{
class Program
{
static void Main(string[] args)
{
// Create the XmlSchemaSet class.
XmlSchemaSet sc = new XmlSchemaSet();
}
}
Listing 7-30. Validating the XML document against the Schema using Visual Basic .NET
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Xml
283
The Complete Reference To Professional SOA with Visual Studio 2005
Imports System.Xml.Schema
Module Module1
Sub Main()
Dim sc As XmlSchemaSet = New XmlSchemaSet
sc.Add("urn:cd_Catalog-schema", "cd_catalog.xsd")
Dim settings As XmlReaderSettings = New XmlReaderSettings
settings.ValidationType = ValidationType.Schema
settings.Schemas = sc
AddHandler settings.ValidationEventHandler, AddressOf ValidationCallBack
Dim reader As XmlReader = XmlReader.Create("cd_catalog_fail.xml", settings)
While reader.Read
End While
Console.WriteLine("__________________")
Console.WriteLine("Parse complete!")
Console.ReadLine()
End Sub
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.
284
The Complete Reference To Professional SOA with Visual Studio 2005
Method Description
GetXml This method allows us to retrieve the XML representation of the data stored in a
DataSet in a string variable.
This method allows us to retrieve the XSD schema for the XML representation of
GetXmlSchema
the data stored in the DataSet.
InferXmlSchema This method allows us to extrapolate the structure of data in the DataSet by using
the schema provided in the TextReader, XMLReader, or Stream object.
ReadXml This method reads the XML data and schema into the DataSet.
ReadXmlSchema This method allows us to read XML Schema into the DataSet.
WriteXml This method allows us to write the data of the DataSet into an XML file.
WriteXmlSchema This method allows us to write the data in the DataSet into an XML Schema.
In ADO.NET we have the option to save a DataSet as a XML file and also save its XML schema to a file.
While vice-versa we can also read an XML schema back into a DataSet and load XML file as data into the
DataSet.
To save the content of the DataSet into an XML document we use the WriteXml() method. While to save its
schema we would use the WriteXmlSchema() method.
NOTE: The connectionstring used in each of these examples may vary depending on your Sql Server Database setup.
Listing 7-31. Writing the data and schema to XML files using Visual C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
namespace csDataSet
{
class Program
{
static void Main(string[] args)
{
SqlConnection sqlcon = new SqlConnection(
"Data Source=DEVSERVER\\;Initial Catalog=AdventureWorks;"+
"Integrated Security=True");
285
The Complete Reference To Professional SOA with Visual Studio 2005
sqlcon.Open();
SqlDataAdapter sqladapter = new SqlDataAdapter(
"select * from HumanResources.Employee",
sqlcon);
DataSet employeeDS = new DataSet();
sqladapter.Fill(employeeDS, "EmployeeTable");
int rowcnt = employeeDS.Tables["EmployeeTable"].Rows.Count;
employeeDS.WriteXml("EmployeeTable.xml");
employeeDS.WriteXmlSchema("EmployeeTableSchema.xml");
Console.WriteLine(rowcnt.ToString());
Console.ReadLine();
sqlcon.Close();
}
}
}
Listing 7-32. Writing the data and schema to XML files using Visual Basic .NET
Imports System.Data
Imports System.Data.SqlClient
Module Module1
Sub Main()
Dim sqlcon As SqlConnection = New SqlConnection( _
"Data Source=DEVSERVER\;Initial Catalog=AdventureWorks;" + _
"Integrated Security=True")
sqlcon.Open()
Dim sqladapter As SqlDataAdapter = New SqlDataAdapter( _
"select * from HumanResources.Employee", sqlcon)
Dim employeeDS As DataSet = New DataSet
sqladapter.Fill(employeeDS, "EmployeeTable")
Dim rowcnt As Integer = _
employeeDS.Tables("EmployeeTable").Rows.Count
employeeDS.WriteXml("EmployeeTable.xml")
employeeDS.WriteXmlSchema("EmployeeTableSchema.xml")
Console.WriteLine(rowcnt.ToString)
Console.ReadLine()
sqlcon.Close()
End Sub
End Module
In the listing above we first retrieve the data from the Employee table then will use Fill to enter the data into
the dataset. Once the DataSet is filled we can write out the data contained in the DataSet into the XML document
using the WriteXml() method, we can then write out the Schema using WriteXmlSchema().
286
The Complete Reference To Professional SOA with Visual Studio 2005
<NationalIDNumber>14417807</NationalIDNumber>
<ContactID>1209</ContactID>
<LoginID>adventure-works\guy1</LoginID>
<ManagerID>16</ManagerID>
<Title>Production Technician - WC60</Title>
<BirthDate>1972-05-15T00:00:00+10:00</BirthDate>
<MaritalStatus>M</MaritalStatus>
<Gender>M</Gender>
<HireDate>1996-07-31T00:00:00+10:00</HireDate>
<SalariedFlag>false</SalariedFlag>
<VacationHours>21</VacationHours>
<SickLeaveHours>30</SickLeaveHours>
<CurrentFlag>true</CurrentFlag>
<rowguid>aae1d04a-c237-4974-b4d5-935247737718</rowguid>
<ModifiedDate>2004-07-31T00:00:00+10:00</ModifiedDate>
</EmployeeTable>
.
.
.
</NewDataSet>
287
The Complete Reference To Professional SOA with Visual Studio 2005
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
We can also read the data back into the DataSet by using ReadXml() method. The schema can also be read
back using ReadXmlSchema().
Listing 7-37. Reading the the schema and the XML document containing data back into the DataSet using Visual C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
namespace CSDataSetRead
{
class Program
{
static void Main(string[] args)
{
DataSet employeeDS = new DataSet();
employeeDS.ReadXmlSchema("EmployeeTableSchema.xml");
employeeDS.ReadXml("EmployeeTable.xml");
int rowcnt = employeeDS.Tables["EmployeeTable"].Rows.Count;
Console.WriteLine(rowcnt.ToString());
Console.ReadLine();
}
}
}
Listing 7-38. Reading the the schema and the XML document containing data back into the DataSet using Visual Basic .NET
Imports System.Data
Imports System.Data.SqlClient
288
The Complete Reference To Professional SOA with Visual Studio 2005
Module Module1
Sub Main()
Dim employeeDS As DataSet = New DataSet
employeeDS.ReadXmlSchema("EmployeeTableSchema.xml")
employeeDS.ReadXml("EmployeeTable.xml")
Dim rowcnt As Integer = _
employeeDS.Tables("EmployeeTable").Rows.Count
Console.WriteLine(rowcnt.ToString)
Console.ReadLine()
End Sub
End Module
Summary
In this chapter we have examined how to access and manipulate XML document using .NET. As all modern
systems today can understand and work with XML document it is therefore important part of our development
towards an interoperable architecture.
We have looked XML DOM. XML DOM is a representation of the XML document in memory. The DOM
class allows us to read and write, and manipulate an XML document. The DOM class contains a set of libraries
which allow us to navigate through the XML document to the relevant information.
We have also learnt to write an XML Parser in .NET using XmlDocument. We have looked at Reading and
Writing XML using XmlTextReader and XmlTextWriter. Both classes provide fast access to XML data.
XmlTextReader class should be used when we don’t need to read the entire document into memory. While the
XmlTextWriter a derived class of XmlWriter, allows us to create XML streams and write data to well-formed
XML documents.
We have also examine utilizing XPath queries in our XML documents. In our XML document we can use
XPath to access a particular node. We can also perform XPath queries on an XML document within .NET.
We have looked at validating an XML document through using a XML Schema. This ensures that the XML
document conforms to its schema.
Lastly we looked at the XML options that the ADO.NET DataSet provided which allowed us to save a
DataSet and its schema as XML. Vice versa we could also read the XML schema and the XML document back
into the DataSet.
289
The Complete Reference To Professional SOA with Visual Studio 2005
.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.
[Serializable]
public class SerializableClass
{
private string _name;
290
The Complete Reference To Professional SOA with Visual Studio 2005
Listing 8-2. Enabling serializable for SerializableClass using Visual Basic .NET
<Serializable()> _
Public Class SerializableClass
Private _name As String
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;
Listing 8-4. disable serialization for ZipCode using NonSerialized attribute in Visual Basic .NET
291
The Complete Reference To Professional SOA with Visual Studio 2005
Return _zipCode
End Get
Set(ByVal value As String)
_zipCode = value
End Set
End Property
Serialization Formatter
.NET offers us two forms of serialization, Binary and SOAP. Binary, form of serialization is more compact
and provides as an excellent model performance wise. The SOAP format allows us to serialize data into a
readable form. This is achieved through the use of a formatter. The formatter helps to determine the serialized
format for the objects that we serialize.
To serialize into a Binary format we need to use the .NET BinaryFormatter class which is a part of the
System.Runtime.Serialization.Formatters.Binary namespace. The BinaryFormatter provides ability to encode
objects into a compact binary format. We need to provide a stream containing the objects to serialize to the
BinaryFormatter see listing 8-5 and listing 8-6 below.
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;
class Program
{
static void Main(string[] args)
{
292
The Complete Reference To Professional SOA with Visual Studio 2005
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
293
The Complete Reference To Professional SOA with Visual Studio 2005
Class Program
End Class
End Namespace
In the above example we have created a SerializableClass which includes the Serializable attribute. This
allows the class to be serialized. We then set values for the SerializableClass object which we then pass to the
BinaryFormatter as well as an open stream to a file which we will be writing the result to. Using the Serialize
method the BinaryFormatter then saves the values into the file SerializedObj.bin.
294
The Complete Reference To Professional SOA with Visual Studio 2005
To deserialize the SerializeObj.bin file we use the deserialize method from the BinaryFormatter object.
After the object has been deserialized we need to cast the object back to a particular type before we can access its
value.
The result from the deserialization can be seen in the image figure 8-1 below.
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.
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.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Soap;
295
The Complete Reference To Professional SOA with Visual Studio 2005
namespace CSSOAPFormatter
{
[Serializable]
public class SerializableClass
{
private string _name;
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();
296
The Complete Reference To Professional SOA with Visual Studio 2005
SerializableClass obj =
(SerializableClass)formatter.Deserialize(reader);
reader.Close();
return obj;
}
}
}
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
Class Program
297
The Complete Reference To Professional SOA with Visual Studio 2005
End Sub
<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<a1:SerializableClass id="ref-1"
xmlns:a1="http://schemas.microsoft.com/clr/nsassem/VBSOAPFormatter
.VBSOAPFormatter/VBSOAPFormatter%2C%20Version%3D1.0.0.0%2C%20Culture%3
Dneutral%2C%20PublicKeyToken%3Dnull">
<_name id="ref-3">John Doe</_name>
<_zipCode>2000</_zipCode>
</a1:SerializableClass>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
In the listing above we can see that the SerializedObj.soap contains the serialized values of the object in a
SOAP format.
298
The Complete Reference To Professional SOA with Visual Studio 2005
XML Serialization
In the previous section we have examined how to serialize objects into binary files and soap files. There is also
another means of serialization which translates serializable objects into XML files. The ASP.NET XML Web
service relies on XML serialization heavily to serialize instances of .NET types to XML and then deserialize
them from XML back to instances of .NET types. Through XML serialization applications can interoperate with
one another.
To serialize objects into XML document we need to use the XMLSerializer class from the
System.Xml.Serialization namespace. In the following example we have serialized the SerializableClass to XML.
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.IO;
namespace CSXMLSerialize
{
public class SerializableClass
{
private string _name;
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");
299
The Complete Reference To Professional SOA with Visual Studio 2005
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Xml.Serialization
Imports System.IO
Namespace VBXMLSerialize
300
The Complete Reference To Professional SOA with Visual Studio 2005
Class Program
<?xml version="1.0"?>
<SerializableClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
301
The Complete Reference To Professional SOA with Visual Studio 2005
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>John Doe</Name>
<ZipCode>2000</ZipCode>
</SerializableClass>
Controlling Serialization
Serialization is automatic. We don’t need to implement anything in code for serialization and deserialization to
occur. It is all taken care of by the .NET runtime. However, sometimes the default serialization and
deserialization process do not meet our requirements. In these instances we need to take control in order to
customize serialization to our needs.
.NET provides a mechanism for altering the way .NET types are serialized to XML. We can do this by using
the attributes defined in the System.Xml.Serialization namespace. See Table 8-1for commonly used attributes.
Name Description
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.
XmlElements Gets a collection of objects that specify how the XmlSerializer serializes a public field or
read/write property as an XML element.
XmlEnum Gets or sets an object that specifies how the XmlSerializer serializes an enumeration member.
XmlIgnore Gets or sets a value that specifies whether or not the XmlSerializer serializes a public field or
public read/write property.
Xmlns Gets or sets a value that specifies whether to keep all namespace declarations when an object
containing a member that returns an XmlSerializerNamespaces object is overridden.
XmlRoot Gets or sets an object that specifies how the XmlSerializer serializes a class as an XML root
element.
XmlText Gets or sets an object that instructs the XmlSerializer to serialize a public field or public
read/write property as XML text.
XmlType Gets or sets an object that specifies how the XmlSerializer serializes a class to which the
XmlTypeAttribute has been applied.
302
The Complete Reference To Professional SOA with Visual Studio 2005
Tip: We can use the word XmlElement in our code instead of the longer XmlElementAttribute.
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; }
}
class Program
{
static void Main(string[] args)
{
303
The Complete Reference To Professional SOA with Visual Studio 2005
Listing 8-14. Implementing XmlRoot and XmlElement attributes using Visual Basic .NET
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Xml.Serialization
Imports System.IO
Namespace VBXMLSerialize2
<XmlRoot("NewRootName", _
Namespace:="http://www.CustomNamespace.com", _
IsNullable:=True)> _
Public Class SerializableClass
Private _name As String
304
The Complete Reference To Professional SOA with Visual Studio 2005
<XmlElement("NewElementName")> _
Public Property Name() As String
Get
Return _name
End Get
Set(ByVal value As String)
_name = value
End Set
End Property
Private _zipCode As Integer
<XmlElement("NewElementZip")> _
Public Property ZipCode() As Integer
Get
Return _zipCode
End Get
Set(ByVal value As Integer)
_zipCode = value
End Set
End Property
End Class
Class Program
305
The Complete Reference To Professional SOA with Visual Studio 2005
CType(xmlserial.Deserialize(reader), SerializableClass)
reader.Close()
Return obj
End Function
End Class
End Namespace
The example creates a XML file that is shown in the listing 8-15 below.
<?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.
Name Description
DataType Gets or sets the XSD data type of the XML root element.
ElementName Gets or sets the name of the XML element that is generated and recognized by the XmlSerializer
class's Serialize and Deserialize methods, respectively.
IsNullable Gets or sets a value that indicates whether the XmlSerializer must serialize a member that is set
to a null reference (Nothing in Visual Basic) .
306
The Complete Reference To Professional SOA with Visual Studio 2005
Namespace Gets or sets the namespace for the XML root element.
TypeId When implemented in a derived class, gets a unique identifier for this Attribute.
The XmlElement attribute also exposes additional properties that we can use to control how a .NET type is
serialized to XML.
Name Description
DataType Gets or sets the XML Schema definition (XSD) data type of the XML element generated by the
XmlSerializer.
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.
307
The Complete Reference To Professional SOA with Visual Studio 2005
<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.
using System;
using System.Collections;
using System.IO;
using System.Xml.Serialization;
[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;
}
308
The Complete Reference To Professional SOA with Visual Studio 2005
x.Name = "Jack";
y.Name = "Jill";
309
The Complete Reference To Professional SOA with Visual Studio 2005
writer.Close();
}
Listing 8-20. Implementing XmlElement for array using Visual Basic .NET
Imports System
Imports System.Collections
Imports System.IO
Imports System.Xml.Serialization
<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
310
The Complete Reference To Professional SOA with Visual Studio 2005
x.Name = "Jack"
y.Name = "Jill"
311
The Complete Reference To Professional SOA with Visual Studio 2005
End Sub
Dim e As Employee
For Each e In g.Employees
Console.WriteLine(e.Name)
Next e
End Sub
End Class
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.
[XmlElement(typeof(int),
ElementName = "ObjectNumber"),
XmlElement(typeof(string),
ElementName = "ObjectString")]
public ArrayList ExtraInfo;
312
The Complete Reference To Professional SOA with Visual Studio 2005
Listing 8-23. Defining XmlElement for arraylist using Visual Basic .NET
<XmlElement(GetType(Integer), _
ElementName := "ObjectNumber"), _
XmlElement(GetType(String), _
ElementName := "ObjectString")> _
Public ExtraInfo As ArrayList
Ignoring Elements
During serialization if we wanted to we can exclude certain entities from serialization by using the
XmlIgnore attribute.
[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; }
}
<XmlRoot("NewRootName", _
Namespace:="http://www.CustomNamespace.com", _
IsNullable:=True)> _
Public Class SerializableClass
Private _name As String
<XmlElement("NewElementName")> _
Public Property Name() As String
Get
Return _name
End Get
Set(ByVal value As String)
313
The Complete Reference To Professional SOA with Visual Studio 2005
_name = value
End Set
End Property
Private _zipCode As Integer
<XmlIgnore()> _
Public Property ZipCode() As Integer
Get
Return _zipCode
End Get
Set(ByVal value As Integer)
_zipCode = value
End Set
End Property
End Class
By adding the XmlIgnore attribute the ZipCode attribute is excluded from the serialization process. As we
can see from the listing 8-26 below. The ZipCode has been removed from the result.
<?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:
[XmlRoot(IsNullable=false)]
public class CATALOG
{
[XmlArray("CDS", IsNullable=false)]
[XmlArrayItem("CD", IsNullable=false)]
public CD [] CDS;
}
<XmlRoot(IsNullable:=False)> _
Public Class CATALOG
<XmlArray("CDS", IsNullable:=False)> _
<XmlArrayItem("CD", IsNullable:=False)> _
314
The Complete Reference To Professional SOA with Visual Studio 2005
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:
[XmlArrayItem("MyInt", typeof(int))]
[XmlArrayItem("MyString", typeof(string))]
public object [] TestArray;
<XmlArrayItem("MyInt", GetType(Integer))> _
<XmlArrayItem("MyString", GetType(String))> _
Public TestArray As Object()
The preceding code will generate the following XML datatype definition:
<element minOccurs="1" maxOccurs="1" name="TestArray" nillable="true" type="s0:ArrayOfChoice1" />
<complexType name="ArrayOfChoice1">
<sequence>
<choice minOccurs="0" maxOccurs="unbounded">
<element minOccurs="1" maxOccurs="1" name="MyInt" type="int" />
<element minOccurs="1" maxOccurs="1" name="MyString" type="string" />
</choice>
</sequence>
</complexType>
Tip: Notice that the TestArray element can contain any combination of child elements of type string and int. To accept data of different
types from the client, the XML mixed array is mapped to a .NET array of type Object. The compiler will not throw an error if the .NET type
is set to something other than Object for example Integer. However, the client will receive a run-time error if the client sends an instance of
an XML datatype that cannot be transformed into the underlying .NET type.
The XmlArray and XmlArrayItems attributes expose additional properties that we can use to control how an
array is serialized to XML.
315
The Complete Reference To Professional SOA with Visual Studio 2005
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.
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.)
Name Description
DataType Gets or sets the XML data type 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.
NestingLevel Gets or sets the level in a hierarchy of XML elements that the XmlArrayItemAttribute
affects.
TypeId When implemented in a derived class, gets a unique identifier for this Attribute.(Inherited
from Attribute.)
316
The Complete Reference To Professional SOA with Visual Studio 2005
Rather than simply throwing an exception and giving up we may want to preserve the content and the structure
of the data from the document so that it can be passed to another component for processing. The .NET
Framework provides two attributes that allow us to capture unknown XML elements and attributes. These are
XmlAnyAttribute and XmlAnyElement:
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.
[XmlAnyElement()]
public XmlNode[] OpenElements
{
get { return _openElements; }
set { _openElements = value; }
}
<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.
[XmlAnyAttribute()]
public XmlNode[] OpenAttributes
{
get { return _openAttributes; }
set { _openAttributes = value; }
}
<XmlAnyAttribute()> _
Public Property OpenAttributes() As XmlNode()
Get
Return _openAttributes
317
The Complete Reference To Professional SOA with Visual Studio 2005
End Get
Set
_openAttributes = value
End Set
End Property
<WebMethodAttribute()> _
318
The Complete Reference To Professional SOA with Visual Studio 2005
<XmlInclude(GetType(Car))> _
<XmlInclude(GetType(Truck))> _
Public Function ReturnVehicle(ByVal i As Integer) As Vehicle
If i = 0 Then
Return New Car
Else
Return New Truck
End If
End Function
End Class
The preceding code will generate an XML datatype called Vehicle and two datatypes that derive by
extension from Vehicle these are Car and Truck. Because Car and Truck are extended versions of the Vehicle
datatype, Web service interfaces that accept the Vehicle datatype can also accept instances of Car and Truck.
Datatype Mapping
XML serialization provides a default mapping between .NET types and the built-in datatypes defined by XML
Schema. For example, a int type in .NET by default will be transformed by the XML serialization to the XML
built-in datatype Int32.
XML serialization supports all XML built-in datatypes.
Table 8-6. lists the supported mappings between XML datatypes and .NET types.
XSD data type .NET data type XSD data type .NET data type
319
The Complete Reference To Professional SOA with Visual Studio 2005
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.
Listing 8-37: Shows the XML Schema for the CD catalog document.
320
The Complete Reference To Professional SOA with Visual Studio 2005
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)
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
321
The Complete Reference To Professional SOA with Visual Studio 2005
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 {
/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public string[] Text {
get {
return this.textField;
}
set {
this.textField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
322
The Complete Reference To Professional SOA with Visual Studio 2005
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class CATALOG {
/// <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 {
/// <remarks/>
public TITLE TITLE {
get {
return this.tITLEField;
}
set {
this.tITLEField = value;
}
}
/// <remarks/>
323
The Complete Reference To Professional SOA with Visual Studio 2005
/// <remarks/>
public COUNTRY COUNTRY {
get {
return this.cOUNTRYField;
}
set {
this.cOUNTRYField = value;
}
}
/// <remarks/>
public COMPANY COMPANY {
get {
return this.cOMPANYField;
}
set {
this.cOMPANYField = value;
}
}
/// <remarks/>
public PRICE PRICE {
get {
return this.pRICEField;
}
set {
this.pRICEField = value;
}
}
/// <remarks/>
public YEAR YEAR {
get {
return this.yEARField;
}
set {
this.yEARField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
324
The Complete Reference To Professional SOA with Visual Studio 2005
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class COMPANY {
/// <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 {
/// <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 {
325
The Complete Reference To Professional SOA with Visual Studio 2005
/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public string[] Text {
get {
return this.textField;
}
set {
this.textField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class TITLE {
/// <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 {
/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public string[] Text {
get {
return this.textField;
}
326
The Complete Reference To Professional SOA with Visual Studio 2005
set {
this.textField = value;
}
}
}
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
'''<remarks/>
<System.Xml.Serialization.XmlTextAttribute()> _
Public Property Text() As String()
Get
Return Me.textField
End Get
Set
Me.textField = value
End Set
End Property
End Class
'''<remarks/>
<System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42"), _
System.SerializableAttribute(), _
System.Diagnostics.DebuggerStepThroughAttribute(), _
System.ComponentModel.DesignerCategoryAttribute("code"), _
System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=true), _
System.Xml.Serialization.XmlRootAttribute([Namespace]:="", _
IsNullable:=false)> _
Partial Public Class CATALOG
327
The Complete Reference To Professional SOA with Visual Studio 2005
Private cdField() As CD
'''<remarks/>
<System.Xml.Serialization.XmlElementAttribute("CD")> _
Public Property CD() As CD()
Get
Return Me.cdField
End Get
Set
Me.cdField = value
End Set
End Property
End Class
'''<remarks/>
<System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42"), _
System.SerializableAttribute(), _
System.Diagnostics.DebuggerStepThroughAttribute(), _
System.ComponentModel.DesignerCategoryAttribute("code"), _
System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=true), _
System.Xml.Serialization.XmlRootAttribute([Namespace]:="", _
IsNullable:=false)> _
Partial Public Class CD
'''<remarks/>
Public Property TITLE() As TITLE
Get
Return Me.tITLEField
End Get
Set
Me.tITLEField = value
End Set
End Property
'''<remarks/>
Public Property ARTIST() As ARTIST
Get
Return Me.aRTISTField
End Get
Set
328
The Complete Reference To Professional SOA with Visual Studio 2005
Me.aRTISTField = value
End Set
End Property
'''<remarks/>
Public Property COUNTRY() As COUNTRY
Get
Return Me.cOUNTRYField
End Get
Set
Me.cOUNTRYField = value
End Set
End Property
'''<remarks/>
Public Property COMPANY() As COMPANY
Get
Return Me.cOMPANYField
End Get
Set
Me.cOMPANYField = value
End Set
End Property
'''<remarks/>
Public Property PRICE() As PRICE
Get
Return Me.pRICEField
End Get
Set
Me.pRICEField = value
End Set
End Property
'''<remarks/>
Public Property YEAR() As YEAR
Get
Return Me.yEARField
End Get
Set
Me.yEARField = value
End Set
End Property
End Class
'''<remarks/>
<System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42"), _
System.SerializableAttribute(), _
System.Diagnostics.DebuggerStepThroughAttribute(), _
System.ComponentModel.DesignerCategoryAttribute("code"), _
System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=true), _
System.Xml.Serialization.XmlRootAttribute([Namespace]:="", _
IsNullable:=false)> _
329
The Complete Reference To Professional SOA with Visual Studio 2005
'''<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
'''<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
'''<remarks/>
330
The Complete Reference To Professional SOA with Visual Studio 2005
<System.Xml.Serialization.XmlTextAttribute()> _
Public Property Text() As String()
Get
Return Me.textField
End Get
Set
Me.textField = value
End Set
End Property
End Class
'''<remarks/>
<System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42"), _
System.SerializableAttribute(), _
System.Diagnostics.DebuggerStepThroughAttribute(), _
System.ComponentModel.DesignerCategoryAttribute("code"), _
System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=true), _
System.Xml.Serialization.XmlRootAttribute([Namespace]:="", _
IsNullable:=false)> _
Partial Public Class TITLE
'''<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
'''<remarks/>
<System.Xml.Serialization.XmlTextAttribute()> _
Public Property Text() As String()
Get
Return Me.textField
End Get
331
The Complete Reference To Professional SOA with Visual Studio 2005
Set
Me.textField = value
End Set
End Property
End Class
After the class is generated we can include the class into our project. Using these classes, we can develop in
an object oriented fashion to generate any XML document to conform to the original XML schema file. The
generated class cd_catalog.cs for C# and cd_catalog.vb if we’re generating for Visual Basic.
<?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>
<?xml version="1.0"?>
<Shipment xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
xmlns="http://schema.soawithwebservice.com/2006/9">
<OrderNo>102</OrderNo>
<Location>
<Addr>76 Reberto av </Addr>
<City>Organge Bay </City>
<State>CA</State>
<Zip>OB6527</Zip>
</Location>
</Shipment>
Schemas that allow the inclusion of additional elements and attributes that are not formally defined within the
schema itself are often referred to as open schemas.
332
The Complete Reference To Professional SOA with Visual Studio 2005
We can create an open schema by decorating a public field or property with the XmlAnyAttribute and
XmlAnyElement attributes. The XmlAnyAttribute attribute specifies that the parent element can contain any XML
attribute in addition to the ones formally defined within the schema. The XmlAnyElement attribute specifies that
the parent element can contain any XML element in addition to the ones formally defined within the schema.
The flexibility of open schemas can be very enticing. However, we should consider the consequences before
we create an open schema because the code needed to handle and process the extended data can become a little
complex.
One popular method for allowing extended information to be included within an instance document in a
semi-controlled fashion is to provide an area in the document definition for that information. The following
example defines an element within the CD datatype that is designated for containing extended information about
the CD:
[XmlRoot(Namespace=”http://www.mswcf.com”)]
public class Shipment
{
string _orderNo = string.Empty;
Location _location = new Location();
public string OrderNo
{
get { return _orderNo; }
set { _orderNo = value; }
}
public Location Location
{
get { return _location; }
set { _location = value; }
}
}
[XmlRoot(Namespace = ”http://www.mswcf.com”)]
public class Location
{
string _addr = string.Empty;
string _city = string.Empty;
string _state = string.Empty;
public string Addr
{
get { return _addr; }
set { _addr = value; }
}
public string City
{
get { return _city; }
set { _city = value; }
}
public string State
{
get { return _state; }
set { _state = value; }
}
333
The Complete Reference To Professional SOA with Visual Studio 2005
<XmlRoot(Namespace=”http://www.mswcf.com”)> _
Public Class Shipment
Private _orderNo As String = String.Empty
Private _location As Location = New Location
<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
334
The Complete Reference To Professional SOA with Visual Studio 2005
End Get
Set
_city = value
End Set
End Property
<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:
335
The Complete Reference To Professional SOA with Visual Studio 2005
<xs:sequence>
<xs:any namespace="##any" minOccurs="0"
maxOccurs="unbounded"
processContents="skip" />
</xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:sequence>
<xs:any namespace="##any"
minOccurs="0" maxOccurs="unbounded"
processContents="skip" />
</xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
In the schema above, the namespace for the open elements are declared as '##any', which is the default value.
Alternatively, we can supply the specific namespace that is allowed, or another predefined namespace tokens.
These tokens are:
##other - The XML elements must be from any namespace other than the target namespace is allowed.
##local - The XML elements must not be in a namespace.
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.
Summary
In this chapter we have examined XML serialization. XML serialization is an important aspect of Web services
as all communication between Web services are achieved through data serialization. It is responsible for
serializing instances of .NET types to XML and deserializing XML to instances of .NET types. This includes
support for instances of built-in .NET types, classes, and structures as well as composite types such as arrays,
nested object hierarchies, and objects that support the ICollection and IEnumerable interfaces. It also supports
serializing .NET type definitions into an XML schema.
XML serialization has default behaviors that might not be appropriate in all situations, so the .NET platform
provides a collection of attributes that we can apply to .NET type definitions, variable declarations, and
parameter declarations to control the behavior of .NET serialization.
336
The Complete Reference To Professional SOA with Visual Studio 2005
The exchange between a client and a XML Web Service consists of several stages. A client can be any
application that can facilitate a SOAP request to the XML Web Service this includes, console applications,
Windows forms applications, Web form applications and or even another XML Web Service. The following
steps are performed during these phases (see Figure 9-1):
337
The Complete Reference To Professional SOA with Visual Studio 2005
* The client creates an object of the XML Web Service by creating a proxy class on the computer on which the
client resides. The client calls a method on the proxy object. The request on the client system serializes the
method call and arguments into a SOAP message and sends it to the XML Web Service over the network.
* The XML Web Service on the server after receiving the request deserializes the SOAP message. The
deserialized message is then used to create an instance of the XML Web Service. The instance is used to
invoke the XML Web Service method with the arguments on the XML Web Service. The XML Web Service
executes the method and returns the value to the requesting client.
* The XML Web Service serializes the response return value and any out parameters into a SOAP message and
sends them to the client over the network.
* The client application after receiving the response message deserializes the SOAP message containing the
return value and any out parameters and sends them to the proxy object. The proxy object passes the relevant
return value and any out parameter back into the application.
In order to build XML Web Services that the clients can consume, we can use the ASP.NET Framework,
which is an integral part of the .NET Framework. Visual Studio 2005 also provides tools to build, deploy, and
publish the XML Web Services once development is complete. In the following section we will look at
development with Visual Studio 2005.
338
The Complete Reference To Professional SOA with Visual Studio 2005
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.
2. In the New Web Site dialog box, select Visual C# or Visual Basic as the language. Also select the location of
the Web Service that we would like it to be in. In the Templates pane, select ASP.NET Web Service. In the
Location box, type the name and location of the XML Web Service as
http://localhost/soa/AdventureWorks/Employee, and click OK. Figure 9-3.
339
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 9-4: Select “Browse” button for the Choose Location dialog window
3. .NET offers several forms of storage for Web Service, we could save our Web Service to File System, Local
IIS, FTP Site or Remote Site. In this instance we will be saving to an IIS location. Figure 9-4.
NOTE: If we are creating Web Service on a remote computer. The remote computer must be running .NET Framework version 2.0 and
must have IIS version 5.0 or later installed and running, ASP.NET must be enabled on IIS and FrontPage Server Extensions must be
installed and enabled at the root level where we are creating the new Web site. The user must also have FrontPage administration or
author permissions to create new folders and files on the remoting computer under the root folder where we want the site to be.
When we create the ASP.NET Web Service project, an .asmx file is created. After creating an XML Web
Service project, we write the code to provide functionality to the XML Web Service. This code is stored in a file
associated with the .cs or .vb file and is known as the code-behind file. The code-behind file depends on the
language that we use to create the XML Web Service. For a Visual C# project, the code-behind file is a .cs file.
The default template content of the file is shown in the listing 9-1and listing 9-2below.
Listing 9-1. XML Web Service default code behind using Visual C#
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
public Service () {
[WebMethod]
340
The Complete Reference To Professional SOA with Visual Studio 2005
}
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.
341
The Complete Reference To Professional SOA with Visual Studio 2005
Under the Solution Explorer we can see the structure of the application Figure 9-5. Under App_Code the
code for the webservice will be stored there. The App_Data folder is used by ASP.NET to store databases that
the system maintains. The .asmx is our .NET Web Service.
1. Rename the Service.asmx to Employee.asmx and
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.
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()
{
[WebMethod]
public string HelloWorld() {
return "Hello World";
}
Listing 9-6. Rename Web Service template’s default Service name to Employee
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class Employee
Inherits System.Web.Services.WebService
342
The Complete Reference To Professional SOA with Visual Studio 2005
<WebMethod()> _
Public Function HelloWorld() As String
Return "Hello World"
End Function
End Class
Since we have changed the file name as well as the class name we will need to adjust the .asmx accordingly.
So that the correct file and class is pointed to by the Employee.asmx file.
4. Double click on the Employee.asmx file and change the code bind pointer to
CodeBehind="~/App_Code/Employee.cs" Class="Employee".
Or
CodeBehind="~/App_Code/Employee.vb" Class="Employee".
Before we start to create the AdventureWorks employee management XML Web Service we need to ensure
that we have the relevant database table:
NOTE: We can install the sample database when installing Sql Server 2005 by specifying the advanced selection during installation and
enabling the AdventureWorks database for install. Or if Sql Server 2005 Express edition is used the database can be downloaded from the
Microsoft’s download site by using AdventureWorks as the search keyword.
We will be focusing on two tables. Employee under HumanResources and Contact under Person.
The Employee table contains employee information such as their national identification number, work title,
and vacation and sick leave hours listing 9-7.
Listing 9-7: The SQL create script for the Employee table
343
The Complete Reference To Professional SOA with Visual Studio 2005
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
344
The Complete Reference To Professional SOA with Visual Studio 2005
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.
[WebMethod]
public string HelloWorld() {
return "Hello World";
}
<WebMethod()> _
Public Function HelloWorld() As String
Return "Hello World"
End Function
Firstly we need to enable our connection to the AdventureWorks database using the the SqlConnection
class. The listing 9-11and listing 9-12 below shows how to use SqlConnection to connect to the AdventureWorks
database. In the connection string the Database login id of Book and Password Book is used. If you will need to
adjust the credential information inorder for the connection to work.
345
The Complete Reference To Professional SOA with Visual Studio 2005
Listing 9-11. Constructor and Finalizer to ensure our database connection is opened and closed using Visual C#
public Employee () {
~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
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.
using System.Data;
346
The Complete Reference To Professional SOA with Visual Studio 2005
using System.Data.SqlClient;
Listing 9-14. Adding the required namespace to code using Visual Basic .NET
Imports System.Data
Imports System.Data.SqlClient
The below listing shows how to implement the GetEmplyoees Method which is used to retrieve a list of
employee details From the XML Web Service listing 9-15and listing 9-16.
[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;
}
<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.
[WebMethod]
347
The Complete Reference To Professional SOA with Visual Studio 2005
return dsEmployees;
}
<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.
[WebMethod]
public void UpdateEmployeeDetailByID(
int EmployeeID,
string EmployeeFirstName,
string EmployeeMiddleName,
string EmployeeLastName,
string EmailAddress,
string Phone,
348
The Complete Reference To Professional SOA with Visual Studio 2005
string Title,
string BirthDate,
string MaritalStatus,
string Gender,
string HireDate)
{
SqlTransaction transaction = this.sqlcon.BeginTransaction("EmployeeTran");
try
{
// update Person.Contact
SqlCommand sqlcmdEmployee = new SqlCommand(
@"update Person.Contact con set
FirstName = @FirstName,
MiddleName = @MiddleName,
LastName = @LastName
EmailAddress = @EmailAddress,
Phone = @Phone,
inner join HumanResources.Employee emp on
emp.ContactID = con.ContactID
where
EmployeeID = @EmployeeID;
sqlcmdEmployee.Parameters.Add
("@FirstName", SqlDbType.VarChar, 50)
.Value = EmployeeFirstName;
sqlcmdEmployee.Parameters.Add
("@MiddleName", SqlDbType.VarChar, 50)
.Value = EmployeeMiddleName;
sqlcmdEmployee.Parameters.Add
("@LastName", SqlDbType.VarChar, 50)
.Value = EmployeeLastName;
sqlcmdEmployee.Parameters.Add
("@Title", SqlDbType.Int,
sizeof(int)).Value = EmployeeID;
sqlcmdEmployee.Parameters.Add
("@BirthDate", SqlDbType.VarChar, 50)
.Value = EmployeeLastName;
sqlcmdEmployee.Parameters.Add
("@MaritalStatus", SqlDbType.VarChar, 50)
.Value = EmployeeLastName;
sqlcmdEmployee.Parameters.Add
349
The Complete Reference To Professional SOA with Visual Studio 2005
transaction.Commit();
} catch {
transaction.Rollback();
}
}
<WebMethod()> _
Public Sub UpdateEmployeeDetailByID(ByVal EmployeeID As Integer, _
ByVal EmployeeFirstName As String, ByVal EmployeeMiddleName As String, _
ByVal EmployeeLastName As String, ByVal EmailAddress As String, _
ByVal Phone As String, ByVal Title As String, _
ByVal BirthDate As String, ByVal MaritalStatus As String, _
ByVal Gender As String, ByVal HireDate As String)
Dim transaction As SqlTransaction = _
Me.sqlcon.BeginTransaction("EmployeeTran")
Try
Dim sqlcmdContactID As SqlCommand = _
New SqlCommand("select contactid from " & _
"HumanResources.Employee where " & _
"HumanResources.Employee.EmployeeID = @EmployeeID", sqlcon)
sqlcmdContactID.Parameters.Add("@EmployeeID", _
SqlDbType.Int).Value = EmployeeID
sqlcmdContactID.Transaction = transaction
Dim contactID As Integer = _
CType(sqlcmdContactID.ExecuteScalar, Integer)
Dim sqlcmdEmployee As SqlCommand = _
New SqlCommand(" update Person.Contact set " & _
"FirstName = @FirstName, MiddleName = @MiddleName, " & _
"LastName = @LastName, EmailAddress = @EmailAddress, " & _
"Phone = @Phone where Person.Contact.ContactID " & _
"= @ContactID; update HumanResources.Employee " & _
"set Title = @Title, BirthDate = @BirthDate, " & _
"MaritalStatus = @MaritalStatus, Gender = @Gender, " & _
"HireDate = @HireDate where " & _
"HumanResources.Employee.EmployeeID = @EmployeeID; ", sqlcon)
sqlcmdEmployee.Transaction = transaction
sqlcmdEmployee.Parameters.Add("@ContactID", _
SqlDbType.Int).Value = contactID
sqlcmdEmployee.Parameters.Add("@EmployeeID", _
SqlDbType.Int).Value = EmployeeID
sqlcmdEmployee.Parameters.Add("@FirstName", _
SqlDbType.VarChar, 50).Value = EmployeeFirstName
sqlcmdEmployee.Parameters.Add("@MiddleName", _
350
The Complete Reference To Professional SOA with Visual Studio 2005
In listing 9-19 and listing 9-20 we’re providing the functionality to allow the consumer of the Web Service
to update a particular employee’s details. The consumer of the Web Service simply need to pass in an ID of the
employee followed by its details in the form of string parameters. The Web Service will then execute an update
statement on the Sql Server database on the server.
Once the above-mentioned Web methods had been created, we can now build and run our ASP.NET Web
Service application. To build an ASP.NET Web Service application, select Build Solution from the Build menu.
In order to execute the ASP.NET Web Service project, select Start Debugging from the Debug menu.
When launching debugging for the first time we will be prompted whether we wanted to enable debugging.
In this instance we will enable debugging see figure 9-7.
Figure 9-7. Debug diaglog option which will create the Web.config file.
351
The Complete Reference To Professional SOA with Visual Studio 2005
Once the Web Service is started we can see the three WebMethods that we had created earlier,
GetEmployeeByID, GetEmployees, UpdateEmployeeDetailByID see figure 9-8. .NET will also create the test
harness for each of the WebMethod. If we clicked on the links which is represented as the GetEmployeeByID
WebMethod.
352
The Complete Reference To Professional SOA with Visual Studio 2005
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.
353
The Complete Reference To Professional SOA with Visual Studio 2005
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.
354
The Complete Reference To Professional SOA with Visual Studio 2005
discuss the creation of setup projects in a later chapter. We will now deploy an XML Web Service by publishing
the XML Web Service files to the Web server.
To deploy our XML Web Service on a Web server, perform the following steps:
Enter the Target Location for the Web Service to be published as http://localhost/soawebservice/deploy/employee
then press the OK button. See figure 9-12 above
After the Web Service has been deployed we can check by browsing to the location
http://localhost/soawebservice/deploy/employee/employee.asmx in our Internet Explorer see figure 9-13 below.
355
The Complete Reference To Professional SOA with Visual Studio 2005
We can see the deployed files by browsing to the location in the file explorer see figure 9-14 below.
Figure 9-14. Shows the files created under the deployed Employee Web Service.
When we are publishing to a HTTP location. We could also publish to a UNC share. If we wanted to publish
to a remote Web site using HTTP or FTP, the Target Location box is where we would specify the remote server
URL.
The Allow this precompiled site to be updatable option specifies that all program code is compiled into
assemblies, but that .aspx files (including single-file ASP.NET Web pages) are copied as-is to the target folder
see figure 9-12.
Note: All data in the target folder and its subfolders will be deleted. Make sure that you do not type the name of a folder that contains data
356
The Complete Reference To Professional SOA with Visual Studio 2005
* 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.
http://localhost/soa/AdventureWorks/Employee/Employee.asmx?disco
357
The Complete Reference To Professional SOA with Visual Studio 2005
1. Create an XML document and insert the <?xml version="1.0" ?> tag in the first line.
<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>
358
The Complete Reference To Professional SOA with Visual Studio 2005
After we have specified the discovery information for our XML Web Service and have published the
discovery file, users can browse the discovery file to locate our XML Web Service.
After a client application discovers a Web Service, the client application can access and use all the exposed
methods of a Web Service. The process of using an exposed method of a Web Service is known as consuming a
Web Service.
To create a new windows project in Visual Studio 2005 select File -> New -> Project. This will bring up a
new project dialog window. In the New Project window select the language that we want to use and select
Windows Application from the Templates. Specify the name of the project as EmployeeClient and select a
location for the project. Then click OK see figure 9-15.
359
The Complete Reference To Professional SOA with Visual Studio 2005
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”.
In Listing 9-17 above we’re adding a reference to the Web Service. By simply entering the location of the
Web Service asmx press the Go button. We should be able to see the Employee Web Service and its
360
The Complete Reference To Professional SOA with Visual Studio 2005
WebMethods. Then we need to give it a reference name. In this case we will call it WSEmployee. Once
complete select Add Reference.
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.
361
The Complete Reference To Professional SOA with Visual Studio 2005
Employee.wsdl, the wsdl file contains the Web Service Description Language for the Employee Web Service. A
.wsdl file is essentially the interface for the Web Service it describes the methods that are available to be
consumed as well as the parameter and its datatype that’s required for each method. The .wsdl file is itself
described by a XML grammar see listing 9-24.
362
The Complete Reference To Professional SOA with Visual Studio 2005
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.
363
The Complete Reference To Professional SOA with Visual Studio 2005
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Results>
<DiscoveryClientResult
referenceType="System.Web.Services.Discovery.DiscoveryDocumentReference"
url="http://localhost/soa/AdventureWorks/Employee/Employee.asmx?disco"
filename="Employee.disco" />
<DiscoveryClientResult
referenceType="System.Web.Services.Discovery.ContractReference"
url="http://localhost/soa/AdventureWorks/Employee/Employee.asmx?wsdl"
filename="Employee.wsdl" />
</Results>
</DiscoveryClientResultsFile>
Reference.cs, this is the proxy file which contains the mapped WSDL in .NET code class. It allows a .NET client
to invoke methods on the XML Web Service over the network. It also handles the SOAP encoding and decoding
as messages are sent to and from the XML Web Service see listing 9-26 for reference.cs and listing 9-27 for
reference.vb. The code generated for the proxy is quite lengthy for our purpose only the
UpdateEmployeeDeatilByID() is shown.
Listing 9-26. UpdateEmployeeDetailByID method contained in the Reference.cs when using Visual C#
.
.
[System.Web.Services.Protocols.SoapDocumentMethodAttribute(
"http://tempuri.org/UpdateEmployeeDetailByID",
RequestNamespace="http://tempuri.org/",
ResponseNamespace="http://tempuri.org/",
Use=System.Web.Services.Description.SoapBindingUse.Literal,
ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public void UpdateEmployeeDetailByID(int EmployeeID,
string EmployeeFirstName, string EmployeeMiddleName,
string EmployeeLastName, string EmailAddress, string Phone,
string Title, string BirthDate, string MaritalStatus,
string Gender, string HireDate) {
this.Invoke("UpdateEmployeeDetailByID", new object[] {
EmployeeID,
EmployeeFirstName,
EmployeeMiddleName,
EmployeeLastName,
EmailAddress,
Phone,
Title,
BirthDate,
MaritalStatus,
Gender,
HireDate});
}
.
.
364
The Complete Reference To Professional SOA with Visual Studio 2005
Listing 9-27. UpdateEmployeeDetailByID method contained in the Reference.vb when using Visual Basic .NET
.
.
Public Sub UpdateEmployeeDetailByID(ByVal EmployeeID As Integer, _
ByVal EmployeeFirstName As String, ByVal EmployeeMiddleName As String, _
ByVal EmployeeLastName As String, ByVal EmailAddress As String, _
ByVal Phone As String, ByVal Title As String, ByVal BirthDate As String, _
ByVal MaritalStatus As String, ByVal Gender As String, _
ByVal HireDate As String)
Me.Invoke("UpdateEmployeeDetailByID", New Object() { _
EmployeeID, EmployeeFirstName, EmployeeMiddleName, EmployeeLastName, _
EmailAddress, Phone, Title, BirthDate, MaritalStatus, Gender, HireDate})
End Sub
.
.
The proxy file can be created automatically when we use Visual Studio’s “Add Web Reference” option to a
XML Web Service. We can also generate the proxy file using the command line utility wsdl.exe in the .NET
Framework. We can access the wsdl.exe utility through the Visual Studio 2005 Command Prompt where the
environment variables are setup for us to use within the command window.
To use the wsdl.exe tool we need to pass the location of the WSDL file to the tool. The tool by default will
generate visual C# proxy. The proxy can then be used to invoke the Web Service.
wsdl http://localhost/soa/AdventureWorks/Employee/Employee.asmx?wsdl
We can also specify a particular file name by using the /out: parameter :
wsdl /out:ReferenceProxy.cs http://localhost/soa/AdventureWorks/Employee/Employee.asmx?wsdl
For VB.NET users we can generate VB proxy by using the /language parameter. The following syntax will
create a VB proxy file called myProxyClass.vb.
wsdl /language:VB /out:myProxyClass.vb http://localhost/soa/AdventureWorks/Employee/Employee.asmx?wsdl
Client Application
Once the reference has been added and the proxy class to the Web Service was created. We can now start on our
windows application to access the Web Service we have created earlier. In this instance we will be creating a
windows application. We will need to create the user interface for the application first.
365
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 9-19 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
4. Next drag and drop a Label control from the Toolbox window onto the GroupBox.
5. Right click on the label select properties and change the Text property to “Employee ID”.
6. Select a TextBox control from the Toolbox window and drag and drop the control onto the “Get Employee
Details” GroupBox.
7. Right Click on the new TextBox and select properties. Change the name property to “textBoxGetEmployeeID”
8. Select a Button control from the Toolbox and drag and drop the control onto the “Get Employee Details”
GroupBox.
9. Right click on the new Button control select properties and change the Text of the button to “Get Employee”
and change the Name property of the control to “buttonGetEmployee”.
10. Select another Button control from the Toolbox and drag and drop the control onto the “Get Employee Details”
GroupBox.
11. Right click on the new Button control select properties and change the Text of the button to “Get All
Employees” and change the Name property of the control to “buttonGetAllEmployees”.
366
The Complete Reference To Professional SOA with Visual Studio 2005
Now we should have a user interface that look like figure 9-20 below.
1. Now we need to create a second GroupBox. To do this select the GroupBox control from the Toolbox window
and drag and drop the control onto the Windows form. Right click on the group box to select properties.
Change the Text property of the GroupBox to “Update Employee Details”.
2. Select a Label control and drag and drop the control into the “Update Employee Details” GroupBox. Change
the Text property for the Label control to “Employee ID”.
3. Select a TextBox control from the Toolbox window and drag and drop the control onto the “Update Employee
Details” GroupBox next to the new Label.
4. Right Click on the new TextBox and select properties. Change the Name property to “textBoxEmployeeID”
5. Select another Label control and drag and drop the control into the “Update Employee Details” GroupBox.
Change the Text property for the Label control to “First Name”.
6. Select a TextBox control from the Toolbox window and drag and drop the control onto the “Update Employee
Details” GroupBox next to the new Label.
7. Right Click on the new TextBox and select properties. Change the Name property to “textBoxFirstName”
8. Select another Label control and drag and drop the control into the “Update Employee Details” GroupBox.
Change the Text property for the Label control to “Middle Name”.
9. Select a TextBox control from the Toolbox window and drag and drop the control onto the “Update Employee
Details” GroupBox next to the new Label.
10. Right Click on the new TextBox and select properties. Change the Name property to “textBoxMiddleName”
11. Select another Label control and drag and drop the control into the “Update Employee Details” GroupBox.
Change the Text property for the Label control to “Last Name”.
12. Select a TextBox control from the Toolbox window and drag and drop the control onto the “Update Employee
Details” GroupBox next to the new Label.
13. Right Click on the new TextBox and select properties. Change the Name property to “textBoxLastName”
14. Select another Label control and drag and drop the control into the “Update Employee Details” GroupBox.
Change the Text property for the Label control to “Email Address”.
15. Select a TextBox control from the Toolbox window and drag and drop the control onto the “Update Employee
Details” GroupBox next to the new Label.
16. Right Click on the new TextBox and select properties. Change the Name property to “textBoxEmailAddress”
367
The Complete Reference To Professional SOA with Visual Studio 2005
17. Select another Label control and drag and drop the control into the “Update Employee Details” GroupBox.
Change the Text property for the Label control to “Phone”.
18. Select a TextBox control from the Toolbox window and drag and drop the control onto the “Update Employee
Details” GroupBox next to the new Label.
19. Right Click on the new TextBox and select properties. Change the Name property to “textBoxPhone”
20. Select another Label control and drag and drop the control into the “Update Employee Details” GroupBox.
Change the Text property for the Label control to “Title”.
21. Select a TextBox control from the Toolbox window and drag and drop the control onto the “Update Employee
Details” GroupBox next to the new Label.
22. Right Click on the new TextBox and select properties. Change the Name property to “textBoxTitle”
23. Select another Label control and drag and drop the control into the “Update Employee Details” GroupBox.
Change the Text property for the Label control to “Marital Status”.
24. Select a TextBox control from the Toolbox window and drag and drop the control onto the “Update Employee
Details” GroupBox next to the new Label.
25. Right Click on the new TextBox and select properties. Change the Name property to “textBoxMaritalStatus”
26. Select another Label control and drag and drop the control into the “Update Employee Details” GroupBox.
Change the Text property for the Label control to “Gender”.
27. Select a TextBox control from the Toolbox window and drag and drop the control onto the “Update Employee
Details” GroupBox next to the new Label.
28. Right Click on the new TextBox and select properties. Change the Name property to “textBoxGender”
29. Select another Label control and drag and drop the control into the “Update Employee Details” GroupBox.
Change the Text property for the Label control to “Birth Date”.
30. We need to add a DateTimePicker to the window. Select the DateTimePicker control from Toolbox and drag
and drop the control onto the “Update Employee Details” GroupBox.
31. Right Click on the new DateTimePicker and select properties. Change the Name property to
“dateTimePickerBirthDate”
32. In the DateTimePicker control set the CustomFormat “yyyy-MM-dd”. This will give us a datetime format of
year-month-day.
33. Select another Label control and drag and drop the control into the “Update Employee Details” GroupBox.
Change the Text property for the Label control to “Hire Date”.
34. Add another DateTimePicker to the window. Select the DateTimePicker control from Toolbox and drag and
drop the control onto the “Update Employee Details” GroupBox.
35. Right Click on the new DateTimePicker and select properties. Change the Name property to
“dateTimePickerHireDate”
368
The Complete Reference To Professional SOA with Visual Studio 2005
36. In the DateTimePicker control set the CustomFormat “yyyy-MM-dd”. This will give us a datetime format of
year-month-day.
37. Select another Button control from the Toolbox and drag and drop the control onto the “Update Employee
Details” GroupBox.
38. Right click on the new Button control select properties and change the Text of the button to “Update” and
change the Name property of the control to “buttonUpdate”.
39. Right click on the Windows Form and select properties. Change the Text Property for the windows form to
“CS Employee Client” or “VB Employee Client” accordingly.
Now we should have a user interface that look like figure 9-21 below.
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.
With the datagrid the windows form should look something similar to figure 9-22 below.
369
The Complete Reference To Professional SOA with Visual Studio 2005
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.
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-31. Implementing Update button event using Visual Basic .NET
370
The Complete Reference To Professional SOA with Visual Studio 2005
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.
371
The Complete Reference To Professional SOA with Visual Studio 2005
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
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.
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.
372
The Complete Reference To Professional SOA with Visual Studio 2005
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
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.
this.textBoxEmployeeID.Text = dsEmployee.Tables[0].Rows[0]
["EmployeeID"].ToString();
this.textBoxFirstName.Text = dsEmployee.Tables[0].Rows[0]
["FirstName"].ToString();
this.textBoxMiddleName.Text = dsEmployee.Tables[0].Rows[0]
["MiddleName"].ToString();
this.textBoxLastName.Text = dsEmployee.Tables[0].Rows[0]
["LastName"].ToString();
this.textBoxEmailAddress.Text = dsEmployee.Tables[0].Rows[0]
["EmailAddress"].ToString();
this.textBoxPhone.Text = dsEmployee.Tables[0].Rows[0]
["Phone"].ToString();
this.textBoxTitle.Text = dsEmployee.Tables[0].Rows[0]
["Title"].ToString();
this.dateTimePickerBirthDate.Text = dsEmployee.Tables[0].Rows[0]
["BirthDate"].ToString();
this.textBoxMaritalStatus.Text = dsEmployee.Tables[0].Rows[0]
["MaritalStatus"].ToString();
this.textBoxGender.Text = dsEmployee.Tables[0].Rows[0]
["Gender"].ToString();
this.dateTimePickerHireDate.Text = dsEmployee.Tables[0].Rows[0]
["HireDate"].ToString();
373
The Complete Reference To Professional SOA with Visual Studio 2005
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.
374
The Complete Reference To Professional SOA with Visual Studio 2005
</soap:Envelope>
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
The result of the execution can be seen in figure 9-23 and figure 9-24 below.
375
The Complete Reference To Professional SOA with Visual Studio 2005
Summary
XML Web Service allows us to build scalable, loosely coupled, platform-independent applications. XML Web
Services enable disparate applications to exchange messages using standard protocols such as HTTP, XML,
XSD, SOAP, and WSDL.
In this chapter we have created an XML Web Service that provide specific functionality to the client
applications over the Web. The Visual Studio 2005 IDE provides us with the environment that are needed to
create projects for distributed desktop applications, Web applications, and XML Web Services.
In this chapter we have also looked at deploying the XML Web Service to a Web server to make it available
to the applications that want to use the XML Web Service. We can deploy an XML Web Service to a Web server
by simply using the Publish Web Site function that’s available within Visual Studio 2005 which will allow us to
deploy to a HTTP location. We could also publish to a UNC share or a remote Web site using HTTP or FTP.
The XML Web Service discovery mechanism enables a client application to locate or discover the
documents that describe an XML Web Service. The XML Web Service discovery mechanism returns a service
description document to a client. The service description document is written in WSDL and contains information
about the capabilities of the XML Web Service, its location, and how to interact with it.
After we create an XML Web Service and publish it, any application having permission to access it can
access our XML Web Service and consume its services. The application that consumes a Web Service is known
as the Web Service client or Web Service consumer. A Web Service client can be a windows application, a web
based application or a mobile application. This is because Web Services are interoperable through open
standards.
376
The Complete Reference To Professional SOA with Visual Studio 2005
* Testing reduces the cost of developing an application. The cost of rectifying an error after an application has
been created is much more than the cost of implementing a thorough testing process as part of the development
life cycle.
* Testing ensures that our application performs as specified. In most cases, if testing is not implemented, we
cannot actually predict the output of a certain operation.
* Testing reduces the total cost of ownership. If a software application functions exactly as described in the
documentation, users require fewer hours of training and less support from product experts.
377
The Complete Reference To Professional SOA with Visual Studio 2005
* Testing develops customer loyalty and word-of-mouth market share. We are more likely to build a strong
customer base with high-quality, bug-free software, which only thorough testing can provide.
To ensure that our application is free of defects and bugs, we can subject our applications to the following
types of testing see Table 10-1:
Requirements testing This is where we perform testing to verify whether our application meets the
requirements as specified in the software specification.
Usability testing We perform usability testing to test the usability and ease of use of our application.
During usability testing, we perform checks to ensure that all the information that
users require is provided by the application. In addition, we also perform tests to
ensure that the user interface is easily navigable.
Unit testing During unit testing, we take the smallest unit of an application usually a method
within a module and test it to ensure that it functions as expected. This ensures the
quality of each function before they’re integrated onto the server.
During integration testing, we combine the functions that had already been
Integration testing
tested through our unit testing phase into a component and test the interface
that combines the two units. We then combine them into components, test
the components, and integrate them into modules. The various modules are
then tested and integrated into an application.
Regression testing We perform regression testing to ensure that any change made to code that has
already been tested does not break the code. We can perform regression testing by
executing the existing tests on the modified code or by creating new tests for the
modified code, if necessary.
Requirements-Based Testing
The first phase of the software development life cycle involves gathering and analyzing requirements. The
requirements phase provides the application's necessary features. Requirements also provide the basis for all
378
The Complete Reference To Professional SOA with Visual Studio 2005
types of testing. Based on the descriptions in the requirement specification, testing identifies defects that create,
cause, or allow unpredictable behavior in the software. Therefore, the test team should also be involved in the
specification-writing process.
We should design our test cases while writing the requirements specifications. A test case consists of sample
data and its corresponding output, which is calculated manually. To design test cases, we need to analyze each
specification and determine how well the requirement supports the development of test cases. Developing a test
case ensures that we will critically analyze the requirement specifications.
* 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.
379
The Complete Reference To Professional SOA with Visual Studio 2005
SOA. These are: functional and regression testing, performance, interoperability, and vulnerability assessment see
figure 10-1.
There are four pillars of successful testing, as shown in Figure 10-1.
380
The Complete Reference To Professional SOA with Visual Studio 2005
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:
b[reak] [[file:] line number] | [[ Using the break command we can set or displays
class::] function [:offset]] breakpoints. If no arguments are specified, the tool
will display a list of current breakpoints
381
The Complete Reference To Professional SOA with Visual Studio 2005
del[ete] [breakpoint id, ...] Delete command can be used to remove breakpoints.
We can specify a specific breakpoint id to remove.
We can find the relevant breakpoint id by using the
break or stop command.
h[elp] [command ...] the help command words as help it can displays
descriptions for a specified command. If no command
is specfied then CorDbg.exe displays a list of
debugger commands. The ? command can be used the
same way as the help command.
n[ext] [count] The next command can be used to step to the next
line of source code. It will also step over function
calls.
o[ut] [count] The out command can be used to steps the program
out of the current function. If no argument is
specified the command will only perform a set out
once for its current position. If we specify a count
parameter the out command will be performed for the
specified number of times.
p[rint] [variable name] The print command can be used to display a local
variable and its value. If no variable is specified all
local variables are displayed.
ref[reshsource] [source file] The refreshsource command can be used to reload the
source code for a given file. The source must be part
of the currently executing program.
r[un] [executable [args]] The run command is use to execute a program for
debugging we can also pass in parameters by
specying them as arguments.
set variable value set command can be used to set the value of a
particular variable.
382
The Complete Reference To Professional SOA with Visual Studio 2005
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.
In the following example we will attempt to debug the following code in listing 10-1 and listing 10-2using
CorDbg:
using System;
using System.Collections.Generic;
using System.Text;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 2; i++)
{
Console.WriteLine("Count: " + i);
}
}
}
}
Listing 10-2. Sample code for debugging using Visual Basic .NET
Module Module1
Sub Main()
Dim i As Integer = 0
While i < 2
Console.WriteLine("Count: " + i.ToString())
i += 1
End While
End Sub
383
The Complete Reference To Professional SOA with Visual Studio 2005
End Module
When we debug an application using CorDbg, the application is debugged in a new CorDbg session. To start
a CorDbg session, we need to type cordbg inside the Visual Studio 2005 Command Prompt, followed by the
required command to control the debugging session.
We can start debugging the program by using the cordbg helloworld.exe command. The command run
helloworld.exe is invoked automatically within the cordbg environment. We can ignore the warning about
mscorlib.dll, the cordbg utility simply informs us that we can not debug the core library that contains .NET
Framework class library types. We are now in the cordbg command prompt see figure 10-2 below and listing 10-
3 for output.
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.
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.
(cordbg) show
384
The Complete Reference To Professional SOA with Visual Studio 2005
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.
(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.
(cordbg) go
break at #1 D:\Projects\Book\SourceCode\Ch10\HelloWorld\HelloWorld\Program.c
s:13 Main+0x6(il) [active]
The deubugger is now currently on line 13 we can see this by executing the show command again. See
listing 10-7 below.
(cordbg) show
008: {
009: static void Main(string[] args)
010: {
011: for (int i = 0; i < 2; i++)
012: {
385
The Complete Reference To Professional SOA with Visual Studio 2005
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.
(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]
We have successfully debugged in the above example the value of i. To exit cordbg debug environment
simply the exit command.
386
The Complete Reference To Professional SOA with Visual Studio 2005
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.
387
The Complete Reference To Professional SOA with Visual Studio 2005
The Call Stack window displays the name of each function and the language in which it is written. In
addition to the function name, the Call Stack window displays optional information, such as module name;
parameter name, parameter type, parameter value, line number and byte offset. To select the desired information
to display, right-click in the Call Stack window and choose the appropriate information type.
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.
388
The Complete Reference To Professional SOA with Visual Studio 2005
statement where we would like to set the breakpoint and click on the grey margin on the left. To open the
Breakpoints window, from the Debug menu, point to Windows and choose Breakpoints.
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.
* Filter - we can restrict the breakpoint to only being set in certain processes and threads. We can enter the
expression such as ProcessID=45 which will influence the breakpoint to only be set when the ProcessID=45
(see Figure 10-10). We can also combine conditions using & (AND), || (OR), ! (NOT), and parentheses.
389
The Complete Reference To Professional SOA with Visual Studio 2005
* 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.
Unit Testing
To build clean, well-structured code, we developers need some mechanism to ensure that the code runs
effectively. One solution is for the developer to write pieces of code and then run the application to see whether
it works the way it should. The developer then moves on to the next piece of code, never coming back to test that
functionality until it’s close to the release date. Unit tests are a way to automate that method of testing so that the
tests can be run repeatedly as the product is developed.
390
The Complete Reference To Professional SOA with Visual Studio 2005
In order to create unit tests, we need to design a series of test cases that test whether the business logic is
functioning correctly and whether inputs produce the expected outputs. To be complete, many unit tests might
test the same piece of code to ensure that all the branches and internal code flow are tested. We’ll see how Visual
Studio solves this problem when we talk about code coverage later. Because unit tests test basic functionality at
the method level, they are considered to be a developer’s responsibility and not the responsibility of the testing
staff.
In the example below we will be creating a calculator Web service we will then attempt to test this
calculator service with our unit tests.
To start with create a new Web service called TestService, as shown in Figure 10-12.
Enter the code below. First, Listing 10-9 shows the 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 () {
[WebMethod]
public int AddInt(int x, int y) {
return x + y;
}
[WebMethod]
391
The Complete Reference To Professional SOA with Visual Studio 2005
[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;
}
}
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
<WebMethod()> _
Public Function AddInt(ByVal x As Integer, ByVal y As Integer) As Integer
Return x + y
End Function
<WebMethod()> _
Public Function SubtractInt(ByVal x As Integer, ByVal y As Integer) As Integer
Return x - y
End Function
<WebMethod()> _
Public Function MultiplyInt(ByVal x As Integer, ByVal y As Integer) As Integer
Return x * y
392
The Complete Reference To Professional SOA with Visual Studio 2005
End Function
<WebMethod()> _
Public Function DivideInt(ByVal x As Integer, ByVal y As Integer) As Double
Return x / y
End Function
<WebMethod()> _
Public Function DivideExceptionInt(ByVal x As Integer, ByVal y As Integer) As Integer
Return x / y
End Function
End Class
Once we have completed our code we need to build the Web service application to verify that there are no
outstanding syntax errors. Once the build is successful using Visual Studio we can generate our test project and
our test methods. Simply right mouse click on the screen then select “Create Unit Tests” (see figure 10-13).
A dialog window will appear (see Figure 10-14). In this window we can select the methods that we’d like to
Visual Studio to generate test cases for.
393
The Complete Reference To Professional SOA with Visual Studio 2005
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.
In the Output project selection checked that you have selected your default language either “Create a new Visual
Basic test project…” or “Create a new Visual C# test project”.
Make sure you have selected all the methods then click OK. Enter VBCalcUnitTest as the new project name
then select Create, as shown in Figure 10-16.
394
The Complete Reference To Professional SOA with Visual Studio 2005
The Test Generation Progress dialog box appears showing the test classes' generation progress (see Figure 10-
17)
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.
[TestMethod()]
public void AddIntTest()
{
Service target = new Service(); // TODO: Use [AspNetDevelopmentServer]
//and TryUrlRedirection() to auto launch and bind web service.
int expected = 0;
int actual;
<TestMethod()> _
Public Sub AddIntTest()
Dim target As Service = New Service 'TODO: Use [AspNetDevelopmentServer]
395
The Complete Reference To Professional SOA with Visual Studio 2005
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
The exact generated code will vary depending on the method type and signature that the test targets for
testing. The wizard will create code using reflection to test private member functions.
The generated test classes in the test project will contain test methods that is decorated with the
TestMethodAttribute. In addition, the classes that contains these test methods are decorated with the
TestClassAttribute. Both of these attributes can be found under the
Microsoft.VisualStudio.QualityTools.UnitTesting.Framework namespace. The Team Test uses reflection to search a
test assembly and find all of the test classes decorated with TestClassAttribute. It then finds the corresponding
TestMethodAttribute within the test classes to determine what to execute. The test method themselves must not
take any parameters it is validated by the execution engine but not by the compiler.
When the tests is run, the Assert.Inconclusive() can be used to indicate that a correct implementation could be
missing. The Assert class provides a number of members which allow us to test a particular condition or
particular state of an object see Table 10-3.
396
The Complete Reference To Professional SOA with Visual Studio 2005
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.
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
397
The Complete Reference To Professional SOA with Visual Studio 2005
namespace CSUnitTest
{
/// <summary>
///This is a test class for CSUnitTest.localhost.Service and is intended
///to contain all CSUnitTest.localhost.Service Unit Tests
///</summary>
[TestClass()]
public class ServiceTest
{
private TestContext testContextInstance;
/// <summary>
///Gets or sets the test context which provides
///information about and functionality for the current test run.
///</summary>
public TestContext TestContext
{
get
{
return testContextInstance;
}
set
{
testContextInstance = value;
}
}
#region Additional test attributes
//
//You can use the following additional attributes as you write your tests:
//
//Use ClassInitialize to run code before running the first test in the class
//
//[ClassInitialize()]
//public static void MyClassInitialize(TestContext testContext)
//{
//}
//
//Use ClassCleanup to run code after all tests in a class have run
//
//[ClassCleanup()]
//public static void MyClassCleanup()
//{
//}
//
//Use TestInitialize to run code before running each test
//
//[TestInitialize()]
//public void MyTestInitialize()
//{
//}
//
//Use TestCleanup to run code after each test has run
//
398
The Complete Reference To Professional SOA with Visual Studio 2005
//[TestCleanup()]
//public void MyTestCleanup()
//{
//}
//
#endregion
/// <summary>
///A test for AddInt (int, int)
///</summary>
[TestMethod()]
public void AddIntTest()
{
Service target = new Service();
Random rand = new Random();
int x = rand.Next(100);
int y = rand.Next(100);
int expected = x + y;
int actual;
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);
Assert.AreEqual(expected, actual,
"CSUnitTest.localhost.Service.DivideInt did not return the expected value.");
}
/// <summary>
///A test for MultiplyInt (int, int)
///</summary>
[TestMethod()]
public void MultiplyIntTest()
399
The Complete Reference To Professional SOA with Visual Studio 2005
{
Service target = new Service();
Random rand = new Random();
int x = rand.Next(100);
int y = rand.Next(100);
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);
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
'''<summary>
'''This is a test class for VBCalcUnitTest.localhost.Service and is intended
'''to contain all VBCalcUnitTest.localhost.Service Unit Tests
'''</summary>
400
The Complete Reference To Professional SOA with Visual Studio 2005
<TestClass()> _
Public Class ServiceTest
'''<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
'''<summary>
'''A test for AddInt(ByVal Integer, ByVal Integer)
'''</summary>
401
The Complete Reference To Professional SOA with Visual Studio 2005
<TestMethod()> _
Public Sub AddIntTest()
Dim target As Service = New Service
Dim rand As Random = New Random
Dim x As Integer = rand.Next(100)
Dim y As Integer = rand.Next(100)
Dim expected As Integer = x + y
Dim actual As Integer
actual = target.AddInt(x, y)
Assert.AreEqual(expected, actual, _
"CSUnitTest.localhost.Service.AddInt did not return the expected value.")
End Sub
'''<summary>
'''A test for DivideInt(ByVal Integer, ByVal Integer)
'''</summary>
<TestMethod()> _
Public Sub DivideIntTest()
Dim target As Service = New Service
Dim rand As Random = New Random
Dim x As Integer = rand.Next(100)
Dim y As Integer = rand.Next(100)
Dim expected As Double = CType(x, Double) / y
Dim actual As Double
actual = target.DivideInt(x, y)
Assert.AreEqual(expected, actual, _
"CSUnitTest.localhost.Service.DivideInt did not return the expected value.")
End Sub
'''<summary>
'''A test for MultiplyInt(ByVal Integer, ByVal Integer)
'''</summary>
<TestMethod()> _
Public Sub MultiplyIntTest()
Dim target As Service = New Service
Dim rand As Random = New Random
Dim x As Integer = rand.Next(100)
Dim y As Integer = rand.Next(100)
Dim expected As Integer = x * y
Dim actual As Integer
actual = target.MultiplyInt(x, y)
Assert.AreEqual(expected, actual, _
"CSUnitTest.localhost.Service.MultiplyInt did not return the expected value.")
End Sub
'''<summary>
'''A test for SubtractInt(ByVal Integer, ByVal Integer)
'''</summary>
<TestMethod()> _
Public Sub SubtractIntTest()
Dim target As Service = New Service
Dim rand As Random = New Random
402
The Complete Reference To Professional SOA with Visual Studio 2005
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-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.
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.
[TestMethod()]
403
The Complete Reference To Professional SOA with Visual Studio 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 will now add the ExpectedExceptionAttribute, which will return successful when the exception is
encountered. See listing 10-17 and listing 10-18.
[TestMethod()]
[ExpectedException(typeof(SoapException))]
public void DivideExceptionIntTest()
{
Service target = new Service();
int x = 0;
int y = 0;
target.DivideExceptionInt(x, y);
}
<TestMethod()> _
<ExpectedException(GetType(System.Web.Services.Protocols.SoapException))> _
Public Sub DivideExceptionIntTest()
Dim target As Service = New Service
Dim x As Integer = 0
Dim y As Integer = 0
404
The Complete Reference To Professional SOA with Visual Studio 2005
target.DivideExceptionInt(x, y)
End Sub
Figure 10-22 shows the Test Results window now we have added an ExpectedExceptionAttribute.
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.
Under the Code Coverage option, select the artifacts to instrument, as shown in Figure 10-24. Then select
Apply.
405
The Complete Reference To Professional SOA with Visual Studio 2005
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.
406
The Complete Reference To Professional SOA with Visual Studio 2005
During debugging it is possible that the TestCleanupAttribute decorated method will not run simply because
the debugger was stopped before the cleanup code executed. For this reason, it is often a good practice to check
for cleanup during test setup and execute the cleanup prior to the setup as necessary. Other test attributes
available for initialization and cleanup are AssemblyInitializeAttribute/AssemblyCleanupAttribute and
ClassInitializeAttribute/ClassCleanupAttribute. The assembly-related attributes run once for an entire assembly
while the class related attributes run once each for the loading of a particular test class.
Static Analysis
Creating quality code often involves analyzing code for known defects, which can be achieved through the use
of static analysis. In Visual Studio 2005 Team System, the static analysis tool is an evolution of FxCop. The
static code analyzer runs against compiled code, looking for a large number of known defects and poor
programming practices. In addition, it can be used to enforce corporate naming conventions.
The rules used by the static analyzer are fully extensible, and it is possible to add a new rule relatively
quickly. It’s also possible to enable and disable rules that will be run against the code. For instance, we might
choose not to run the rules that enforce naming conventions but be very interested in the results of the tests that
check for known security issues. Finally, we can choose whether a violation of a rule generates a warning or a
compile-time error.
For coding conventions that absolutely must not be violated, using an error is the best practice and is one of
the easiest to implement. Setting a violation of code from being checked in unless it has compiled without error,
results in an easy to implement yet very powerful technique for guaranteeing a certain level of code quality.
We can enable code analysis in Visual Studio by right click on a project selecting properties. Then selecting
the Code Analysis tab see figure 10-26. To enable code analysis we will need to select the check box “Enable
Code Analysis”.
Once we have enabled the project set up for code analysis, all we need to do is recompile our application.
This will cause the static code analyzer to run. The results can then be seen by examining the Errors window (see
figure 10-27). If a particular line of code caused the error, double-clicking the error in the Error window will
open the appropriate code window and bring us to the problem area within the code.
407
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 10-27: Result from static analysis test in Visual Studio 2005
The results can also be saved to CodeAnalysisLog.xml. Opening this file will show all the issues the compiler
had uncovered.
Profiling
Code profiling is the process where we analyze the code and how quickly it executes. It enables developers to
see where the bottleneck exists within the application quickly. After the application has been completed and the
code unit tested we should always profile the code. There’re two types of methods to profile an application in
Visual Studio: sampling and instrumentation.
408
The Complete Reference To Professional SOA with Visual Studio 2005
Sampling
Using the sampling method, the profiler will periodically determine which function is being executed. The
profiler keeps track of the number of times that it has executed the function by incrementing a counter. It
interrupts the application in short intervals to build up a statistical view of he application. It’s a reliable way to
determine where an application spends the majority of its time. Once the application is stopped, a report is
generated that provides the details.
Instrumentation
The instrumentation method is more aggressive than the sampling method. In this method, the profiler inserts
enter and exit probes into specific functions of an application. These functions are now monitored when the
application runs. The probes capture the deterministic performance metrics for the functions. This means that we
can get information about how long a method takes to execute. This method also provides a relatively complete
numeric look at how often various methods are called. Once the application is stopped, a report can be generated
based on the data gathered by the instrumentation profiler.
Implementing Sampling
To configure the performance we can check session properties under the Tools ~TRA Options ~TRA
Environment ~TRA Performance Tools page in Visual Studio, shown in Figure 10-29. This is the section where
we can specify all settings related to all performance sessions.
The first option shown in Figure 10-29 is a radio button to show time as CPU clock ticks or milliseconds.
The next option lets us select how many functions are shown in summary view. Summary view is the first view
that we see when analyzing a performance run and it lists the top X functions in terms of total number of calls,
total number of calls to a function and all child functions, and total time taken by a function. The last option
allows us to serialize symbols, which saves symbols in with our .VSP files. The .VSP files can be copied and
read on different systems without chasing down symbols files. These .VSP files are the files that are created with
each run of the profiler.
In the example below we will create a sampling session on a Web service client we had created in Chapter
9. Select the Tools ~TRA Performance Tools ~TRA Performance Wizard option, as shown in Figure 10-30.
409
The Complete Reference To Professional SOA with Visual Studio 2005
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.
We will now browse to the location of the executable that we had created in Chapter 9 of the employee Web
service client (the CSEmployeeClient project in Chapter 9), as shown in Figure 10-32.
410
The Complete Reference To Professional SOA with Visual Studio 2005
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.
411
The Complete Reference To Professional SOA with Visual Studio 2005
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.
412
The Complete Reference To Professional SOA with Visual Studio 2005
Once we close the Windows application the analysis of the results collected begins, as shown in Figure 10-
37.
The end result is a report into which we can drill to view the result from the execution of each method (see
Figure 10-38).
413
The Complete Reference To Professional SOA with Visual Studio 2005
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.
In instrumentation mode the performance report summary contains three different sections (see figure 10-
39). These are “most called functions,” “functions with most individual work” and “functions taking longest.”
The “most called functions” lists the functions that had been called the highest number of times. The report
also lists the number of times that they have been called.
The “Functions with most individual work” section lists the functions in which most amount of time had
been spent. The report shows the amount of time spent by each of these methods and their percentage against the
total execution time.
414
The Complete Reference To Professional SOA with Visual Studio 2005
Lastly the “functions taking longest” section shows the functions that took the longest to execute this
includes time spent in sub-functions this is similar to the inclusive mode for sampling.
By using instrumentation every function entry and exit is captured. This provides a very detailed report
which is not only limited to the samples. Figure 10-40 shows the instrumentation summary view for our demo
application.
Generally determining which method to use for profiling is based on our needs. Sampling is often used as a
first look at an application. The sampling method is also far less intrusive than the instrumentation method, and
thus allows the application to run at a normal pace. It doesn’t, however, provide a complete analysis of the
application. For example, even though we can see how the code appears within a method, we cannot determine
how long that particular method took to execute.
Instrumentation profiling provides for very specific performance metrics. However, it performs this in an
intrusive manner. This makes the application seem like it is struggling, but it does provide a much fuller profile
of the application and more reliable and specific information than the sampling method.
Summary
Visual Studio 2005 Team System has integrated a lot of tools for developers. It provides a vast range of tool sets
over previous versions of Visual Studio especially those tools help developers to develop efficiently and quickly.
After using Visual Studio Team System it is difficult to go back to any other development environments.
In this chapter we had looked at testing and how to accomplish a number of tasks, such as:
* Unit testing - Unit testing helps developers to build clean and well-structured code. It also helps to support the
mechanism to ensure that the code written runs effectively.
* Code coverage - Code coverage helps a developer to determine how much of the code is tested when the unit
tests run. Team Test includes a code coverage tool for detailing both the percentage of code that is executed
along with highlighting within the code to show which lines are executed and which lines are not.
* Static analysis - Creating quality code often involves analyzing code for known defects, which can be achieved
through the use of static analysis. The static code analyzer runs against compiled code, looking for a large
number of known defects and poor programming practices.
415
The Complete Reference To Professional SOA with Visual Studio 2005
* Profiling - Profiling the code ensures the performance of the code. After the application has been completed
and the code unit tested we should always profile the code. Code profiling is the process where we analyze the
code and how it quickly it executes. It enables developers to see where the bottleneck exists within the
application quickly. There’re two types of methods to profile an application in Visual Studio 2005: sampling
and instrumentation.
In addition to Visual Studio Team System Developer’s implementation to application testing. Visual Studio
Team System Tester’s also helps with the implementation to integration and regression testing.
416
The Complete Reference To Professional SOA with Visual Studio 2005
Chapter 11 Deployment
The .NET Framework provides features and tools that enable us to easily package and distribute a variety of
applications to a number of users. In this chapter, we will learn how to create setup projects to automatically
install and configure our Web service.
Once we have ensured that our application is free from bugs, we need to distribute our Web service
applications to end users by possibly deploying the application on various computers. In this chapter we will be
looking at various deployment features of the .NET Framework.
.NET Deployment
Ensuring successful deployment of an application is extremely important in the software development lifecycle,
especially when the majority of the deployment today is done at the client’s site. Any sort of failure during the
deployment process can easily become quite embarrassing. The .NET Framework is packed full of features and
tools that we can use to deploy applications successfully. These features and tools enable us to deploy different
types of applications to a large number of users. In addition, we can install new versions of applications on target
computers without adversely affecting the older versions of our applications. The .NET Framework provides
various packaging and distribution options that make it easy to deploy applications. The features of .NET
deployment include
No-impact deployment: In the past an incompatible version of DLL can be installed over an existing DLL. This
was a serious issue as it caused applications to stop working and was referred to as the “DLL Hell” problem. No-
impact deployment offered by the .NET Framework resolves this problem and DLL is deployed in isolation.
Controlled code sharing: Because components are private by default, multiple applications cannot share
components. We need to explicitly make the components available for sharing by assigning a strong name to an
assembly containing the components and installing the assembly in the global assembly cache.
XCOPY deployment and reproduction: .NET applications and components are self describing and self
contained so there is no need for registry entries or other form of dependencies. This allows application to be
simply copied from source to the destination directory on the target computer. Because of its simplicity it is often
referred to as XCOPY deployment. XCOPY is a MS DOS copy command.
Integration with the Windows Installer: Windows Installer offers rich capabilities and allows application users
to easily manage the deployed applications. Windows installer supports advertisement, publishing, repair and
install-on-demand when deploying applications. By deploying with Visual Studio we are able to build
deployment projects utilizing Windows Installer.
Private components by default: By default, the components are deployed to the application directory. These
components are visible only to the containing application. Because components are private by default, they have
no impact on other applications.
Side-by-side versioning: The .NET Framework supports the deployment of multiple versions of a component or
an application. We can specify the version of components that our application must use, and the Common
Language Runtime will enforce the versioning policy.
On the fly updates: One of the problems in the past with application update is that every application has to be
manually updated. With .NET applications administrators can use runtime hosts, such as ASP.NET, to update
program DLLs, even on remote computers. This feature enables us to update an application without stopping it.
417
The Complete Reference To Professional SOA with Visual Studio 2005
ClickOnce Deployment: ClickOnce deployment is a new feature in .NET Framework 2.0. The deployment
process is as the name suggests is very simple. It allows the deployment of Windows based client applications to
desktops by placing the application files on a Web server or file server that is accessible to the client.
Enterprise deployment: Using the software installation feature of Active Directory,an administrator can
automatically distribute and install .NET applications on the entire network.
Downloading and caching: .NET Applications and components can take advantage of the downloading and
caching feature which allows incremental downloads of applications to reduce the impact of the deployment
process on the client system. The components can also be isolated for use by the application for zero-impact
deployment.
An assembly’s information includes the version number, name and culture information about the assembly (see
figure 11-1). The common language runtime considers assemblies that contain different version numbers to be
different assemblies. The version number is a four part number consists of major version, minor version, build
number and revision. The format of the version number is:
<major version>.<minor version>.<build number>.<revision>
418
The Complete Reference To Professional SOA with Visual Studio 2005
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.
There are three ways of specifying the assembly version. One way is using the Visual Studio IDE, right mouse
click on our CSEmployeeClient project in the solution explorer, and the properties. We can directly specify the
version of the assembly as shown in Figure 11-1. Select the Application tab then select Assembly Information. A
dialog window will appear. We can specify the version of the assembly by typing the values into the assembly
version section.
The second way is to let Visual Studio automatically increment the version number for us upon each
publication of the project Figure 11-2. Select Publish in the properties section of the project then select the
checkbox for “Automatically increment revision with each publish”.
419
The Complete Reference To Professional SOA with Visual Studio 2005
The third way to specify the assembly version is to modify the AssemblyInfo.cs or AssemblyInfo.vb file. It
can be found when we enable “Show All Files” in solution explorer. Then open the Properties folder under the
project under C# and open the My Project folder under Visual Basic 2005. See Figure 11-3.
The following code shows the attribute that we use to specify the version of an assembly see listing 11-1 and
listing 11-2.
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 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")]
Imports System
Imports System.Reflection
Imports System.Runtime.InteropServices
420
The Complete Reference To Professional SOA with Visual Studio 2005
<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.
421
The Complete Reference To Professional SOA with Visual Studio 2005
At this stage a location dialog window will appear. Visual Studio provides us with several options we can
publish to a local IIS server (figure 11-5), a location on the file system (figure 11-6), a remote FTP site (figure
11-7) or a Remote web location (FrontPage Server Extensions is required) (figure 11-8).
Tip: Click the (…) button on the Publish Web Site dialog window to see the Publish Web Site window below.
Figure 11-5: Select a IIS location Figure 11-6: Select a File System location
422
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 11-7: Select a FTP location Figure 11-8: Select a remote location
In this example we will be publishing to a local IIS server. Select a location to publish (figure 11-5) then select
open. The Publish Web Site dialog window will appear. We can select a location to deploy here.
There are three checks boxes available. The “Allow this precompiled site to be updatable” option allows the
content of the .aspx pages to remain as it is. This allows us to update the HTML code after deploying to a Web
location. This is typically used by ASP.NET Web form application.
The second option is “Use fixed naming and single page assemblies”. This option specifies that we will not
be compiling in batch mode during precompiling as a result we can generate assemblies with fixed names.
The last option is “Enable strong naming on precompiled assemblies”. This option specifies that the
generated assemblies are to be strongly named using a key file. Strong naming a assembly ensures that they will
not be tampered with. If we select this option we can specify a key file or a key container.
After choosing the required options, click OK to continue the deployment process.
423
The Complete Reference To Professional SOA with Visual Studio 2005
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).
The WSDL document for the deployed Web service can be located by appending the ?wsdl after the .asmx
extension (see Figure 11-12).
424
The Complete Reference To Professional SOA with Visual Studio 2005
http://localhost/soawebservice/deploy/employee/employee.asmx?wsdl
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
425
The Complete Reference To Professional SOA with Visual Studio 2005
* 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.
The following table compares the features of ClickOnce deployment with Windows Installer deployment:
Table 11-1: Comparison between ClickOnce deployment and traditional Windows Installer
426
The Complete Reference To Professional SOA with Visual Studio 2005
427
The Complete Reference To Professional SOA with Visual Studio 2005
We should Build the solution first to make sure that everything is in working order first. Click the menu option
to publish our solution. (see figure 11-15).
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.
428
The Complete Reference To Professional SOA with Visual Studio 2005
ClickOnce deployments allows us to deploy applications to a Web site, a Network location or onto a CD-
ROM. In this example we will be deploying to disk, select From a CD-ROM or DVD-ROM. Enter your
preferred location to deploy to. (You will need to have IIS installed for this to work). (see figure 11-16)
Click Next to continue. We will be asked if we want our application to automatically check for updates. We
can specify the location from which the application periodically checks (see figure 11-18).
Figure 11-18: Specify whether the application will check for updates.
Click Next and Finish will automatically deploy the application to file system. We can see the setup files
created in figure 11-19.
429
The Complete Reference To Professional SOA with Visual Studio 2005
Since we are publishing the ClickOnce deployment application to a Web location we will be prompted
whether this application will be available online or offline (see Figure 11-20). The default online or offline
deployment mode will automatically create a start button menu shortcut and an uninstall option in windows. It
will also link our project to a web page location. In this example we will select “yes, this application is available
online or offline” mode. Select Next followed by Finish to publish the application to an online location.
430
The Complete Reference To Professional SOA with Visual Studio 2005
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).
431
The Complete Reference To Professional SOA with Visual Studio 2005
After the deployment manifest is created it is copied to the deployment location. This can be a Web server, a
network file share, or media such as a CD ROM. Application manifest and the application files can also be
copied to the same deployment location or a different location that is specified within the deployment manifest.
When we’re performing the deployment through the Visual Studio 2005 Publishing Wizard the operation is
performed automatically.
After deploying the ClickOnce application to the specified location, the end users can install the application
by clicking on a install icon from the Web page (see Figure 11-21) or from a deployed folder. In most cases, the
end user is presented with a simple dialog box asking the user to confirm installation Figure 11-23, after which
installation proceed and the application is launched without further intervention. In cases where application
requires additional security permissions, the user will be prompted to grant permission before the installation is
allowed to continue.
Once the application has been installed an icon will be added to the user’s Start menu and to the
Add/Remove Programs group in Control Panel. Unlike previous deployment technologies no additional files will
be added under Program Files Folder or records added into the registry or desktop. ClickOnce is a completely
isolated deployment and execution environment.
432
The Complete Reference To Professional SOA with Visual Studio 2005
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.
Location Files
433
The Complete Reference To Professional SOA with Visual Studio 2005
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).
2. Specify a name and location for the project then select OK. By default, the project name is the same as
the Web site with _deploy appended to the name. The default location is in the same folder as the
solution. The project file in our case will be named Employee_deploy.webdeployproj, and the project
folder path will be C:\Projects\Book\SourceCode\Ch11\Employee_deploy.
434
The Complete Reference To Professional SOA with Visual Studio 2005
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.
* Compilation
* Output Assemblies
* Signing
* Deployment
435
The Complete Reference To Professional SOA with Visual Studio 2005
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
Setting Description
Output folder This is folder which will contain the precompiled image of the Web project.
Generate debug information Select this option to generate debug information when compiling. This setting
will also update the <compilation debug="true"/> element in the configuration
file of the precompile Web project.
Use IIS Metabase path for During compilation, if there are sub-Web sites this will result in build errors.
source input By enablying to use IIS Metabase path which will cause the compiler to skip
sub-Web sites defined in the IIS metabase. To compile the sub-Web sites, we
must add a separate Web Deployment project for each of the sub-Web sites.
Allow this precompiled site to This option is used for ASP.NET Web form. It allows HTML component of
be updatable the aspx and ascx pages to be updated after compiling so that only the code-
behind files are compiled.
The Output Assembly page is used to customize precompiled Web project assemblies. The Output
Assembly properties are shown in Table 11-4
436
The Complete Reference To Professional SOA with Visual Studio 2005
Setting Description
Merge all outputs to a single This option merges all output assemblies from the compiler into a single
assembly assembly. This is similar to using the aspnet_merge.exe –o assemblyname
option.
Treat as library component This option will remove the App_code.compiled file. This allows a project’s
App_Code.dll assembly to be added to another Web site without conflict. It
is useful for building a library of .ascx controls. This is equivalent to using
aspnet_merge.exe –r command.
Merge each individual folder This option will create a separation output assembly for each folder. This
output to its own assembly allows us to update a Web Project at the folder level rather than the entire
application.
Merge all pages and controls to a This option merges all output assemblies for all pages and user controls in a
single assembly Web project into a single assembly. We can use the assembly to update UI
components separately.
Create a separate assembly for This option creates separate assemblies for each page and user control.
each page and control output
Version Output Assemblies Selecting Version Output Assembly will enable the Asembly Version and
File Version. We can set the Assembly Version and File Version in the
Assembly Version
following format. The format is 0.0.0.0.
File Version
The version information specified will override the setting information
defined within AssemblyInfo.vb or AssemblyInfo.cs file.
Table 11-4: The table above describes the properties of the Output Assemblies page.
Properties of the signing page are only enabled if we select Enable strong naming see figure 11-30 the
property of the page is shown in Table 11-5. Singing an assembly ensures that the assembly is free from
tempering.
437
The Complete Reference To Professional SOA with Visual Studio 2005
Table 11-5: The table shows the properties within the Signing section.
Setting Description
Key file location After enabling strong naming we can specify a keyfile used for
signing the assembly. We can generate the key file using the
sn.exe utility included with the .NET Framework SDK.
Delay signing Delay signing allow us to compile assemblies with delay signing.
This allows the assemblies to be signed after the build process.
Mark assemblies with This allows types in the strongly named assembly to be called by
AllowPartiallyTrustedCallersAttribute partially trusted code only when the assembly is marked with
(APTCA). AllowPartiallyTrustedCallersAttribute. This removes the
automatic demand for Full trust permission.
The deployment page figure 11-31 is used to customize various deployment configuration. This allows us to
adjust certain configuration in Web.config for deployment setup. We can also automatically create an IIS virtual
directory. Properties for the deployment page is show in table 11-6.
Table 11-6: The following table describes the properties that we can set in the Deployment page.
Setting Description
Enable Web.config file section By enabling the Web.config file section replacement we can replace any
replacement section in the root Web.config file with the matching content in a separate
external .config file. We can use this option to provide configuration
settings for the deployed environment.
438
The Complete Reference To Professional SOA with Visual Studio 2005
Enforce matching section This option requires that the specified section in the Web.config file
replacements matches the number of elements in the external .config file. A build error
occurs if the two do not match.
Use external configuration source file This option is useful for changing database connecting strings or
references for different build configurations.
This option replaces elements using configSource reference with .config
file. configSource attribute can be in the format of:
<appSettings configSource="appSettings.config" />
If this option is not selected the entire section is replaced with the .config
file.
Create an IIS virtual directory for the This option when selected will automatically create an IIS virtual directory
output folder that will point to the output folder for the specified build configuration. To
avoid conflict we should adopt the naming convention for example such as
MyWeb_Staging and MyWeb_Release.
Replace the existing virtual directory This option allows us to replace an existing virtual directory. For example
if a virtual directory already exists we can override it to point to a different
output location.
Remove the App_Data folder from This option removes the App_Data from the precompiled image of the
the output location Web project. This is useful if we’re not requiring a SQL Server Express,
Access or MSDE in the App_Data folder.
* Debug build configuration. Debug build is commonly used by developers during design time to test and
check the Web Application. In a typical team development enivornment when multiple developers are working
on the same project. To avoid impacting development and overwriting each other’s code each developer can set
their own custom settings for their development environment. These may be local resources such as a local
SQL Server database, or a local IIS Web reference which points to http://localhost/....
* Staging build configuration. The staging environment is often a replica of the production or release
environment. We can adjust our configurations to connect to the staging environment. This may mean rather
than connecting to a local database during the debug build we may be connecting to a shared database
containing test data. While Web services and Web Form applications may also be distributed onto different
servers in the staging environment.
* Release build configuration. The Web project is deployed onto a production release environment after it has
been thoroughly tested on the staging environment. The release build means we would no longer require the
debug information that may have been required on the staging build. We can adjust the Debug mode within the
Web.config file by setting it to false.
439
The Complete Reference To Professional SOA with Visual Studio 2005
The benefit of using the Web Deployment projects is that it allows us to add and customize so many
differerent variables for each of the specific builds. We can tailor our environment variables into each of the
build configuration. This helps to lower the risk of deployment errors from misconfigured environment settings.
The property values that we specify within Web deployment project apply only to the specific build
configuration. We can easily change a build configuration for a specific build by changing the required property.
For global properties we can also select All Configurations, which we can apply to change settings globablly
across all configurations.
To change or create a new configuration, in the project Property Page dialog window select Configuration
Manager. The Configuration Manager dialog window will appear (see figure 11-32). By selecting Active
solution configuration drop down list and selecting <New…> we can define a build option for deployment. The
Configuration Manager dialog box allow us to create new configurations and to specify which projects to build
as part of that configuration.
In the following example we will create a setting for staging. By selecting <New…> under Active Solution
Configuration. A dialog window will appear (see figure 11-33). We will be prompted to set the name of the
configuration. We can also simplify the configuration process by letting the configuration manager to copy
existing settings defined for Release. Once complete select OK.
440
The Complete Reference To Professional SOA with Visual Studio 2005
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).
Tip: We should also remember to disable building the Web Deployment project in the Debug configuration. Building a Web Deployment
project unnecessarily increases the time it takes to build a solution or start a debug session. We should enable building the Web
Deployment project only in solution configurations intended for deployment builds.
When we sepecify the build configurations we should keep in mind that build configuration for Web projects
should be optimized for developers productivity. When we create our solution configurations, we should build
441
The Complete Reference To Professional SOA with Visual Studio 2005
either the Web site project or the Web Deployment project, but not both. See table 11-7 for suggestion towards
different build solution configurations.
Solution configuration
To specify the solution configuration to use when we build, select the configuration name from the Solution
Configurations list on the toolbar:
When we have our build configurations established, we can initiate a build for any configuration. There are two
ways to build a Web Deployment project from within Visual Studio 2005 or from the command line using
MSBuild.
The files generated for this build are in the MyWeb_deploy\Release folder. Note the single output assembly
MyCompany.MyWeb.dll.
Location Files
C:\Projects\Book\SourceCode\Ch11\Employee_deploy\Re Employee.asmx
lease
PrecompiledApp.config
web.config
C:\Projects\Book\SourceCode\Ch11\Employee_deploy\Re App_Code.compiled
lease\bin
Employee_deploy.dll
442
The Complete Reference To Professional SOA with Visual Studio 2005
The following are guidelines for choosing the right type of deployment project for our project (see Table 11-9).
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.
2. In the Add New Project dialog box, select “Setup and Deployment Projects” under the Project Types pane
(Figure 11-36).
443
The Complete Reference To Professional SOA with Visual Studio 2005
Note: The screenshot may vary depending on the edition of Visual Studio
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).
5. Once the Setup web project has been added to the existing Employee Web service project. Right click on the
setup project in the solution explorer. Select Add-> Project Output from the context menu (Figure 11-38).
444
The Complete Reference To Professional SOA with Visual Studio 2005
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.
445
The Complete Reference To Professional SOA with Visual Studio 2005
7. As shown in Figure 11-40 the precompiled web deployment output from Employee_deploy is now attached to
the WSEmployeeSetup project.
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.
9. By building the setup project the two setup files will be created automatically. One of the file will be an EXE
setup file while the other is a MSI file (Figure 11-42).
446
The Complete Reference To Professional SOA with Visual Studio 2005
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.
447
The Complete Reference To Professional SOA with Visual Studio 2005
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.
448
The Complete Reference To Professional SOA with Visual Studio 2005
If we set the BufferResponse property to False, ASP.NET buffers the responses in chunks of 16 KB each.
The response to the XML Web service method is sent back to the client as it is serialized. The default value of
the BufferResponse property is True. The following Microsoft Visual Basic .NET and Microsoft Visual C# code
samples show how to use the BufferResponse property (see listing 12-1 and listing 12-2).
Listing 12-1. Demonstrates a program using Buffered and Unbuffered properties in Web service. Using C#
using System;
using System.IO;
using System.Collections;
using System.Xml.Serialization;
using System.Web.Services;
using System.Web.Services.Protocols;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service {
[WebMethod(BufferResponse=true)]
public TextFile GetFileBuffered(string filename) {
return new TextFile(filename);
}
[WebMethod(BufferResponse=false)]
public TextFile GetFileUnbuffered(string filename)
{
return new TextFile(filename);
}
public TextFile() {
}
[XmlArrayItem("line")]
public TextFileReaderWriter contents {
get {
readerWriter = new TextFileReaderWriter(filename);
return readerWriter;
}
}
449
The Complete Reference To Professional SOA with Visual Studio 2005
}
}
public TextFileReaderWriter() {
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
450
The Complete Reference To Professional SOA with Visual Studio 2005
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
<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
<XmlArrayItem("line")> _
451
The Complete Reference To Professional SOA with Visual Studio 2005
End Sub
End Class
452
The Complete Reference To Professional SOA with Visual Studio 2005
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.
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.
using System.Web.Services;
453
The Complete Reference To Professional SOA with Visual Studio 2005
using System;
using System.Web;
[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;
}
Listing 12-4: The above codes demonstrates the CacheDuration properties Visual Basic 2005
Imports System.Web.Services
Imports System
Imports System.Web
<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
The above code listing 12-3 and listing 12-4 sets the CacheDuration property of the ServiceUsage Web
method to 60 seconds. When the CacheDuration is set ASP.NET will cache the request response based on the
454
The Complete Reference To Professional SOA with Visual Studio 2005
parameters. In this case the response of how frequently the application has been invoked is cached for a period of
60 seconds.
There are two issues that can affect output caching in an ASP.NET 2.0 Web service application.
In ASP.NET 2.0 the HTTP method of the test page has changed from GET to POST. However, POSTs are
not normally cached. If we change the test page in an ASP.NET 2.0 Web service application to use GET,
caching will work properly. As a such we cannot test the Web method directly from the test page. There is a
windows form project called TestCacheClient with the source code which allow us to test caching using SOAP
see Listing 12-5 and Listing 12-6. From the test application we can see that the result to the user request is
cached for 60 seconds.
In addition, HTTP indicates that a user agent (the browser or calling application) should be able to override
server caching by setting the "Cache-Control" to "no-cache". ASP.NET applications, therefore, ignore cached
results when they find a "no-cache" header.
The example below demonstrates the main logic within TestCacheClient. The application calls the web service
and invokes the ServiceUsage WebMethod using SOAP (see Listing 12-5 and Listing 12-6).
using System;
using System.Web.Services;
Imports System
Imports System.Web.Services
455
The Complete Reference To Professional SOA with Visual Studio 2005
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.
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>
456
The Complete Reference To Professional SOA with Visual Studio 2005
In listing 12-9 and listing 12-10 , we have decorated WebMethod with EnableSession property set to true.
This allows our WebMethod to access the underlying state management provided by ASP.NET.
using System.Web.Services;
Imports System.Web.Services
To consume a WebMethod using session we need to specify a session container to enable the application to keep
track of the Web service session. Using CookieContainer allows us to persist data within the same session. See
listing 12-11 and listing 12-12.
457
The Complete Reference To Professional SOA with Visual Studio 2005
Note: If we do not wish to persist data for the web service call we do not to implement support for cookie on the client application.
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();
}
}
}
Module Module1
Sub Main()
Dim cookieJar As System.Net.CookieContainer = _
New System.Net.CookieContainer
End Module
458
The Complete Reference To Professional SOA with Visual Studio 2005
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.
using System;
using System.Web.Services;
Imports System
Imports System.Web.Services
' The MessageName property defaults to Add for this XML Web service method.
<WebMethod()> _
Public Function Multiply(ByVal i As Integer, ByVal j As Integer) As Integer
Return i * j
End Function
459
The Complete Reference To Professional SOA with Visual Studio 2005
<WebMethod(MessageName:="Multiply2")> _
Public Function Multiply(ByVal i As Integer, ByVal j As Integer, ByVal k As Integer) As Integer
Return i * j * k
End Function
End Class
In the example above listing 12-13 and listing 12-14 we have a WebMethod which is overloaded with
another WebMethod. In Web service it is not possible to have two WebMethods of the same name. This results
in a conflict. One way around this is through the use of MessageName to specify an alias name. This helps to
distinguish between the two WebMethods. See Figure 12-2.
Item Description
Disabled By setting the TransactionOption state to Disabled the WebMethod will be executed without
460
The Complete Reference To Professional SOA with Visual Studio 2005
support for transaction. Any transaction in the current context will be ignored.
[WebMethod(TransactionOption= TransactionOption.Disabled)]
NotSupported The NotSupported state indicates that the WebMethod will not run within the scope of a
transaction. The WebMethod will be executed in a context with no governing transaction.
[WebMethod(TransactionOption= TransactionOption.NotSupported)]
Supported The Supported state indicates that the WebMethod will share a transaction if it exists.
[WebMethod(TransactionOption= TransactionOption.Supported)]
Required The Required state indicates that the WebMethod requires a transaction. A new transaction
will be created for the WebMethod if no transaction exists otherwise if transaction exist it
will be shared.
[WebMethod(TransactionOption= TransactionOption.Required)]
RequiresNew The RequiresNew state indicates that the WebMethod requires a new transaction regardless
of the state of the current context. When a request is received the WebMethod is created
within a new transaction.
[WebMethod(TransactionOption= TransactionOption.RequiresNew)]
XML Web service transactions can only participate in Transactions as the root of a new transaction. XML
Web service methods that call other XMLWeb service methods participate in different transactions. This is
because transactions do not flow across XML Web service methods.
When using transactions with ASP.NET XML Web service we can declare the Web method’s transactional
behavior by setting the TransactionOption property of the WebMethod Attribute. If an exception is thrown while
the WebMethod is executing the transaction is automatically aborted otherwise if no exception occurs the
transaction is automatically committed.
To enable Web methods to support transactions, we need to add reference to the System.EnterpriseServices
namespace. This namespace contains the methods and properties that expose the distributed transaction model in
COM+ services. The ContextUtil class of the System.EnterpriseServices namespace allows us to control a
transaction using the SetAbort or SetComplete method.
The following example listing 12-15 and listing 12-16 demonstrates using TransactionOption.
using System;
using System.Web.Services;
using System.EnterpriseServices;
461
The Complete Reference To Professional SOA with Visual Studio 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
462
The Complete Reference To Professional SOA with Visual Studio 2005
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):
We will use this delegate to wrap around a Web service method that is called VerySlowWSFunction(). Every
time we define a delegate such as VerySlowWebMethodAsyncDelegate a custom delegate class is generated and
added to our assembly. The reason is because the code for each delegate is different, depending on the signature
of the method we define.
Through out the examples in this section we will be using the WebMethod VerySlowWSFunction() (see
listing 12-19 and listing 12-20).
463
The Complete Reference To Professional SOA with Visual Studio 2005
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 () {
}
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
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.
464
The Complete Reference To Professional SOA with Visual Studio 2005
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace CSTestAsyncClientBegin
{
public delegate string VerySlowWebMethodAsyncDelegate();
465
The Complete Reference To Professional SOA with Visual Studio 2005
In listing 12-21 and listing 12-22 we have created a delegate named VerySlowWebMethodAsyncDelegate, this
delegate takes no parameters and has a return type of string. This is to match the parameter and return type of our
WebMethod. We then create an object of the delegate by passing in the WebMethod that we’re interested in.
This will allow the delegate to wrap around the WebMethod. See listing 12-23 and listing 12-24 below.
VerySlowWebMethodAsyncDelegate veryslowWebMethod =
new VerySlowWebMethodAsyncDelegate(wsa.VerySlowWSFunction);
Listing 12-24. Allowing delegate to wrap around a function in Visual Basic 2005
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).
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();
}
WSAsync.Service wsAsyncService =
new CSTestAsyncClient.WSAsync.Service();
String result = wsAsyncService.VerySlowWSFunction();
ComplexTimeconsumingLogic();
466
The Complete Reference To Professional SOA with Visual Studio 2005
this.labelSynchTimeTaken.Text =
((TimeSpan)DateTime.Now.Subtract(starttime)).TotalSeconds.ToString();
MessageBox.Show(result);
}
this.labelAsyncTimetaken.Text =
((TimeSpan)DateTime.Now.Subtract(starttime)).TotalSeconds.ToString();
MessageBox.Show(result);
}
Imports System.Threading
467
The Complete Reference To Professional SOA with Visual Studio 2005
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.
468
The Complete Reference To Professional SOA with Visual Studio 2005
Listing 12-30. Wrapping the delegate around the VerySlowWSFunction WebMethod in Visual Basic 2005
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-32. Using BeginInvoke() and EndInvoke() using Visual Basic 2005
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-34. Catching errors for EndInvoke() using Visual Basic 2005
469
The Complete Reference To Professional SOA with Visual Studio 2005
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);
}
470
The Complete Reference To Professional SOA with Visual Studio 2005
object, we can call WaitAll() to wait until all our asynchronous operations are complete. See listing 12-37 and
listing 12-38.
The following example uses this technique to call the our VerySlowWSFunction() method four times at once.
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;
WaitHandle[] waitHandles = {
handle.AsyncWaitHandle,
handle1.AsyncWaitHandle,
handle2.AsyncWaitHandle,
handle3.AsyncWaitHandle};
// perform some very length calculation in the main application
ComplexTimeconsumingLogic();
471
The Complete Reference To Professional SOA with Visual Studio 2005
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
472
The Complete Reference To Professional SOA with Visual Studio 2005
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.
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).
473
The Complete Reference To Professional SOA with Visual Studio 2005
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using CSTestAsyncClient.WSAsync;
namespace CSTestAsyncClient
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
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);
}
wsAsyncService.VerySlowWSFunctionCompleted +=
new CSTestAsyncClient.WSAsync.
VerySlowWSFunctionCompletedEventHandler
(VerySlowWSFunctionCompleted);
wsAsyncService.VerySlowWSFunctionAsync();
this.labelAsyncTimetaken.Text =
474
The Complete Reference To Professional SOA with Visual Studio 2005
((TimeSpan)DateTime.Now.Subtract(starttime)).
TotalSeconds.ToString();
}
Imports System.Threading
Me.labelSynchTimeTaken.Text = _
CType(DateTime.Now.Subtract(starttime), TimeSpan) _
.TotalSeconds.ToString()
MessageBox.Show(result)
End Sub
475
The Complete Reference To Professional SOA with Visual Studio 2005
New VBTestAsyncClient.WSAsync.Service
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.
wsAsyncService.VerySlowWSFunctionCompleted += new
CSTestAsyncClient.WSAsync.VerySlowWSFunctionCompletedEventHandler(VerySlowWSFunctionCompleted);
Listing 12-42. Asynchronous implementation using events using Visual Basic 2005
AddHandler wsAsyncService.VerySlowWSFunctionCompleted, _
New VBTestAsyncClientWinForm.WSAsync.VerySlowWSFunctionCompletedEventHandler(AddressOf
VerySlowWSFunctionCompleted)
This implementation is extremely useful in Windows application because it allows the UI to remain
responsive whilst the asynchronous thread did the work. Once the results are obtained by the Asynchronous
thread the UI can be updated with the new results.
476
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 12-6. Shows the difference of using Asynchronous implementation with event and that of synchronous implementation.
In Figure 12-6 we can see that the asynchronous implementation utilizing events has returned immediately
after the button has been pressed and thus allowing the UI to continue work and thus remain responsive. This is
particularly important in distributed systems where latency between request and response greatly varies.
Soap Extensions
A XML Web service sends and receives data from clients in the form of SOAP messages. These SOAP
messages can consist of information about a certain operation or about the result of an operation. Whenever a
client requires information from the server that hosts the XML Web service, the client sends a SOAP request to
the server. The SOAP request should be in compliance with a format that the XML Web service understands.
The XML Web service processes the SOAP request and sends a response to the client. The client receives the
SOAP response, interprets it, and performs a specified operation. If we need to access and modify the SOAP
messages that are exchanged between an XML Web service and its clients, we can use SOAP extensions.
SOAP extensions enable us to access and modify the SOAP messages that are exchanged between the client
and the XML Web service. For example, we can use SOAP extensions to validate the SOAP message before it
reaches the XML Web service and change the SOAP message after validation so that the XML Web service
receives a valid SOAP request. We can also implement an encryption or compression algorithm that can be
executed within an existing XML Web service by using SOAP extensions.
In ASP.NET architecture see figure 12-7 when ever IIS receives a request, the extension is mapped to an
ISAPI filter according to the IIS settings. The .NET extension types .aspx, .asmx, .asx and other file types are
mapped to the aspnet_isapi.dll which is simply an ISAPI filter that launches the ASP.NET runtime. The
477
The Complete Reference To Professional SOA with Visual Studio 2005
ASP.NET Runtime then launches the relevant Web service application and executes the SOAP Extensions
before passing the request into the relevant web service.
ASP.NET SOAP extensions are implemented by classes deriving from the SoapExtension class. They allow
us to intercept messages and modify the corresponding streams. We can easily implement SOAP extension by
overriding a few simple functions.
The basis of SOAP extensions is the SoapExtension class. The main methods of concern are ChainStream(),
GetInitializer(), Initialize(), and ProcessMessage(). The ChainStream() helps to capture the message stream within
the SOAP call. The GetInitializer() and Initialize() are used to provide a means of initialization. While the
ProcessMessage() method is the heart of the extension where most of the development attention goes.
* 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.
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:
Name Description
ChainStream This method when overridden allows a SOAP extension to access memory buffer that contains the SOAP request or
response.
GetInitializer This method when overridden allows a SOAP extension to initialize a one time only data specific to a XML Web service.
Initialize This method when overridden allows a SOAP extension to initialize itself using the data cached in the GetInitilizer
method.
ProcessMessage This method when overridden allows a SOAP extension to receive a SoapMessage to process at each SoapMessageStage.
We will now create a Web service which provides an Add WebMethod. We will use overridable methods
from SoapExtension class to implement a SOAP logging application to monitor the SOAP exchange performed
on the Add WebMethod (see listing 12-43 and listing 12-44).
478
The Complete Reference To Professional SOA with Visual Studio 2005
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;
479
The Complete Reference To Professional SOA with Visual Studio 2005
480
The Complete Reference To Professional SOA with Visual Studio 2005
fs.Close();
}
break;
}
return;
}
}
481
The Complete Reference To Professional SOA with Visual Studio 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"
482
The Complete Reference To Professional SOA with Visual Studio 2005
Inherits SoapExtension
Private LogFile As String = ""
Private SoapStream As Stream
Private TempStream As Stream
483
The Complete Reference To Professional SOA with Visual Studio 2005
FileMode.Append, FileAccess.Write)
Dim sw As StreamWriter = New StreamWriter(fs)
sw.WriteLine("** BEGIN SOAP RESPONSE: {0}", _
DateTime.Now)
sw.Flush()
TempStream.Position = 0
CopyTextStream(TempStream, fs)
sw.WriteLine("** END SOAP RESPONSE")
sw.Flush()
TempStream.Position = 0
CopyTextStream(TempStream, SoapStream)
fs.Close()
End Select
Return
End Sub
End Class
End Namespace
The above code shows the SOAP logger library. In order to use the SOAP logger we need to have a Web
service for the SOAP extensions to work with. Below is a Web service which performs addition operations (see
listing 12-45 and listing 12-46).
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.IO;
using Logging;
[WebService(Namespace = "http://tempuri.org/")]
public class Service : System.Web.Services.WebService
{
public Service () {
}
[WebMethod]
[SoapLogger]
public int Add(int x, int y) {
return x + y;
}
Listing 12-46. Web service which performs addition Visual Basic 2005
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
484
The Complete Reference To Professional SOA with Visual Studio 2005
Imports Logging
<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class Service
Inherits System.Web.Services.WebService
<WebMethod()> _
<SoapLogger()> _
Public Function Add(ByVal x As Integer, _
ByVal y As Integer) As Integer
Return x + y
End Function
End Class
Now we will look at the structure of the SOAP extensions code. We will start by inheriting from the SoapExtension
class (see listing 12-47 and listing 12-48),
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).
485
The Complete Reference To Professional SOA with Visual Studio 2005
There is also another version of GetInitializer() the reason is that SOAP extension can be loaded in two
ways. One way is through the attribute for the WebMethod the other way is to specify it within the Web.Config
file. We will be looking at this a little later (see listing 12-51 and listing 12-52).
Listing 12-52. GetInitializer used by the Web.Config load implementation file Visual Basic 2005
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.
486
The Complete Reference To Professional SOA with Visual Studio 2005
{
// this method will be called several times during
// the processing of a SOAP request. The
// ASP.NET system tells us which stage the
// SOAP request is at with the Stage property
// of the SoapMessage class
switch (message.Stage)
{
case SoapMessageStage.BeforeDeserialize:
{
// copy the SOAP request from the
// network stream into our memory buffer
CopyTextStream(SoapStream, TempStream);
FileStream fs = new FileStream(LogFile,
FileMode.Append, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine("** BEGIN SOAP REQUEST: {0}",
DateTime.Now);
sw.Flush();
487
The Complete Reference To Professional SOA with Visual Studio 2005
TempStream.Position = 0;
CopyTextStream(TempStream, SoapStream);
fs.Close();
}
break;
}
return;
}
488
The Complete Reference To Professional SOA with Visual Studio 2005
back to the beginning of the stream. If we don’t take this step, a deserialization error will occur. Notice we have
copied the stream using the CopyTextStream method then write it to a file before reseting the
TempStream.Postion back to 0 (see listing 12-57 and listing 12-58).
[AttributeUsage(AttributeTargets.Method)]
489
The Complete Reference To Professional SOA with Visual Studio 2005
<AttributeUsage(AttributeTargets.Method)> _
Public Class SoapLoggerAttribute
Inherits SoapExtensionAttribute
Private _priority As Integer = 0
Private _logFile As String = "C:\soap.log"
490
The Complete Reference To Professional SOA with Visual Studio 2005
End Property
End Class
XML Web service methods created using ASP.NET can be configured to run with a SOAP extension by
applying an attribute to the XML Web service method. When a custom extension attribute is added to an XML
Web service method, ASP.NET calls the associated extension at the appropriate time. An extension attribute is a
custom attribute class deriving from SoapExtensionAttribute. Derived attributes must override the ExtensionType
property to return the type of extension that is associated with the attribute.
Using SoapLogger
There’s two ways to enable our SOAP Extensions. One way is to enable the SOAP extension through using an
attribute (see listing 12-63 and listing 12-64).
[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).
<webServices>
<soapExtensionTypes>
<add type="Logging.SoapLogger, Logging" priority="1" group="0" />
</soapExtensionTypes>
</webServices>
Tip: We cannot test the SOAP extensions using the asmx autogenerated test harness for web method. There is a
TestSOAPExtensionsClient application on the source CD which we can use to test the SOAP extensions. Its also important to remember
that we need to start the Web service first, we may also need to adjust the port number for the web service within the client application as
the web service will be running off the ASP.NET Development Server Environment for file system web applications.
The client code that we use call the Web service is as how we would call a normal Web service (see listing
12-66 and listing 12-67).
491
The Complete Reference To Professional SOA with Visual Studio 2005
NOTE: Please give the correct privileges to the Web Service so that the log file can be written to the hard drive.
Summary
In this chapter, we have looked at a variety of advanced SOAP techniques; these include using various
WebMethod properties, implementing web services using asynchronously implementations, and how to use
SOAP extensions.
We have also examined WebMethod properties these are BufferResponse, CacheDuration, Description,
EnableSession, MessageName, TransactionOption.
In this chapter we have also looked at asynchronous implementation which is used to allow applications to
execute a method without waiting for it complete. This is very useful in a distributed architecture, because the
492
The Complete Reference To Professional SOA with Visual Studio 2005
inherent nature of the internet, the response time between request and response can vary greatly. As such we do
not want our program to wait for the method to return.
The last thing we have looked at is SOAP extensions. SOAP extensions enable us to access and modify the
SOAP messages that are exchanged between the client and the XML Web service. For example, we can use
SOAP extensions to validate the SOAP message before it reaches the XML Web service and change the SOAP
message after validation so that the XML Web service receives a valid SOAP request. We can also implement an
encryption or compression algorithm that can be executed within an existing XML Web service by using SOAP
extensions.
493
The Complete Reference To Professional SOA with Visual Studio 2005
Table 13-1. The table below outlines differences between .NET Remoting and Web services.
.NET Web services are typically accessed over .NET Remoting can be used across three channels
HTTP. TCP, HTTP, IPC. and two formatters SOAP and
Binary.
Web services work in a stateless environment. Each .NET Remoting supports state management options
request results in a new object created to service the and can associate multiple calls from the same
request. client. Remoting model also support Asynchronous
callbacks.
Web services serialize objects into XML that is .NET Remoting relies the Common Language
contained in the SOAP message and as such can Runtime assemblies that contain information about
only handle items that can be fully expressed in data types. This allows objects to be passed by value
XML. or by reference.
Web services are interoperable across platforms and .NET Remoting can only be created using .NET
are good for environment that consists of different
technologies but are required to work together.
In the world of SOA .NET remoting may not be ideal for public facing as it is not as interoperable as Web
service. However we can use .NET remoting internally within an architecture to improve the performance of
communication between .NET to .NET applications.
494
The Complete Reference To Professional SOA with Visual Studio 2005
the client can call methods on the server object as if the object resides in the client's process. This process of
invoking methods on the server is very much like how we invoke methods of Web services.
.NET Remoting uses proxy objects to allow the use of the server object in the client process. When we
create an instance of the remote object type in the client application, .NET Remoting creates a proxy object and
sends it to the client application. This proxy object contains references to all the methods and properties of the
server object. When a call is made on the proxy object, the remoting system receives the call and routes the call
to the server process. This invokes the server object, which then returns the result to the client proxy. The client
proxy then in turn return the result to the client application (see figure 13-1). The .NET Remoting architecture is
quite flexible we can use different transport protocols such as HTTP, TCP and IPC we can also communicate
using different formatters such as SOAP and Binary.
Marshal-by-value Objects
In marshal-by-value objects are copied by the Remoting system and passed in their entirety to the caller’s
application domain. Once the objects are copied to the caller’s application domain, all method calls and property
accesses are executed entirely within the domain of the calling application. Since the entire object exists in the
caller’s domain, there is no need to marshal access across domain boundaries. Marshal-by-value is ideal for
small objects because smaller objects increase performance by reducing network traffic especially if the objects
needs to be accessed frequently. However because the object exists in the caller application domain, no state
change to the object will be reflected to the originating application domain or from the originator back to the
495
The Complete Reference To Professional SOA with Visual Studio 2005
caller. Marshal-by-value is not ideal for large objects which need to be accessed frequently. We should also keep
in mind to only marshal the field, method or property that we really need to access. This will dramatically reduce
the network requirements.
We create a marshal-by-value object by decorating the class with the [Serializable] attribute see listing 13-1
and listing 13-2.
using System;
namespace RemotingSamples {
[Serializable]
public class MarshalByValue {
<Serializable()> _
Public Class MarshalByValue
Dim mValue As Integer = 1
In the listing above we have defined a MarshalByValue class which is flagged with the [Serializable]
attribute. This allows the class to be serialized and streamed to and from the server. Additionally, implementing
the ISerializable interface gives us an opportunity to plug into the standard marshalling formatters.
496
The Complete Reference To Professional SOA with Visual Studio 2005
Marshal-by-reference Objects
In marshal-by-reference when a client instantiates a marshal-by-reference object the .NET Remoting
infrastructure creates a proxy object in the caller application domain and returns the reference of that proxy to
the caller. When the client makes calls on the object through the proxy, the Remoting infrastructure marshals the
calls, and sends them to the originator’s application domain. The application domain then invokes the call on the
actual object. The return value from the call and or any out parameters are handled similarly on the way back.
We should use marshal-by-reference objects when the state of the object and any executable functionality
must remain in the application domain in which it was created (that is, on the server).
using System;
namespace RemotingSamples {
Imports System
Namespace RemotingSamples
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.
497
The Complete Reference To Professional SOA with Visual Studio 2005
activated. We have to be aware of how remote objects are activated. We need to specify to the remoting system
what type of activation is required on the objects before the remoting system provides these objects to the clients.
There’re two groups Server Activated Objects (SAOs) and Client-Activated Objects (CAOs).
* 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.
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);
498
The Complete Reference To Professional SOA with Visual Studio 2005
"ValidateRegistration",
WellKnownObjectMode.Singleton);
System.Console.WriteLine
("Press the enter key to exit...");
System.Console.ReadLine();
}
}
}
Listing 13-6. Shows an implementation of Remoting server using WellKnownObjectMode.Singleton in Visual Basic 2005
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp
Imports VBSampleObject
Namespace InsuranceServer
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.
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(InsuranceOperation),
"ValidateRegistration",
WellKnownObjectMode.SingleCall);
499
The Complete Reference To Professional SOA with Visual Studio 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.
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");
}
Imports System
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
500
The Complete Reference To Professional SOA with Visual Studio 2005
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.
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);
501
The Complete Reference To Professional SOA with Visual Studio 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
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.
502
The Complete Reference To Professional SOA with Visual Studio 2005
Listing 13-13. Shows the xml configuration RemoteServerConfig.xml file for the above remoting server implementation.
In the above configuration file, RemoteServerConfig.xml, all of the remoting configurations must be added
as child elements to <system.runtime.remoting>. The <application> element defines the name of the application.
The service that is offered from the application must be listed as a child of <service>. This is where we define
the remote object itself. The remote object is defined within the <wellknown> element. Here we need to define
the name of the assembly where the type of this object can be loaded from this is defined in the <type> element.
The last property in the <wellknow> object is the objectUri. objectUri is a name that is assigned to the object
which will be used by the client. The mode attribute is set to SingleCall. If Singleton is required we simply alter
the mode to Singleton:
<service>
<wellknown
mode="Singleton"
type="InsuranceOperation, InsuranceOperation"
objectUri="ValidateRegistration" />
</service>
Once the configuration file has been defined all that the application needs to do is read the configuration file
to activate the channel by using the static method RemotingConfiguration.Configure().
503
The Complete Reference To Professional SOA with Visual Studio 2005
Listing 13-14. The listing below shows the C# implementation of the remoting server
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
namespace InsuranceServer
{
public class VehicleDetailsServer : MarshalByRefObject
{
public static void Main(string[] args)
{
RemotingConfiguration.Configure
("RemoteServerConfig.xml", false);
System.Console.WriteLine
("Press the enter key to exit...");
System.Console.ReadLine();
}
}
}
Listing 13-15. The listing below shows the Visual Basic 2005 implementation of the remoting server
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp
Namespace InsuranceServer
504
The Complete Reference To Professional SOA with Visual Studio 2005
Creating a client using configuration file is as simple as creating the server with configuration. Here we will
create a client using a configuration file.
Listing 13-16. Shows RemoteClientConfig.xml which contains the client configuration for remoting.
The XML client configuration file RemoteClientConfig.xml uses the <client> element to specify the
interested remote server object. Under <client> we can specify the URL of the server using
protocol://hostname:port/application. In the example we had illustrated we have used tcp as the protocol, and the
server runs on localhost with the port number 3080. The application name of the server is defined with the name
attribute of the <application> element in the server configuration file.
The <wellknown> element specifies the remote object we want to access. As in the server configuration file,
the type attribute defines the type of the remote object and the assembly. The url attribute defines the path to the
remote object. Appended to the URL of the application is the endpoint name ValidateRegistration. The channel
that is configured with the client can again be found in the configuration file machine.config, but this time it is
the client channel and thus specified as “tcp client”.
Let us have a look at the code required to load the configuration settings for the client.
Listing 13-17. Shows the C# code for a remoting client using configurations
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting;
namespace InsuranceClient
{
class Client
{
public static void Main(string[] args)
{
RemotingConfiguration.Configure
("RemoteClientConfig.xml", true);
InsuranceOperation obj = new InsuranceOperation();
505
The Complete Reference To Professional SOA with Visual Studio 2005
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
If obj.Equals(Nothing) Then
System.Console.WriteLine _
("Error: unable to locate server")
Else
Console.WriteLine(obj.ValidateRegistration("xyz-123"))
End If
Console.ReadLine()
End Sub
End Class
End Namespace
As in the server, we can activate the client channel by calling the RemotingConfiguration.Configure(). Using
configuration files we can simply use new to create the remote object. By using new the remoting framework
will automatically reference the remote object for us. Any call made to the reference will be automatically
marshaled to the server.
506
The Complete Reference To Professional SOA with Visual Studio 2005
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Activation;
namespace InsuranceServer
{
public class VehicleDetailsServer : MarshalByRefObject
{
public static void Main(string[] args)
{
TcpServerChannel channel = new TcpServerChannel(9080);
ChannelServices.RegisterChannel(channel, true);
RemotingConfiguration.ApplicationName =
"ValidateRegistration";
RemotingConfiguration.RegisterActivatedServiceType
(typeof(InsuranceOperation));
System.Console.WriteLine
("Press the enter key to exit...");
System.Console.ReadLine();
}
}
}
Listing 13-20. Client Activated Object server implementation using Visual Basic 2005
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp
507
The Complete Reference To Professional SOA with Visual Studio 2005
Imports System.Runtime.Remoting.Activation
Namespace InsuranceServer
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.
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
/// <remarks>
/// Sample object to demonstrate the use of .NET Remoting.
/// </remarks>
public class InsuranceOperation : MarshalByRefObject
{
/// <summary>
508
The Complete Reference To Professional SOA with Visual Studio 2005
/// Constructor
/// </summary>
///
public InsuranceOperation()
{
Console.WriteLine("Constructor has been called");
}
Listing 13-24. Client Activated Object InsuranceOperation using Visual Basic 2005
Imports System
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
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.
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting;
509
The Complete Reference To Professional SOA with Visual Studio 2005
using System.Runtime.Remoting.Activation;
namespace InsuranceClient
{
class Client
{
static void Main(string[] args)
{
TcpClientChannel channel = new TcpClientChannel();
ChannelServices.RegisterChannel(channel, true);
object[] attrs = {
new UrlAttribute(
"tcp://localhost:9080/ValidateRegistration") };
InsuranceOperation obj =
(InsuranceOperation)Activator.CreateInstance(
typeof(InsuranceOperation), null, attrs);
// Use the object
if (obj.Equals(null))
{
System.Console.WriteLine
("Error: unable to locate server");
}
else
{
Console.WriteLine(
obj.ValidateRegistration("xyz-123"));
}
Console.ReadLine();
Console.WriteLine();
}
}
}
Listing 13-26. Client Activated Object client implementation using Visual Basic 2005
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp
Imports System.Runtime.Remoting.Activation
Imports VBSampleObject
Namespace InsuranceClient
Class Program
510
The Complete Reference To Professional SOA with Visual Studio 2005
"tcp://localhost:9080/ValidateRegistration")}
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.
The above figure shows an image of the response from the server. We can see that our server is started and when
a request is received the InsuranceOperation’s constructor is executed. Whilst the constructor has also been
executed on the server window shows that the reference call from the client had been marshaled to the server
where it is executed.
511
The Complete Reference To Professional SOA with Visual Studio 2005
In the above diagram, the client window shows the response from invoking the validation function on the server.
RemotingConfiguration.Configure
("RemoteClientConfig.xml", true);
InsuranceOperation obj = new InsuranceOperation();
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.
RemotingConfiguration.Configure
("RemoteServerConfig.xml", false);
RemotingConfiguration.Configure _
("RemoteServerConfig.xml", True)
Though the XML configuration which defines client activated code is slightly different.
512
The Complete Reference To Professional SOA with Visual Studio 2005
mode="SingleCall"
type="InsuranceOperation, InsuranceOperation"
objectUri="ValidateRegistration" />
</service>
<channels>
<channel ref="tcp server" port="3080" />
</channels>
</application>
</system.runtime.remoting>
</configuration>
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.
513
The Complete Reference To Professional SOA with Visual Studio 2005
A lifetime lease is created for the marshal-by-reference object when the object is remoted outside an
application domain. Each application domain contains a lease manager that manages the leases in its domain.
The role of the lease manager is to periodically review the leases for expiration. If a lease expires, the lease
manager goes through its list of sponsors for that object and checks to see if any of the sponsors want to renew
the object’s lease. If no sponsor wishes to renew the lease then the lease manager removes the lease. The object
is then deleted, and garbage collection reclaims the object memory. As such the lifetime of an object can be
extended to longer than specified by its lifetime lease.
There are a few ways in which we can influence leasing times of objects. One way is to use configuration
files, and another way is to do it programmatically for the server, the remote object, or in the client. Let us look
at what can be configured first.
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.
514
The Complete Reference To Professional SOA with Visual Studio 2005
<system.runtime.remoting>
<application name="ValidateRegistration">
<service>
<activated type="InsuranceOperation,
InsuranceOperation" />
</service>
<channels>
<channel ref="tcp server" port="9080" />
</channels>
<lifetime leaseTime="10M"
sponsorshipTimeOut="2M"
renewOnCallTime="2M"
leaseManagerPollTime="10S"/>
</application>
</system.runtime.remoting>
</configuration>
Code
Setting the lifetime option in the configuration file is quite useful especially if we wanted to have the same
lifetime management for all objects for the server. If we need to define remote objects with different lifetime
requirements then we would need to set the lifetime for the object programmatically.
We can configure the lifetime lease within our code. To do this we need to override the
InitializeLifetimeService function of the MarshalByRefObject class. The following is the syntax used to override
the InitializeLifetimeService function see listing 13-35 and 13-36.
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Lifetime;
public InsuranceOperation()
{
Console.WriteLine("Constructor has been called");
}
515
The Complete Reference To Professional SOA with Visual Studio 2005
Imports System
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Lifetime
516
The Complete Reference To Professional SOA with Visual Studio 2005
End Class
The LeaseTime option defines the remote object’s maximum time to lease. The object will be deactivated if
the client does not need the remote object for this time period. Every time a method is invoked the leasing time is
incremented by the value defined with within RenewOnCallTime.
In listing 13-35 and listing 13-36, we have set the InitialLeaseTime to two minutes, SponsorshipTimeout to
three minutes and RenewOnCallTime to three. In the remote object class we can override the
InitializeLifetimeService() method. The method InitializeLifetimeService() from the base class MarshalByRefObject
returns a reference to the ILease interface that can be used to change the default values. Changing the values is
only possible as long as the lease has not been activated, so that is why we need to check for the current state to
compare it with the enumeration value LeaseState.Initial.
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Activation;
using System.Runtime.Remoting.Lifetime;
using System.Threading;
namespace InsuranceClient
{
class Client
{
static void Main(string[] args)
{
TcpClientChannel channel = new TcpClientChannel();
ChannelServices.RegisterChannel(channel, true);
object[] attrs = {
new UrlAttribute(
"tcp://localhost:9080/ValidateRegistration") };
InsuranceOperation obj =
(InsuranceOperation)Activator.CreateInstance(
typeof(InsuranceOperation), null, attrs);
// Use the object
Thread.Sleep(5000);
ILease lease =
(ILease)RemotingServices.GetLifetimeService(obj);
517
The Complete Reference To Professional SOA with Visual Studio 2005
Console.WriteLine();
}
}
}
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
Thread.Sleep(5000)
Dim lease As ILease = _
CType(RemotingServices.GetLifetimeService(obj), ILease)
Console.WriteLine("Current Lease Time: " + _
lease.CurrentLeaseTime.ToString())
518
The Complete Reference To Professional SOA with Visual Studio 2005
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.
Table 13-3. The table above highlights the difference between server-activated and client-activated objects.
519
The Complete Reference To Professional SOA with Visual Studio 2005
Activation of the Message is only sent when the first method call is Activation messages is sent to the server
server object made. No activation messages is sent upon when a proxy is created after the client
requesting the reference. Constructor is not creates the object. Constructors with
executed. parameters are supported.
Lifetime of the The lifetime for single call and singleton is Lifetime is the earlier of these two events:
server object determined by the configuration on the server.
a) Lease expires
Singleton objects are also subjected to lifetime
management. b) When the client loses its reference on the
server object
Server side a) Use configuration file to specify the type configuration file can be used to export the
registration (SingleCall or Singleton). client-activated object.
b) Use RegisterWellKnownServiceType() api to
register the type.
Advantages of a) Clients can be compiled against server a) Classic COM "coclass" like invocation of
the models component’s base class or interface definition. the server object.
b) Useful to perform finite operations on the b) Gives clients more flexibility to govern the
server side. server object's lifetime.
c) Applications that uses Single call objects are c) Client can pass constructor parameters to
easily deployed in a Load Balanced environment, the created object.
as they don't hold state.
d) Server Objects can hold state for its
d) Singleton Objects can maintain state specific client between method calls.
information across client objects.
Transport Channels
Channels are stateless objects that transport messages between applications across remoting boundaries, whether
between application domains, processes, or computers. A channel can listen on an endpoint for inbound
messages, send outbound messages to another endpoint, or both. This allows us to plug in a wide range of
protocols, even if the common language runtime is not at the other end of the channel. The .NET Remoting
infrastructure defines three kinds of channels: TCP, HTTP and IPC. IPC is the named pipe protocol which can be
used to transmit messages. In remoting it also is possible to create our own custom channels and plug them into
the .NET Remoting infrastructure.
The .NET Framework provides the System.Runtime.Remoting.Channels name-space, which includes the
interfaces and classes that we use to work with channels. All channels implement the IChannel interface. The
IChannel interface provides properties such as ChannelName and ChannelPriority, which uniquely identify a
channel and define the channel priority, respectively.
TCP Channel
The TCP protocol is support by the .NET remoting infrastructure. TCP protocol is utilized for transporting
serialized stream across .NET Remoting boundaries. The TcpChannel type is defined in the
System.Runtime.Remoting.Channels.Tcp namespace. Which implements the IChannel, IChannelReceiver, and
IChannelSender interfaces. This means that the TcpChannel supports both sending and receiving data across the
520
The Complete Reference To Professional SOA with Visual Studio 2005
.NET Remoting boundaries. The TcpChannel type uses binary wire format to serialize object by default. We had
demonstrated implementing Remoting by using TCP in the previous example.
HTTP Channel
The .NET Remoting infrastructure also provides a transport that utilizes the HTTP protocol for transporting the
serialized message stream across the Internet. By utilizing HTTP it is particularly useful across network
boundaries where there are firewalls. As HTTP is a typical web protocol most networks support HTTP. The
HttpChannel type defined in the System .Runtime.Remoting.Channels.Http namespace implements the HTTP
transport functionality. Like the TcpChannel type, HttpChannel can send and receive data across .NET Remoting
boundaries. The HttpChannel type serializes message objects by using a SOAP wire format by default. The
below shows an application implementing HTTP channel configuration.
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);
System.Console.WriteLine
("Press the enter key to exit...");
System.Console.ReadLine();
}
}
}
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.Remoting
521
The Complete Reference To Professional SOA with Visual Studio 2005
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Http
Imports System.Runtime.Remoting.Activation
Imports VBSampleObject
Namespace InsuranceServer
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.
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);
522
The Complete Reference To Professional SOA with Visual Studio 2005
"http://localhost:8081/ValidateRegistration");
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
If obj.Equals(Nothing) Then
System.Console.WriteLine("Error: unable to locate server")
Else
Console.WriteLine(obj.ValidateRegistration("xyz-123"))
End If
Console.ReadLine()
Console.WriteLine()
End Sub
End Class
End Namespace
523
The Complete Reference To Professional SOA with Visual Studio 2005
The above code shows the implementation of the remoting client implementing HTTP channel. Switching
between TCP, HTTP and IPC is fairly simple in most cases its just a simple matter of substituting the TCP for
HTTP or for IPC.
Using HTTP Channel we can also view the wsdl document generated by using a browser. We can do this by
simply browsing to http://localhost/ValidateRegisration?wsdl to view the WSDL document.
Figure 13-7. The figure above shows the WSDL document for the remoting object.
IPC Channel
With the release of .NET Framework 2.0 the .NET Remoting infrastructure now provide Inter-Process
Communication (IPC). IPC is a form of communication channel for .NET Remoting and can be used with the
IPC system of the Windows operating system. Since IPC does not use network communication. The IPC channel
is thus much faster than the HTTP and TCP channel. But it can only be used for communication between
application domains on the same physical computer. Like the HTTP and TCP channels the IpcChannel Type is
defined in the System.Runtime.Remoting.Channels.Ipc namespace which implements the IPC transport
functionality. The IpcChannel can send and receive data across the .NET remoting boundaries but only on the
same physical machine. In the example below the usage of an application implementing IPC channel
configuration is demonstrated (see listing 13-43 and listing 13-44).
Listing 13-43. The below code shows the IPC Server implementation using C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
namespace InsuranceServer
{
public class VehicleDetailsServer : MarshalByRefObject
524
The Complete Reference To Professional SOA with Visual Studio 2005
{
public static void Main(string[] args)
{
// Create an instance of a channel
IpcChannel channel = new IpcChannel("ValidateRegistration");
// register the channel with security disabled
ChannelServices.RegisterChannel(channel, false);
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
525
The Complete Reference To Professional SOA with Visual Studio 2005
In the listing above in listing 13-43 and listing 13-44 we have demonstrated creating a remoting server using
the IPC protocol by creating an instance of the IpcChannel type that listens for incoming connections on the
named pipe that we have created called “ValidateRegistration”. The IpcChannel is then registered using the
ChannelServices.RegisterChannel() function. The first parameter for the RegisterChannel is the IpcChannel object
that we had created. The second parameter for the RegisterChannel method is a Boolean value which defines
whether we want to enable security for the channel in this case we have specified false to disable.
Listing 13-45. The below code shows the IPC Client implementation using C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
namespace InsuranceClient
{
class Client
{
public static void Main(string[] args)
{
// Create a channel for communicating with the remote object
IpcChannel chan = new IpcChannel();
ChannelServices.RegisterChannel(chan, false);
Listing 13-46. The below code shows the IPC Client implementation using Visual Basic 2005
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Ipc
526
The Complete Reference To Professional SOA with Visual Studio 2005
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Activation
Imports VBSampleObject
Namespace InsuranceClient
Class Client
If obj.Equals(Nothing) Then
System.Console.WriteLine _
("Error: unable to locate server")
Else
Console.WriteLine(obj.ValidateRegistration("xyz-123"))
End If
Console.ReadLine()
Console.WriteLine()
End Sub
End Class
End Namespace
The above code shows the implementation of the remoting client implementing IPC channel. Notice that we
don’t need to specify a port number for IPC we only need to specify the named pipe as well as the remotable
instance of the remoting server. This is because IPC can only used on the same computer. It is ideal for
application to application communication.
Channel Sinks
The .NET Remoting architecture is very flexible because it possesses a clear separation of object responsibilities.
The channel architecture employs a series of channel sink objects linked together into a sink chain. Each channel
sink within the chain has a clearly defined role in the processing of the message. The channel sink performs
certain functions on the message before the message is forwarded onto the next channel sink in the chain. Within
the channel sink chain we can access the message that is routed to or coming from a Remoting object. This
allows us to perform tasks such as logging, security, custom encryption, applying filters, and imposing other
security restrictions.
527
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 13-8. shows channel sink chains on the client and on the server.
In the above figure the client object makes calls on a transparent proxy, which in turn converts the method call
into a message object. The message object is routed through the context sink chains until it reaches the formatter
sink which is the first sink in the chain. The formatter sink is responsible for serializing the message object to a
byte stream by using a particular wire format. The formatter sink then passes the stream to the next sink in the
chain for further processing. The last sink in the channel sink chain is responsible for transporting the stream
over the wire by using a specific transport protocol.
To implement channel sink providers to create channel sink chains. We need to implement properties and
methods that implement the IClientChannelSinkProvider, IClientFormatterSinkProvider, or
IServerChannelSinkProvider interfaces. So that when we activate a remote object, the remoting system retrieves
the channel sink provider from the current channel and calls the CreateSink method on the channel sink provider
to create the first channel in the chain. When the CreateSink method is invoked, it creates its own channel sink.
The CreateSink call is forwarded to the next sink provider in the chain (if one exists), it ensures that the next sink
and the current one are linked together. The first channel sink on a client must be a formatter sink that serializes
the message into a stream. The last sink on the channel sink chain should be a transport sink that sends the
stream over the network wire.
528
The Complete Reference To Professional SOA with Visual Studio 2005
The Server
We will start with the Server implementation of our remotable Bank debit application which only needs to
perform a simple BankDebit() operation.
using System;
using System.Threading;
using System.Security;
using System.Security.Principal;
using System.Runtime.Remoting;
class Server
{
static void Main(string[] args)
{
RemotingConfiguration.Configure(
AppDomain.CurrentDomain.BaseDirectory +
"server.config", false);
Imports System
Imports System.Threading
Imports System.Security
Imports System.Security.Principal
Imports System.Runtime.Remoting
Imports icalc
Imports System.Collections
Imports System.IO
Imports System.Runtime.Remoting.Messaging
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Serialization.Formatters
529
The Complete Reference To Professional SOA with Visual Studio 2005
Class Calc
Inherits MarshalByRefObject
Implements icalc.IBank
Class Server
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.
<configuration>
<system.runtime.remoting>
<application name="calcsrv">
<service>
<wellknown mode="Singleton"
type="Calc, server" objectUri="calc" />
</service>
<channels>
<channel ref="http" port="8081">
<serverProviders>
<formatter ref="soap" />
<provider ref="wsdl"/>
<provider type="ServerSinkProvider, Sink"/>
</serverProviders>
530
The Complete Reference To Professional SOA with Visual Studio 2005
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>
In the configuration file we have registered the server as a Singleton. Notice that under the channel element,
we added the element serverProviders. The serverProviders element contains three elements. The first element
under serverProviders is formatter. The second element is where we tell the remoting server to add support for
the wsdl document. The third element is the provider element. This is where our sink is added by using the type
attribute. The type attributes defines the class required and the assembly where the class can be found.
We will now look at the implementation of the sink on the server.
public ServerSinkProvider()
{
Console.WriteLine("Entering constructor ServerSinkProvider");
}
531
The Complete Reference To Professional SOA with Visual Studio 2005
{
Console.WriteLine("Getting Next Server Channel Sink");
return next;
}
set
{
Console.WriteLine("Setting Next Server Channel Sink");
next = value;
}
}
Listing 13-51. Shows the implementation of the ServerSinkProvider in Visual Basic 2005
532
The Complete Reference To Professional SOA with Visual Studio 2005
[next] = value
End Set
End Property
End Class
The channel sinks are connected to a server channel through implementations of the
IServerChannelSinkProvider interface. Channel sink providers are stored in a chain, this allows us to manipulate
and customize chaining all channel sink providers together IServerChannelSinkProvider provides a property
called Next for this.
When multiple channel sink providers are specified in a configuration file, the remoting infrastructure will
chain them together in the order they were found in the configuration file. During a
RemotingConfiguration.Configure call the channel sink providers are created at the same time as the channel.
In order to create the server provider we need to implement the methods defined by the
IServerChannelSinkProvider interface.
Table 13-4. In order to implement IServerChannelSinkProvider we need to implement the following methods and property.
Name Description
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).
if (next != null)
{
nextSink = next.CreateSink(channel);
}
533
The Complete Reference To Professional SOA with Visual Studio 2005
534
The Complete Reference To Professional SOA with Visual Studio 2005
return spres;
}
Console.WriteLine("Entering GetResponseStream")
Return Nothing
End Function
535
The Complete Reference To Professional SOA with Visual Studio 2005
In the above listing we have implemented the ServerSink which implements the IServerChannelSink and
IChannelSinkBase interface and inherits from the BaseChannelObjectWithProperties.
Name Description
GetResponseStream Retrieve the stream from which the response message is serialized.
NextChannelSink Retrieve the next server channel sink in the server sink channel.
To understand the key method ProcessMessage() in the IServerChannelSink. We need to look back into the
process of how a message is transmitted using the proxy. The job of a proxy is to convert a method call invoked
on it into a message object. This message object, which implements the IMessage interface, is passed from the
client end to the server end by invoking ProcessMessage on message sink objects. Message sinks are chained
together in the sense that every message sink is responsible for calling ProcessMessage on the next message sink
after it has performed its work.
Below shows the parameters that ProcessMessage() requires:
536
The Complete Reference To Professional SOA with Visual Studio 2005
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
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();
}
}
537
The Complete Reference To Professional SOA with Visual Studio 2005
Class Client
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.
public ClientSinkProvider ()
{
Console.WriteLine("Entering client ClientSinkProvider");
538
The Complete Reference To Professional SOA with Visual Studio 2005
539
The Complete Reference To Professional SOA with Visual Studio 2005
Table 13-6. In order to implement IClientChannelSinkProvider we need to implement the following methods and property.
Name Description
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:
540
The Complete Reference To Professional SOA with Visual Studio 2005
541
The Complete Reference To Professional SOA with Visual Studio 2005
542
The Complete Reference To Professional SOA with Visual Studio 2005
End Sub
543
The Complete Reference To Professional SOA with Visual Studio 2005
End Class
In the above listing we have implemented the ClientSink which implements the IClientChannelSink and
IMessageSink interface and inherits from the BaseChannelObjectWithProperties.
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.
544
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 13-12. Shows the execution result from the Client sides
Summary
In this chapter we have explored .NET remoting. A possible alternative to XML Web services. .NET remoting is
a generic system for different applications to use to communication with one another through a number of
protocols such as HTTP, TCP and IPC.
In .NET remoting much like Web services the proxy within the remoting architecture abstracts a lot of the
complexities involved in cross boundry communication. When we create an instance of the remote object type in
the client application, .NET Remoting creates a proxy object and sends it to the client application. This proxy
object contains references to all the methods and properties of the server object. When we call a method that is
on that proxy object, the remoting system receives the call, routes it to the server process, invokes the server
object, and returns the return value to the client proxy, which returns the result to the client application.
There are two categories of objects in remoting: remotable and nonremotable. Nonremotable objects do not
provide the remoting system with a method to either copy them or use them in another application domain.
Therefore, we can access these objects only in their own application domain. Remotable objects can either be
accessed outside their application domain or context using a proxy or copied and passed outside their application
domain or context.
There’re two types of activation Server Activated Objects (SAOs) and Client-Activated Objects (CAOs).
Server-activated objects are similar to classic stateless Web Services. While client-activated objects can have
states. A client-activated object is instantiated on the server when the client creates it, and not with every method
call.
Lastly in this chapter we have also explored implementing channel sinks with remoting. The remoting
architecture supports a channel architecture which provides flexibility by employing a series of channel sink
objects linked together into a sink chain. Each channel sink in the chain has a clearly defined role in the
processing of the message. The channel sink performs certain functions on the message before forwarding the
message to the next channel sink in the chain.
545
The Complete Reference To Professional SOA with Visual Studio 2005
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:
<configuration>
<system.web>
<authentication mode="Windows"/>
</system.web>
546
The Complete Reference To Professional SOA with Visual Studio 2005
<location path="secureservice.asmx">
<system.web>
<authorization>
<allow users="Administrator"/>
<allow users="DOMAIN\Bradley"/>
<deny roles="BUILTIN\Power Users"/>
</authorization>
</system.web>
</location>
</configuration>
The web service can also examine role membership. The example below will examine to see if the user has
been authenticated and also if the role of the user is Administrator.
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
[WebMethod()]
public string TestWinAuthentication()
{
string strUserDetails = "";
if (!User.Identity.IsAuthenticated)
{
strUserDetails = "Not an authenticated user.";
}
else
{
strUserDetails = "Authenticated as: " +
User.Identity.Name + "; ";
if (!User.IsInRole("Administrator"))
{
strUserDetails += "User is NOT an Administrator";
}
else
{
strUserDetails += "User IS an Administrator";
}
}
return strUserDetails;
}
547
The Complete Reference To Professional SOA with Visual Studio 2005
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class Service
Inherits System.Web.Services.WebService
<WebMethod()> _
Public Function TestWinAuthentication() As String
Dim strUserDetails As String = ""
If Not User.Identity.IsAuthenticated Then
strUserDetails = "Not an authenticated user."
Else
strUserDetails = "Authenticated as: " + _
User.Identity.Name() + "; "
If Not User.IsInRole("Administrator") Then
strUserDetails += "User is NOT an Administrator"
Else
strUserDetails += "User IS an Administrator"
End If
End If
Return strUserDetails
End Function
End Class
The above Web service, which provides a single TestWinAuthentication() method. This method checks to
see if the user has been authenticated. If the user is authenticated, and if the role of the user belongs to the
Administrator group. If the user is authenticated, it returns the user name (which will be a string in the form
DomainName\UserName or Computer-Name\UserName).
Within the listing 14-2 and 14-3 the Web service class provides a User property of type
System.Security.Principal.IPrincipal, which we can use to retrieve information about the client user. We can
authorize access to our Web service using the Authorization section in the ASP.NET Web.Config file. The
User.IsAuthenticated property allows our code to determine if the current user has been authenticated. While the
User.IsInRole method allows our code to determine if the current user is a member of the specified role. This is
where we checked if the user is currently authenticated under the Administrator group.
This works well when we know that the client of the XML Web service will be running as a specific
Windows user. However what if we need a client running as one user, to act on behalf of another. Consider an
ASP.NET page that accesses a secure XML Web service that does not impersonate the client who accesses it. In
such a case, we need to programmatically set the username and password before connecting to the Web service.
To submit user credentials to this service, the client needs to modify the NetworkCredential property of the
proxy class. We have two options:
548
The Complete Reference To Professional SOA with Visual Studio 2005
* One way is to create a new NetworkCredential object and attach this to the NetworkCredential property of the
proxy object. When we create the NetworkCredential object, we will need to specify the user name and
password that we want to access the web service as. This approach works with all forms of Windows
authentication.
* The second way only works if the web service is using Integrated Windows authentication, we can
automatically submit the credentials of the current user by using the static DefaultCredentials property of the
CredentialCache class and applying that to the NetworkCredential property of the proxy object.
Both the CredentialCache and NetworkCredential classes are found in the System.Net namespace. The
NetworkCredential class is a base class that supplies credentials in password-based authentication schemes such
as basic, digest, NTLM, and Kerberos
The CredentialCache class is used when applications need to access multiple resources. These credential
information are stored in a CredentialCache instance. The GetCredentail method can be called to compare the
Uniform Resource Identifier (URI) and authenticate type provided with those stored in cache and return the first
set of credentials that match.
The DefaultCredentials property contains system credentials of the current security context. These represent
user name, password and the domain of the user currently logged in. For ASP.NET applications, the default
credentials are the user credentials of the logged-in user or the user being impersonated.
To enable custom windows authentication for the web service we need to first configure IIS to take our
principle information that web submit under NetworkCredential. To do this use the below steps:
Tip: Depending on the version of IIS used the screen may differ slightly.
1. We can open the IIS MMC console by going to the start menu -> then select run and type “inetmgr”.
2. In the left pane, expand the tree to find our virtual directory.
549
The Complete Reference To Professional SOA with Visual Studio 2005
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):
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();
}
550
The Complete Reference To Professional SOA with Visual Studio 2005
{
WSAuthenticate.Service wsAuthenticate =
new CSTestAuthenticationClient.WSAuthenticate.Service();
// Supply some user credentials for the web service.
NetworkCredential credentials = new NetworkCredential(
this.TextBoxLogin.Text, this.TextBoxPassword.Text);
wsAuthenticate.Credentials = credentials;
this.LabelAuthenticResult.Text =
wsAuthenticate.TestWinAuthentication();
}
catch (Exception ex)
{
this.LabelAuthenticResult.Text = ex.Message;
}
}
}
}
Imports System.Net
551
The Complete Reference To Professional SOA with Visual Studio 2005
The above code shows a windows application with two text boxes and two buttons, see figure 14-2. One
button performs an unauthenticated call, while the other submits the user name and password that have been
entered in the text boxes. In this example the unauthenticated call will fail since we have disabled anonymous
users in the section before. This means we must authenticate the client application the authenticated call will
always succeed as long as we submit the correct credentials that correspond to a valid user on our web server.
See figure 14-2.
Figure 14-2. Using unauthenticated and authenticated calls to the Web service.
Since NetworkCredential is found in System.Net. We need to first import the namespace for System.Net.
In order to specify the user that we would like to authenticate ourselves under we would first need to use
NetworkCredential where we pass in the login and password details of the user. This information is then attached
to the Credentials property generated by the Web service proxy. See listing 14-6 and listing 14-7.
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;
WSAuthenticate.Service wsAuthenticate =
new CSTestAuthenticationClient.WSAuthenticate.Service();
552
The Complete Reference To Professional SOA with Visual Studio 2005
wsAuthenticate.Credentials = CredentialCache.DefaultCredentials;
LabelAuthenticResult.Text = wsAuthenticate.TestWinAuthentication();
* 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.
Class/Interface Functions
553
The Complete Reference To Professional SOA with Visual Studio 2005
MembershipProvider The Membership provider defines the methods and properties that a
provider is required to implement.
Defines functionality for data
providers that can be used by the
membership system.
MembershipPasswordFormat Defines the possible storage format available for password used by the
membership provider. These are Clear, Hashed, Encrypted.
We can perform use the ASP.NET Web Site Administration Tool, which includes a security wizard.
Configuring Membership is straight forward simply go to the Website menu -> ASP.NET Configuration. See
figure 14-3 (below).
554
The Complete Reference To Professional SOA with Visual Studio 2005
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).
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.
555
The Complete Reference To Professional SOA with Visual Studio 2005
aspnet_regsql.exe tool in two ways either through a wizard interface or through the command line. If we just
launch the tool without any parameters, it will launch with the wizard interface that will guide us through the
process of creating a database. See figure 14-5.
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.
556
The Complete Reference To Professional SOA with Visual Studio 2005
If we select to configure a new Sql Server or application services. See figure 14-6 (above). The setup
wizard will prompt us for connection properties to our database server. We will also be prompted to select the
database that we wanted to use to store our user membership information into. By selecting the <default> option
for the database, the setup wizard will create a database called aspnetdb and the relevant tables within it on the
server we have specified.
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
-W This is the Wizard mode. This is the default if no command line arguments are specified.
-C connection string Define the connection string to the computer running SQL Server database will be
installed or already installed.
557
The Complete Reference To Professional SOA with Visual Studio 2005
-S server Define the name of the computer running SQL Server where the database will be installed.
-E Specifies the authentication using the current Windows credentials that the user is logged-
in as.
-d database Define the name of the database to create or modify. The default name is “aspnetdb”.
-sqlexportonly Create a SQL script file. We can customize this file to modify specific features.
filename
-A all|m|r|p|c|w Adds support for one or more features. The following identifiers are used for ASP.NET
features.
All - All features
m – Membership
r - Role management
p – Profile
w - Web events
Feature identifiers can be specified together or separately, as shown in the following
examples.
aspnet_regsql.exe -E -S localhost -A mp
aspnet_regsql.exe –E -S localhost -A m -A p
-R all|m|r|p|c|w Removes support for one or more features. The following identifiers are used for
ASP.NET features.
Feature identifiers can be specified together or separately, as shown in the following
examples.
aspnet_regsql.exe -E -S localhost -R mp
aspnet_regsql.exe -E -S localhost -R m -R p
-Q Runs the tool in quiet mode and does not confirm before removing a feature.
558
The Complete Reference To Professional SOA with Visual Studio 2005
Going through any of the above steps will result in the automated creation of tables within the database. See
figure 14-9.
559
The Complete Reference To Professional SOA with Visual Studio 2005
this we will need to either modify the web.config file directly or edit the configuration properties through the
ASP.NET Configuration Settings if the application is deployed on IIS.
Using Web.Config
We can specify the default membership provider using the defaultProvider attribute of the membership element.
The machine configuration specifies a SqlMembershipProvider instance named "AspNetSqlMembershipProvider"
this is identified as the default provider if we do not specify a default provider explicitly. The
"AspNetSqlMembershipProvider" connects to the aspnetdb database in the local SQL Server. To specify a custom
default provider we can use the below entries either into Web.config or Machine.config files.
We can also specify the default provider instance and options for that provider by configuring a provider in
the membership section. We can use the <providers> element to identify a provider to add to the collection of
providers available for the application. We can then identify this provider instance as the default provider. See
listing 14-10.
<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.
560
The Complete Reference To Professional SOA with Visual Studio 2005
Name Description
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.
MinRequiredNonAlphanumericCh Retrieve the minimum number of special charaters that must be used
aracters in a valid password
UserIsOnlineTimeWindow Retrieve the time window in number of minutes after the last activity
for a user to be online.
561
The Complete Reference To Professional SOA with Visual Studio 2005
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.
562
The Complete Reference To Professional SOA with Visual Studio 2005
A provider settings diaglog is shown in figure 14-12. From here we can Add/Remove or modify existing
provider details.
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.
Name Description
FindUsersByEmail Retrieves a collection of membership users where the e-mail address contains the specified e-mail
address to match.
563
The Complete Reference To Professional SOA with Visual Studio 2005
GetUser Retrieve the information for a membership user from the database.
GetUserNameByEmail Retrieve the user name by the user name’s email address.
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.
<?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>
if (user == null)
{
564
The Complete Reference To Professional SOA with Visual Studio 2005
Msg.Text = "The user name " + Server.HtmlEncode(UsernameTextBox.Text) + " was not found. Please check the value and reenter
your user name.";
QuestionLabel.Text = "";
QuestionLabel.Enabled = false;
AnswerTextBox.Enabled = false;
ResetPasswordButton.Enabled = false;
}
else
{
QuestionLabel.Text = user.PasswordQuestion;
QuestionLabel.Enabled = true;
AnswerTextBox.Enabled = true;
ResetPasswordButton.Enabled = true;
}
}
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.";
}
}
565
The Complete Reference To Professional SOA with Visual Studio 2005
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
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
End Sub
The listings 14-12 and 14-13 above demonstrates using membership to validate a user by username. By
calling the GetUser function under the VerifyUsername method. We can also reset a password by using the
Membership.Provider.ResetPassword function this will generate a new password for the user. Figure 13-13 below
demonstrates the UI for the application.
566
The Complete Reference To Professional SOA with Visual Studio 2005
567
The Complete Reference To Professional SOA with Visual Studio 2005
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
public AuthHeader sHeader;
if (sHeader == null)
return "ERROR: Please supply credentials";
else
return "USER: " + sHeader.Username;
}
}
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
568
The Complete Reference To Professional SOA with Visual Studio 2005
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.
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.
<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.
569
The Complete Reference To Professional SOA with Visual Studio 2005
To process SOAP headers within a Web service. Add a public member to the class implementing the Web
service of the type representing the SOAP header.
Listing 14-21. Setting a public property matching the header type using C#
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
public AuthHeader sHeader;
Listing 14-22. Setting a public property matching the header type using Visual Basic 2005
<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class Service
Inherits System.Web.Services.WebService
Listing 14-24. Demonstrates setting SoapHeader Attribute using Visual Basic 2005
using System;
using System.Collections.Generic;
570
The Complete Reference To Professional SOA with Visual Studio 2005
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace CSSoapHeaderClient
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
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
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.
571
The Complete Reference To Professional SOA with Visual Studio 2005
WSSoapHeaderService.AuthHeader authHeader =
new WSSoapHeaderService.AuthHeader();
Listing 14-28. Creating a new instance of the SOAP header using Visual Basic 2005
authHeader.Username = "JohnDoe";
authHeader.Password = "password";
Listing 14-30. Defining values for the header using Visual Basic 2005
authHeader.Username = "JohnDoe"
authHeader.Password = "password"
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
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.
this.LabelResult.Text = wsHeaderService.SecureMethod();
Listing 14-36. Calling the WebMethod on the service using Visual Basic 2005
Me.LabelResult.Text = wsHeaderService.SecureMethod
Finally when we can call the WebMethod on the Web service. The SOAP header portion of the SOAP
request sent to the Web service will include the contents of the data stored in the SOAP header object. See the
SOAP Request and Response Below.
Listing 14-37. Demonstrates a Request from our SoapHeaderClient Application to the SoapHeaderService.
572
The Complete Reference To Professional SOA with Visual Studio 2005
Listing 14-38. Demonstrates a Response from our SoapHeaderClient Application to the SoapHeaderService.
573
The Complete Reference To Professional SOA with Visual Studio 2005
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.
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 () {
[WebMethod]
[SoapHeader("Token", Direction = SoapHeaderDirection.Out)]
public string Login(string username, string password) {
if (Membership.ValidateUser(username, password))
{
SecurityLibrary.Token token =
new SecurityLibrary.Token(username);
Application[token.TokenID] = token;
Token = new SecurityLibrary.TokenHeader(token.TokenID);
return "logged in";
}
else
{
throw new SecurityException("Invalid credentials.");
574
The Complete Reference To Professional SOA with Visual Studio 2005
[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";
}
575
The Complete Reference To Professional SOA with Visual Studio 2005
return token;
} else {
throw new SecurityException("Insufficient permissions.");
}
}
[WebMethod]
public void CreateTestUser(string username, string password)
{
if (Membership.GetUser(username) != null)
{
//we can delete the user if it exists
throw new
SecurityException("User already exists in system!");
}
Membership.CreateUser(username, password);
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
<WebMethod()> _
<SoapHeader("SHToken", Direction:=SoapHeaderDirection.Out)> _
Public Function Login(ByVal username As String, _
ByVal password As String) As String
If Membership.ValidateUser(username, password) Then
576
The Complete Reference To Professional SOA with Visual Studio 2005
<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
577
The Complete Reference To Professional SOA with Visual Studio 2005
<WebMethod()> _
Public Sub CreateTestUser(ByVal username As String, _
ByVal password As String)
If Not (Membership.GetUser(username) Is Nothing) Then
Throw New SecurityException("User already exists in system!")
End If
Membership.CreateUser(username, password)
Dim role As String = "Administrator"
If Not Roles.RoleExists(role) Then
Roles.CreateRole(role)
End If
Roles.AddUsersToRole(New String() {username}, role)
End Sub
End Class
The listing 14-39 and listing 14-40 above shows the Web service implementation of our token security
system. We also need a security token library which is used to derive from SoapHeader and also store relevent
information relating to the token. See listing 14-41 (below)
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
namespace SecurityLibrary
{
578
The Complete Reference To Professional SOA with Visual Studio 2005
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
Namespace SecurityLibrary
579
The Complete Reference To Professional SOA with Visual Studio 2005
End Sub
End Class
End Namespace
To use our custom token security, the first step is to decide what user-specific information we want to keep in
our memory. We need to create a custom class that represents this information. This class can include
information about the user (name, e-mail address, and so on) and the user’s permissions. We’re also storing the
token id information along with the token so that the information can be retrieved at a later date. In our
implementation the Token ID is a randomly generated GUID to ensure that the tokens do not overlap. See listing
14-43.
Listing 14-43. Demonstrates token class used to store information relating to the token using C#
Listing 14-44. Demonstrates token class used to store information relating to the token using Visual Basic 2005
580
The Complete Reference To Professional SOA with Visual Studio 2005
Me.luserName = userName
ltokenID = Guid.NewGuid.ToString
End Sub
End Class
Once we have the token class, we can store relevant information into it, we need to create a SOAP header.
The header will track the token for us. See listing 14-45. The TokenHeader in our implementation is derived
from SoapHeader. We will be serializing an instance of the TokenHeader object into the SOAPHeader. Thus all
the information it needs to contain is the TokenID information from which we can then later retrieve all the
relevant information back again.
Listing 14-46. Demonstrates TokenHeader class implementing SoapHeader using Visual Basic 2005
Listing 14-47. Demonstrates an instance of TokenHeader in our main Web service using C#
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
public SecurityLibrary.TokenHeader Token;
Listing 14-48. Demonstrates an instance of TokenHeader in our main Web service using Visual Basic 2005
<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
Public Class Service
Inherits System.Web.Services.WebService
Public SHToken As SecurityLibrary.TokenHeader
581
The Complete Reference To Professional SOA with Visual Studio 2005
The next step is to create a dedicated web method that logs the user in. User will need to submit user login
and password to this method. The method will then retrieve the user information, create the Token object, and
issue the token. In our example, a Login() web method checks the user credentials using the static
Membership.ValidateUser() method. A new token is constructed with the user information and stored in a user-
specific slot in the Application collection. At the same time, a new SOAP header is issued with the token so that
the user can access other methods with the token information. See listing 14-49.
Here’s the example for the Login() method:
[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.");
}
<WebMethod()> _
<SoapHeader("SHToken", Direction:=SoapHeaderDirection.Out)> _
Public Function Login(ByVal username As String, _
ByVal password As String) As String
If Membership.ValidateUser(username, password) Then
Dim token As SecurityLibrary.Token = _
New SecurityLibrary.Token(username)
Application(token.TokenID) = token
SHToken = _
New SecurityLibrary.TokenHeader(token.TokenID)
Return "logged in"
Else
Throw New SecurityException("Invalid credentials.")
End If
Return "cannot login"
End Function
In the listing 14-50 above, the Token object is stored in the Application collection, which is global to all users.
The tokens are stored using GUID that was generated to prevent them from overwriting each other. We can then
use the token id information that’s embedded in the Soap header to retrieve the user information. In this way, our
code can check the Application collection first, and if a matching Token is found, no database call is required.
But if the Token isn’t present, the information can still be retrieved from the database.
582
The Complete Reference To Professional SOA with Visual Studio 2005
The next step is to verify the credential information, the following AuthorizeUser() method checks for a
matching token and returns the Token if it’s found. Otherwise an exception is thrown, this exception will be
raised as a SOAP exception which will be returned to the client. See listing 14-51.
Listing 14-54. Verifying that the user belongs to a role using Visual Basic 2005
583
The Complete Reference To Professional SOA with Visual Studio 2005
[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";
}
<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);
if (!Roles.RoleExists(role))
{
Roles.CreateRole(role);
}
Roles.AddUsersToRole(new string[] { username }, role);
}
Listing 14-58. Demonstrates CreateTestUser() used to create an user of the role Administrator in Visual Basic 2005
584
The Complete Reference To Professional SOA with Visual Studio 2005
<WebMethod()> _
Public Sub CreateTestUser(ByVal username As String, _
ByVal password As String)
If Not (Membership.GetUser(username) Is Nothing) Then
Throw New SecurityException("User already exists in system!")
End If
Membership.CreateUser(username, password)
Dim role As String = "Administrator"
If Not Roles.RoleExists(role) Then
Roles.CreateRole(role)
End If
Roles.AddUsersToRole(New String() {username}, role)
End Sub
In order to enable the Membership functionalities we also need to make a few entries into our web.config
file.
<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.
<membership>
<providers>
<remove name="AspNetSqlMembershipProvider"/>
<add name="AspNetSqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider, System.Web,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
connectionStringName="LocalSqlServer1"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="false"
applicationName="/"
requiresUniqueEmail="false"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="5"
minRequiredPasswordLength="1"
minRequiredNonalphanumericCharacters="0"
passwordAttemptWindow="10"
passwordStrengthRegularExpression="" />
</providers>
</membership>
585
The Complete Reference To Professional SOA with Visual Studio 2005
In the configuration above we define the properties of the Membership management. We also define password
policies and where the information will be stored.
The last thing we need to define is:
<roleManager enabled="true" />
This will allow ASP.NET Membership to manage roles for us. As in the example we need to assign users to
the Administrator role that we had defined. Thus roleManager must be enabled.
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.
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();
}
586
The Complete Reference To Professional SOA with Visual Studio 2005
this.labelResult.Text = wsts.PerformSecuredOperation1() +
Environment.NewLine + wsts.PerformSecuredOperation2() +
Environment.NewLine + wsts.PerformSecuredOperation3();
} catch (Exception ex) {
this.labelResult.Text = ex.Message;
}
}
Listing 14-62. Demonstrates the token application using Visual Basic 2005
In Visual Studio 2005 when we add a Web reference Visual Studio 2005 will automatically generate the
proxy class for us. The proxy class will help us manage the token so as a client we don’t need to be aware of the
header that’s actually being transported to and from the requests. As we can see in the SOAP exchange below.
587
The Complete Reference To Professional SOA with Visual Studio 2005
In the above listing we are making a SOAP request to the Login() method within the security Token Web
service.
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.
588
The Complete Reference To Professional SOA with Visual Studio 2005
</soap:Body>
</soap:Envelope>
In the listing above we are making a request to the PerformSecuredOperation1() operation. However notice
that the request now contains SOAP header information. Which contains the TokenHeader as well as the TokenID
that was issued by our Web service.
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.
589
The Complete Reference To Professional SOA with Visual Studio 2005
performed 2</PerformSecuredOperation2Result>
</PerformSecuredOperation2Response>
</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.
Summary
In this chapter, we have covered:
590
The Complete Reference To Professional SOA with Visual Studio 2005
Windows Authentication - We can use windows authentication to authenticate our users. This is particularly
useful in an intranet environment. In Web service this works in much the same way as it does with web pages.
The difference is that a web service is always executed by another application, and not directly by the browser.
Managing Users by Using Membership - ASP.NET Membership provides us with a built-in way to validate and
store user credentials. ASP.NET Membership is particularly useful when implementing user and role
management within Web services.
Custom Authentication and Authorization with SOAP Headers – The optional Header element
can contain additional information not directly related to the particular message. Each child
element of the Header element is called a SOAP header. We thus use SOAP header to store
security credential details. This is particularly useful as it saves the client from having to
authenticate themselves upon each WebMethod call.
591
The Complete Reference To Professional SOA with Visual Studio 2005
592
The Complete Reference To Professional SOA with Visual Studio 2005
This runtime essentially intercepts SOAP request and response messages and invokes a set of filters that
either serialize specification compliant SOAP response message headers (in the case of outbound response
messages) or interpret specification compliant request message headers (in the case of inbound request
messages). These filters can handle SOAP messages transported over both HTTP or TCP.
The filters and the WSE runtime are implemented by the Microsoft.Web.Services assembly
(Microsoft.Web.Services.dll), and WSE provides a set of APIs that allows us to programmatically determine the
behavior of these inputs and output filters in order to implement the desired functionalities described by the
various specifications.
The WSE runtime can also be installed at a Web service client computer and used by client applications that
consume Web services that require the additional support for advanced Web services headers. As on the Web
service provider, the WSE runtime on the client passes SOAP messages through a set of filters that either
serialize supported headers for outgoing messages or abstract the supported headers from incoming messages
into proxy objects that the client application consumes.
WS-Security
The Web service security (WS-Security) specification defines SOAP extensions for message integrity, and
message confidentiality. The WS-Security specification provides message level security end-to-end security
support rather than point-to-point security such as those provided by SSL/HTTPS. WS-Security defines a
method of implementing Web service security using SOAP. It defines rules for authentication, signatures, and
encryption mechanisms.
WS-Security also defines a general mechanism for associating security tokens with messages. The token
support itself is extensible and is not restricted to a specific type of security token. Typically a client will be
required to provide proof of identity and or a business certificate. Additionally, WS-Security describes how to
encode binary security tokens such as X.509 certificates and Kerberos ticket as well as how to include opaque
encrypted keys. We can also extend security mechanisms that can be used to further describe the characteristics
of the credentials.
Security Tokens
WS-Security uses the concept of soft security tokens, which are logical entities generated by the system to
ensure authentication. These refers to Username/Password, Kerberos tickets, or X.509 certificates. A developer
can also build custom binary security tokens if necessary and use them without breaking the specification. For
this purpose, WSE provides the BinarySecurityToken class. Classes that we build that derive from this will be
compatible with the WS-Security soft token specification.
593
The Complete Reference To Professional SOA with Visual Studio 2005
To add a security token to an outbound message using WSE, all that we need to do is to programmatically
define the token using an instance of an appropriate class that overrides the SecurityToken base class then add
this object to the SoapContext of the outbound message. When received by a WSE-enabled application, the WSE
runtime generates security token objects based on contents of the Security header in the incoming message.
These tokens, which belong to the SoapContext object for the incoming message, are then presented to the
appropriate security token manager for authentication and authorization. These security token objects are
accessible to our application for as long as the SoapContext object exists.
During setup, we will be prompted to select from several setup type options, including options to install only
the runtime files, runtime plus tools, documentation, Visual Studio tools, and a custom install option. These
setup options help to differentiate between the different types of WSE components that should be installed. We
can also specify Custom option, which allow us to select the various components manually. Most developers
should choose the Visual Studio® Developer option, which installs the WSE 3.0 runtime files, documentation
and samples, standalone tools, and the Visual Studio 2005 tools (see figure 15-13 below).
594
The Complete Reference To Professional SOA with Visual Studio 2005
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).
595
The Complete Reference To Professional SOA with Visual Studio 2005
Enabling WSE for an ASP.NET Web service is quite simple with this tool. All that we need to do is select
WSE Settings 3.0 from the context menu in solution explorer for our project. Then select both check boxes on
the General tab. To enable WSE for an application consuming a WSE-enabled Web service, we need only select
the “Enable this project for Web Services Enhancements” check box see figure 15-5 (below). By enabling this
option the necessary assembly reference will be added to the project, and the SOAP extensions configurations
will be automatically entered into our Web.config file.
596
The Complete Reference To Professional SOA with Visual Studio 2005
Listing 15-1. Demonstrates the Web.config file after WSE has been enabled.
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="microsoft.web.services3"
type=
"Microsoft.Web.Services3.Configuration.WebServicesConfiguration,
Microsoft.Web.Services3, Version=3.0.0.0,Culture=neutral,
PublicKeyToken=31bf3856ad364e35"/>
</configSections>
<system.web>
<webServices>
<soapExtensionImporterTypes>
<add
type="Microsoft.Web.Services3.Description.WseExtensionImporter,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35"/>
</soapExtensionImporterTypes>
<soapServerProtocolFactory
type="Microsoft.Web.Services3.WseProtocolFactory,
Microsoft.Web.Services3, Version=3.0.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</webServices>
<compilation debug="true">
<assemblies>
<add assembly="Microsoft.Web.Services3,
Version=3.0.0.0, Culture=neutral,
597
The Complete Reference To Professional SOA with Visual Studio 2005
PublicKeyToken=31BF3856AD364E35"/>
</assemblies>
</compilation>
</system.web>
</configuration>
The rest of the tabs in this tool allow us to configure various components of WSE that correspond to the
specifications that the Web service needs to use.
Requesting Process
The communication process starts with the client generating a Web service request. This process involves three
steps: initializing the UsernameToken, establishing message integrity, encrypting sensitive data in the message,
(see figure 15-6 above).
598
The Complete Reference To Professional SOA with Visual Studio 2005
During initialization the UsernameToken implements a token object with a SendPlainText password option
to send the password over the network as plaintext. This is often required because directory services such as
Active Directory require plaintext passwords for credential validation. SendPlainText is the default option of the
UsernameTokenManager which is similar to basic authentication over HTTP. When sending clear text password
we should always secure the communication channel between the client and the server this can be achieved using
Secure Socket Layer (SSL). To add security we can also add message level encryption by using WSE 3.0.
The next stage is establishing message integrity, at this stage data origin authentication is established
between the client and the service, either implicitly or explicitly, depending upon one of the two following
methods that we can choose to secure messages between the client and the service:
To ensure security when we use server certificates with HTTPS using the turnkey assertion help to provide
data integrity and data confidentiality at the transport level. If we require message origin authentication from the
client, we would need to install and use a certificate for the client.
Using usernameForCertificateSecurity turnkey assertion WSE 3.0 can provide support for data confidentiality
and message origin authentication. This is achieved when a derived key token is included in the request message
this message is then encrypted with a wrapped symmetric encryption key. Then using the service’s X.509
certificate public key the wrapped symmetric key is encrypted. This derived key token is referred to as an
encrypted key. This key is accompanied with a valid UsernameToken, message origin authentication is provided
when the client uses the derived key token to sign the message.
Encrypting sensitive data in the message, at this stage we should encrypt the message from the client to the
service to ensure that only the service, as the intended recipient of the message, can process it. The method that
we choose to secure the communication channel between the client and the service should also provide data
confidentiality.
Response Process
The response process is a little more complicated in WSE as the service needs to authenticate the client and
return a response. This part of the process has five steps: decrypting the request message, verifying message
integrity, validating the password, establishing the response integrity, encrypting the response.
* The first of these steps is the decryption of the request message. It is at this stage that we choose whether to
secure the communication channel between the client and the service and to determine how to decrypt the
request message. There are two forms of decryption at this stage if transport level encryption had been enabled
using the usernameOverTransportSecurity assertion which relies on SSL to decrypt the message. WSE 3.0 also
provides support for certificate based decryption using the usernameForCertificateSecurity assertion which
decrypts the derived key token that had been encrypted using the wrapped symmetric key. Then using the
derived key token to decrypt the message signature, the UsernameToken, and the rest of the message that the
client had encrypted.
* The second step is to verify the message integrity to ensure that the message had not been altered. The option
that we had selected in step one on how to secure communication between the client and the service determines
how the message integrity will be verified. WSE uses usernameOverTransportSecurity assertion relying on
SSL to verify message integrity. Otherwise if a client certificate is provided then the certificate can be used to
verify the message origin authentication. This is achieved with WSE 3.0 using the
usernameForCertificateSecurity assertion verifies the message integrity using the derived key token that was
sent by the client and was decrypted in step one.
599
The Complete Reference To Professional SOA with Visual Studio 2005
* The third step is to validate the password. After the service receives the message using WSE 3.0 the
UsernameTokenManager class validates the information in the UsernameToken using the AuthenticateToken
method. The UsernameTokenManager can be used to validate credentials against an Active Directory domain
controller. If a directory service or a database is used then we can extend the implementation of the
UsernameTokenManager class.
* The fourth step is to establish response integrity. At this stage the method used to establish the response
message’s integrity depends upon whether communication is secured at the message layer using WSE 3.0 or at
the transport layer using SSL. If the communication is secured at the transport level then message integrity is
provided by using SSL. If communication is secured at the message level then the response message will be
signed with a key derived from the encrypted key which was sent in the request message.
* The last step is the encrypting the response. Encryption is dependent on whether communication is secured at
the message level using WSE 3.0 or at the transport level using SSL. If communication is secured at the
transport level the encryption for the message is left to SSL. If communication is secured at the message layer
then response signature and the message is encrypted with a key derived from the encrypted key sent in the
request message.
600
The Complete Reference To Professional SOA with Visual Studio 2005
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).
601
The Complete Reference To Professional SOA with Visual Studio 2005
On the General tab, select the “Enable this project for Web Services Enhancements” check box, and also
select the “Enable Microsoft Web Services Enhancements Soap Protocol Factory” then click OK (see figure 15-9
below). this will add reference to the WSE 3 assembly as well configure the necessary settings within the
Web.config configuration file.
After we enable the service application to support WSE 3.0 SOAP extensions, we must enable policy
support. If our application does not currently have a policy cache file, we can add one and enable policy support
by performing the following steps.
1. In Visual Studio 2005, right-click the application project and select WSE Settings 3.0.
2. On the Policy tab, select the “Enable Policy” check box. Selecting this check box will automatically add the
wse3policyCache.config file as the default name for the policy cache file.
3. Within the Edit Application Policy group, select Add and then type "usernameTokenSecurity" for the new
application policy.
4. Click OK to start the WSE Security Settings Wizard, and then click Next (see figure 15-10. below).
602
The Complete Reference To Professional SOA with Visual Studio 2005
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.
7. On the Users and Roles section, we can configure authorization based on the user name or roles associated with
the user represented in the UsernameToken. By default, the perform authorization check box is cleared. If we
wanted to perform authorization through the policy assertion, select the perform authorization check box, add
users and roles as appropriate, and then click Next. In this example we will not be using this.
603
The Complete Reference To Professional SOA with Visual Studio 2005
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.
9. On the Create Security Settings page, review the settings, and then click Finish (see figure 15-14 below).
604
The Complete Reference To Professional SOA with Visual Studio 2005
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).
After we have completed the above steps, our server security policy should look similar to the following
code below.
605
The Complete Reference To Professional SOA with Visual Studio 2005
<policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy">
<extensions>
<extension name="usernameOverTransportSecurity"
type="Microsoft.Web.Services3.Design.UsernameOverTransportAssertion,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
<extension name="requireActionHeader"
type="Microsoft.Web.Services3.Design.RequireActionHeaderAssertion,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</extensions>
<policy name="usernameTokenSecurity">
<usernameOverTransportSecurity />
<requireActionHeader />
</policy>
</policies>
We can see that the configuration is set to use usernameOverTransportSecurity as we had specified during the
configuration wizard.
The listing above demonstrates the Web.Config file that has been modified by the WSE configuration
wizard. We can see that the wse3policyCache.config policy file has been set in the Web.Config file and also that
606
The Complete Reference To Professional SOA with Visual Studio 2005
SOAP extensions had been set to the WSE 3.0 assembly. This is necessary for WSE to intercept messages in
order to apply the ws-security.
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 () {
[WebMethod]
public string EmployeeSalaryDetail(string id) {
if (id == "123")
{
return "Salary for John Doe is $xyz";
}
return "no salary details found";
}
Listing 15-5. Demonstrates the Web service code in Visual Basic .NET
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports Microsoft.Web.Services3.Design
Imports Microsoft.Web.Services3
<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
<Policy("usernameTokenSecurity")> _
Public Class Service
Inherits System.Web.Services.WebService
<WebMethod()> _
Public Function EmployeeSalaryDetail(ByVal id As String) As String
If id = "123" Then
Return "Salary for John Doe is $xyz"
607
The Complete Reference To Professional SOA with Visual Studio 2005
End If
Return "no salary details found"
End Function
End Class
In the listings 15-4 and listings 15-5 above we have created a standard Web service the only difference is that we
have specified to use Policy("usernameTokenSecurity") this is a way of telling WSE to apply the policy of
usernameTokenSecurity within our class. As in WSE we can specify many different policies. With the policy
that we have selected using username and password token authentication the WSE engine will validate against
the windows user accounts on the server by default.
In the following section we will examine how to create a client application to consume the WSE web
service.
Enabling WSE for the console application is the same process as enabling for the web service. To enable a
Visual Studio 2005 project to support WSE 3.0. Right mouse click on the console project in solution explorer
and select WSE Settings 3.0.
608
The Complete Reference To Professional SOA with Visual Studio 2005
On the General tab, select the Enable this project for Web Services Enhancements check box, and then click
OK. This will add reference to the WSE 3 assembly as well configure the necessary settings within the
app.config configuration file for the console application.
After we enable the service application to support WSE 3.0 SOAP extensions, we must enable policy
support. If our application does not currently have a policy cache file, we can add one and enable policy support
by performing the following steps.
1. In Visual Studio 2005, right-click the application project and select WSE Settings 3.0.
2. On the Policy tab, select the “Enable Policy” checkbox. Selecting this setting automatically adds
wse3policyCache.config a policy cache file. (This is the same process as configuring WSE policy for the Web
service).
3. In “Edit Application Policy”, select Add, and then type "usernameTokenSecurity" for the new application
policy.
4. Click OK to start the WSE Security Settings Wizard, and then click Next.
5. In “Authentication Settings” page, we are provided with a choice on how to secure a service or a client. Select
“Secure a client application” to configure the client.
6. The wizard also provides a choice of authentication methods in the same step. Select Username, and then click
Next (see figure 15-17 below).
7. In “Optionally Provide Username and Password” page, we are provided with options to define a user name and
password. Select “Specify Username Token in code” checkbox is selected and select Next.
609
The Complete Reference To Professional SOA with Visual Studio 2005
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.
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>
610
The Complete Reference To Professional SOA with Visual Studio 2005
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.
When we add a Web reference to the service from the client application, two proxies are generated for the
Web service, one is a non-WSE 3.0 proxy and the other is WSE 3.0 enabled. In the WSE enabled proxy
Microsoft uses the naming convention of service name + "Wse". For example, if our Web service is named
"MyService", our WSE 3.0–enabled Web service proxy class name would be "MyServiceWse".
611
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 15-20. Demonstrates two server proxies one WSE enabled the other non-WSE
We can also use the WseWsdl3.exe tool under C:\Program Files\Microsoft WSE\v3.0\Tools to generate the
WSE proxy. The following command creates a client proxy class in C# for a Web service located at the specified
URL. The WSDL to SoapClient tool saves the client proxy class in the file MyProxyClass.cs.
WseWsdl3 http://hostServer/WebServiceRoot/WebServiceName.asmx?WSDL MyProxyClass.cs
The following command creates a client proxy class in Visual Basic for a Web service located at the
specified URL. The WSDL to SoapClient tool saves the client proxy class in the file MyProxyClass.vb.
WseWsdl3 http://hostServer/WebServiceRoot/WebServiceName.asmx?WSDL MyProxyClass.vb VB
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");
612
The Complete Reference To Professional SOA with Visual Studio 2005
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:
UsernameToken token =
new UsernameToken("BookUser", "BookUser",
PasswordOption.SendPlainText);
proxy.SetClientCredential(token);
Note: The Username in this case is BookUser, this is using Windows Integrated Security so we need to ensure that the user BookUser is
added onto the system.
613
The Complete Reference To Professional SOA with Visual Studio 2005
We then need to attach the policy we had configured through the WSE configuration wizard. This policy
contains information about how WSE should handle the security headers. This policy needs to be attached to the
proxy object by using the WSE proxy’s SetPolicy function.
proxy.SetPolicy("usernameTokenSecurity");
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.
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
614
The Complete Reference To Professional SOA with Visual Studio 2005
messageId="urn:uuid:cb166956-1202-4f34-bbcb-94c0d4d71572">
<processingStep description="Unprocessed message">
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<EmployeeSalaryDetail xmlns="http://tempuri.org/">
<id>123</id>
</EmployeeSalaryDetail>
</soap:Body>
</soap:Envelope>
</processingStep>
<processingStep
description="Entering SOAP filter Microsoft.Web.Services3
.Design.UsernameOverTransportAssertion+ClientOutputFilter" />
<processingStep description="Exited SOAP filter Microsoft.Web
.Services3.Design.UsernameOverTransportAssertion+ClientOutputFilter" />
<processingStep description="Processed message">
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/
envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/
oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/
oasis-200401-wss-wssecurity-utility-1.0.xsd">
<soap:Header>
<wsa:Action>http://tempuri.org/EmployeeSalaryDetail</wsa:Action>
<wsa:MessageID>urn:uuid:cb166956-1202-4f34-bbcb-94c0d4d71572
</wsa:MessageID>
<wsa:ReplyTo>
<wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/
addressing/role/anonymous</wsa:Address>
</wsa:ReplyTo>
<wsa:To>http://localhost:1704/CSService/Service.asmx</wsa:To>
<wsse:Security soap:mustUnderstand="1">
<wsu:Timestamp wsu:Id="Timestamp-71379091-a431-41d8
-9732-1a363e76d5cf">
<wsu:Created>2006-06-13T07:49:40Z</wsu:Created>
<wsu:Expires>2006-06-13T07:54:40Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/
wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
wsu:Id="SecurityToken-20f9c662-4201-44ea-993a-f11cefb1a485">
<wsse:Username>BookUser</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/
wss/2004/01/oasis-200401-wss-username-token-profile-1.0
#PasswordText">BookUser</wsse:Password>
<wsse:Nonce>1MUXtG6OAAEjBjKQPHchmA==</wsse:Nonce>
<wsu:Created>2006-06-13T07:49:40Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
615
The Complete Reference To Professional SOA with Visual Studio 2005
</soap:Header>
<soap:Body>
<EmployeeSalaryDetail xmlns="http://tempuri.org/">
<id>123</id>
</EmployeeSalaryDetail>
</soap:Body>
</soap:Envelope>
</processingStep>
</outputMessage>
The listing below demonstrates the response sent by the Web service to the client.
Listing 15-15. Demonstrates the response received from the WSE Web service
616
The Complete Reference To Professional SOA with Visual Studio 2005
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using Microsoft.Web.Services3;
using Microsoft.Web.Services3.Security.Tokens;
617
The Complete Reference To Professional SOA with Visual Studio 2005
using Microsoft.Web.Services3.Security;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[Policy("usernameTokenSecurity")]
public class Service : System.Web.Services.WebService
{
public Service()
{
[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
618
The Complete Reference To Professional SOA with Visual Studio 2005
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.
//AuthenticationManager.cs
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Web.Services3.Security.Tokens;
using Microsoft.Web.Services3;
using Microsoft.Web.Services3.Security;
using System.Xml;
using System.Security.Permissions;
using System.Web.Security;
using System.Security.Principal;
namespace AuthenticationManager
{
[SecurityPermissionAttribute(SecurityAction.Demand,
Flags = SecurityPermissionFlag.UnmanagedCode)]
public class CustomUsernameTokenManager : UsernameTokenManager
{
/// <summary>
/// Constructs an instance of this security token manager.
/// </summary>
public CustomUsernameTokenManager()
{
}
/// <summary>
/// Constructs an instance of this security token manager.
/// </summary>
/// <param name="nodes">
/// An XmlNodeList containing XML elements from a
/// configuration file.</param>
public CustomUsernameTokenManager(XmlNodeList nodes)
: base(nodes)
{
}
619
The Complete Reference To Professional SOA with Visual Studio 2005
/// <summary>
/// Returns the password or password equivalent
/// for the username provided.
/// Adds a principal to the token whith user's roles.
/// </summary>
/// <param name="token">The username token</param>
/// <returns>The password (or password equivalent)
/// for the username</returns>
protected override string AuthenticateToken(UsernameToken token)
{
string username = token.Username;
if (username == "john")
return "doe";
else
throw new ApplicationException();
}
‘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
620
The Complete Reference To Professional SOA with Visual Studio 2005
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.
621
The Complete Reference To Professional SOA with Visual Studio 2005
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.
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.
622
The Complete Reference To Professional SOA with Visual Studio 2005
<assemblies>
<add assembly="Microsoft.Web.Services3, Version=3.0.0.0,
Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Security, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" />
<add assembly="System.Design, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" />
<add assembly="System.Configuration.Install,
Version=2.0.0.0, Culture=neutral,
PublicKeyToken=B03F5F7F11D50A3A" />
</assemblies>
</compilation>
</system.web>
<microsoft.web.services3>
<security>
<securityTokenManager>
<add type="AuthenticationManager.CustomUsernameTokenManager"
namespace="http://docs.oasis-open.org/wss/2004/01/
oasis-200401-wss-wssecurity-secext-1.0.xsd"
localName="UsernameToken" />
</securityTokenManager>
<x509 allowTestRoot="true" revocationMode="Offline"
verificationMode="TrustedPeopleOnly" />
</security>
<policy fileName="wse3policyCache.config" />
<diagnostics>
<trace enabled="true" input="InputTrace.webinfo"
output="OutputTrace.webinfo" />
<detailedErrors enabled="true" />
</diagnostics>
</microsoft.web.services3>
</configuration>
Our custom usernameTokeManager is added as a type in the Web.config configuration file, the type of the
SecurityTokenManager is comprised of the namespace and class implementing the handler and the name of the
assembly containing the class, without extension.
In the listing below we will be adding a Web Reference to the WSE enabled Web Service the reference will
be named as WSEProxy.
Listing 15-21. Demonstrates the client code required to access the Web service in Visual C#
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Microsoft.Web.Services3.Security.Tokens;
using Microsoft.Web.Services3;
623
The Complete Reference To Professional SOA with Visual Studio 2005
UsernameToken token =
new UsernameToken("john", "doe",
PasswordOption.SendPlainText);
proxy.SetClientCredential(token);
proxy.SetPolicy("usernameTokenSecurity");
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
624
The Complete Reference To Professional SOA with Visual Studio 2005
End Class
End Namespace
The client code used to access the Web service is the same as that from the previous example.
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.
3. The MMC console window should now appear on the File menu, click Add/Remove Snap-in, and then click
Add.
625
The Complete Reference To Professional SOA with Visual Studio 2005
5. Click My user account, and then click Finish. This allows us to manage certificates for the current user.
Certificates – Current User appears on the list of selected snap-ins for the new console.
6. While the Add Standalone snap-in is still open under Snap-in, add another Certificates snap-in by double-
clicking on the Certificates.
7. Add the computer Computer Management snap in, by selecting Add and then selecting Computer Management
from the list of possible snap ins. Click Add, click Local computer, and then click Finish.
8. Click Close to close the Add Standalone Snap-in and OK to close the Add/Remove Snap-in dialog windows.
This will allows us to manage local computer certificates.
TIP: The certificates that are displayed are installed by default when you install WSE 3.0
WSECertificate3.exe
WSE also comes with a X.509 certificate tool (WSECertificate3.exe). The X.509 Certificate tool displays details
about X.509 certificates stored on the local computer. This information helps us diagnose configuration issues
related to X.509 certificates. The WSECertificate3.exe tool allows us to View details about an X.509 certificate
and view the attributes of the file containing the private key for an X.509 certificate.
To run the X.509 Certificate tool
1. Click Start, point to All Programs, point to Microsoft WSE 2.0, and then click X.509 Certificate Tool.
626
The Complete Reference To Professional SOA with Visual Studio 2005
2. Enter the Certificate Location and Store Name for the X.509 certificate.
3. Click Open Certificate.
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.
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.
627
The Complete Reference To Professional SOA with Visual Studio 2005
4. In the Enter the object names to select box, type the name for the user account that the WSE is running under,
and then click OK.
6. Click OK.
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.
1. In Visual Studio 2005, right-click the application project and select WSE Settings 3.0.
2. On the Policy tab, select the Enable Policy checkbox. Selecting this setting adds a policy cache file with the
default name wse3policyCache.config.
3. Under Edit Application Policy, click Add, and then type a policy friendly name for the new application policy,
such as "usernameTokenSecurity."
4. Click OK to start the WSE Security Settings Wizard, and then click Next.
5. On the Authentication Settings page, the wizard provides a choice to secure a service application.
6. The wizard also provides a choice of authentication methods in the same step. Select Username, and then click
Next.
628
The Complete Reference To Professional SOA with Visual Studio 2005
7. On the Optionally Provide Users and Roles page, click Next to continue.
8. On the Message Protection page, we can configure options for message protection. We will select “Sign and
Encrypt”. This will automatically use the usernameForCertificateSecurity policy assertion.
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.
11. Select the WSE2QuickStartServer certificate then click OK. Then Next.
629
The Complete Reference To Professional SOA with Visual Studio 2005
12. On the Create Security Settings page, review the settings, and then click Finish.
1. In Visual Studio 2005, right-click the application project and select WSE Settings 3.0.
2. On the Policy tab, select the Enable Policy checkbox. Selecting this setting adds a policy cache file with the
default name wse3policyCache.config.
3. Under Edit Application Policy, click Add, and then type a policy friendly name for the new application policy,
such as "usernameTokenSecurity."
4. Click OK to start the WSE Security Settings Wizard, and then click Next.
5. On the Authentication Settings page, the wizard provides a choice to secure a Client.
6. The wizard also provides a choice of authentication methods in the same step. Select Username, and then click
Next.
7. On the Optionally Provide Username and Password page, click Next to continue.
8. On the Message Protection page, we can configure options for message protection. We will select “Sign and
Encrypt”. This will automatically use the usernameForCertificateSecurity policy assertion.
9. Click Next.
630
The Complete Reference To Professional SOA with Visual Studio 2005
10. We will now come to a Server Certificate configuration page. On the Store Location choose LocalMachine.
And Click on Select Certificate.
11. Select the WSE2QuickStartServer certificate then click OK. Then Next.
12. On the Create Security Settings page, review the settings, and then click Finish.
Listing 15-23. Demonstrates the signed and encrypted request SOAP Message
<soap:Envelope
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/
oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/
oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
.
.
.
<wsu:Timestamp
wsu:Id="Timestamp-3e7d40d1-0060-40a5-a711-528d4ac6f25e">
<wsu:Created>2006-06-14T06:47:07Z</wsu:Created>
<wsu:Expires>2006-06-14T06:52:07Z</wsu:Expires>
</wsu:Timestamp>
<xenc:EncryptedKey
Id="SecurityToken-f4b7b281-7193-4b37-a960-5a592bbbe6de"
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
<xenc:EncryptionMethod
Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p">
<ds:DigestMethod
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
</xenc:EncryptionMethod>
.
.
.
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<ds:CanonicalizationMethod
Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#" />
<SignatureMethod
Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1" />
<Reference
URI="#SecurityToken-efd24129-fa1f-4ca0-bbfd-d76ef62c6f47">
<Transforms>
<Transform
Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod
631
The Complete Reference To Professional SOA with Visual Studio 2005
Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>fHa41bEoBYaCAV/QUp7bNFJtOJM=</DigestValue>
</Reference>
.
.
.
<soap:Body wsu:Id="Id-0e59d56d-d309-46e0-85f1-50ecaaf14b9d">
<xenc:EncryptedData
Id="Enc-05209377-c7a0-464a-ab7b-e59f91c2df89"
Type="http://www.w3.org/2001/04/xmlenc#Content"
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
<xenc:EncryptionMethod
Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
Listing 15-24. Demonstrates the signed and encrypted response SOAP Message
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<ds:CanonicalizationMethod
Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#" />
<SignatureMethod
Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1" />
<Reference URI="#Id-94e2b69b-4db1-4520-897a-335db2a07a0d">
<Transforms>
<Transform
Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod
Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>/7vTIR7+xHJb+TvPrmohsg3pPos=</DigestValue>
</Reference>
.
.
.
.
<Reference URI="#Id-7e1aacb9-5342-40dd-b6aa-a9c3f47d3d76">
<Transforms>
<Transform
Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod
Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>l1EsdLhBi2jilH9iy0uzfZsT0+w=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>cVOlLPE71rdX7y8+x4affGu+YXQ=</SignatureValue>
<KeyInfo>
<wsse:SecurityTokenReference>
<wsse:Reference
URI="#SecurityToken-e18fe938-10d9-444c-915a-b9d14acbccd3"
632
The Complete Reference To Professional SOA with Visual Studio 2005
ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/dk" />
</wsse:SecurityTokenReference>
</KeyInfo>
</Signature>
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.
In spite of the flexibility and acceptance of XML in application architecture, there are certain limitations
associated with XML. These limitations are for example media data and data that includes digital signatures are
633
The Complete Reference To Professional SOA with Visual Studio 2005
two of the most common examples. The reason is with media data there are highly standardized formats where
compression plays a major part. While for digital signatures, the binary integrity required would not be preserved
if it were serialized into a structured XML format. At the same time serializing binary data proved to be
extremely resource intensive. As a result there are various methods for sending binary data through the use of
Web services. These are:
* XML Representation: Replace any non-Xml data with a structured XML representation and include it in our
message. The problem here is that it bloats the data tremendously. However, if we are sending something like
Microsoft Word documents, we might want to consider saving them in XML format.
* SOAP with Attachments (SwA): Use SOAP with Attachments to send binary data with SOAP in a MIME
Multipart message. SOAP with Attachments was the first attempt by Microsoft (along with Hewlett Packard) at
solving the opaque data/attachments problem. Unfortunately SwA had poor composability and it did not work
well with the WS-* specifications.
* WS-Attachments with DIME: Compared to SOAP with attachments this is a faster and more efficient solution
to sending binary data. However it also has the same composability issues as SwA. As in the case with SwA, it
does not use a SOAP envelope approach to messaging. This limits DIME’s ability of the higher-level Web
service specifications to properly work upon a message.
* Base 64 Encoding: This method of encoding has been used for quite sometime and is well known for its binary
data problem. Although base-64-encoded data is usually more efficient from a message-size perspective than
using XML Representation, it still increases the data size by about 33% even when only single byte characters
are used.
* Message Transmission and Optimization Mechanism (MTOM): MTOM is widely accepted today in binary
transport. The MTOM approach take advantage of the SOAP infrastructure, but gain the transport efficiencies
provided by a SOAP with Attachments solution. MTOM is supported in WSE 3.0 and it will also be supported
by the future Windows Communication Foundation (WCF) see chapter 16.
MTOM implementation combines the benefits of composability of Base 64 encoding with the transport
efficiency of SwA. The binary data is dealt with just like it is with SwA it is simply streamed as binary data as
one of the Multipurpose Internet Mail Extensions (MIME) message parts. MTOM utilizes what is called an
XML Information Set (Infoset). Infoset allows for easy serialization/deserialization of the entire message into
XML form. At the Infoset level, immediately before the message is serialized, the binary data is accessed, it is
temporarily treated as base-64-encoded text.
By using the Infoset, we can implement WS-Security for binary attachments. In MTOM the WS-Security
layer create a digital signature for message level security. The binary data is streamed through a layer in which it
is temporarily encoded to base-64. During the streaming the signature of the message is calculated. The encoded
base-64 data is not transferred or held in memory. On deserialization, the same concepts apply. The raw binary is
transferred directly to the higher layer, but any processing layers that access it would do so through a temporary
base-64-encoding layer (see figure 15-32 below).
634
The Complete Reference To Professional SOA with Visual Studio 2005
2. In Solution Explorer, right-click the project name, and then click WSE Settings 3.0….
635
The Complete Reference To Professional SOA with Visual Studio 2005
4. Select Enable this project for Web Services Enhancements and Enable Microsoft Web Services Enhancements
SOAP Protocol Factory.
5. To enable our Web service to use MTOM select the Messaging tab.
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
636
The Complete Reference To Professional SOA with Visual Studio 2005
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.IO;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
public Service () {
[WebMethod]
public byte[] GetFile(string fileName)
{
byte[] response;
String filePath = AppDomain.CurrentDomain.BaseDirectory +
@"App_Data\" + fileName;
response = File.ReadAllBytes(filePath);
return response;
}
}
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 () {
[WebMethod]
public byte[] GetFile(string fileName)
{
byte[] response;
String filePath = AppDomain.CurrentDomain.BaseDirectory +
@"App_Data\" + fileName;
response = File.ReadAllBytes(filePath);
637
The Complete Reference To Professional SOA with Visual Studio 2005
return response;
}
}
By default the amount of data sent or received by the Web service is set at a limit of 4 MB to exceed 4 MB,
configure the Web server to handle the larger amount of data by modifying the Web.config file.
We can increase the ASP.NET limits on the maximum size of SOAP messages and the maximum number of
seconds that a request is allowed to execute by adding the <httpRuntime> configuration element to the
application's web.config file.
The following code example will set the ASP.NET limit for the maximum size of an incoming request to
400MB, and the maximum amount of time a request is allowed to execute to 5 minutes (300 seconds).
<configuration>
<system.web>
<httpRuntime maxRequestLength="409600" executionTimeout="300" />
</system.web>
</configuration>
To cater for large files we will also need to increase the WSE limit on the maximum size of SOAP messages using the
<maxMessageLength> Element. To send and receive the largest possible SOAP messages, set the value of the <maxMessageLength>
element to -1.
The following code example disables the limit on the maximum size of SOAP messages by WSE.
<configuration>
<microsoft.web.services3>
<messaging>
<maxMessageLength value="-1" />
</messaging>
</microsoft.web.services3>
</configuration>
638
The Complete Reference To Professional SOA with Visual Studio 2005
<add type="Microsoft.Web.Services3.Description
.WseExtensionImporter, Microsoft.Web.Services3,
Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</soapExtensionImporterTypes>
<soapServerProtocolFactory
type="Microsoft.Web.Services3.WseProtocolFactory,
Microsoft.Web.Services3, Version=3.0.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</webServices>
<httpRuntime maxRequestLength="409600" executionTimeout="300" />
</system.web>
<microsoft.web.services3>
<messaging>
<mtom serverMode="always" />
<maxMessageLength value="-1" />
</messaging>
</microsoft.web.services3>
</configuration>
5. To enable our Web service to use MTOM select the Messaging tab.
7. Select On for Client Mode and leave MaxMimeParts at 64 and check Require Soap Evelope First
This adds an <mtom> Element to the client application’s app.config file. The following settings are added to
the App.config file.
Listing 15-28. The client appliaction’s App.config after configuration
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="microsoft.web.services3"
type="Microsoft.Web.Services3.Configuration
.WebServicesConfiguration, Microsoft.Web.Services3,
639
The Complete Reference To Professional SOA with Visual Studio 2005
Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
<sectionGroup name="applicationSettings"
type="System.Configuration.ApplicationSettingsGroup,
System, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089">
<section name="MTOMClient.Properties.Settings"
type="System.Configuration.ClientSettingsSection,
System, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089"
requirePermission="false" />
</sectionGroup>
</configSections>
<microsoft.web.services3>
<messaging>
<mtom clientMode="On" serverMode="always" />
</messaging>
</microsoft.web.services3>
<applicationSettings>
<MTOMClient.Properties.Settings>
<setting name="MTOMClient_WSEProxy_Service" serializeAs="String">
<value>http://localhost:4529/MTOMService/Service.asmx</value>
</setting>
</MTOMClient.Properties.Settings>
</applicationSettings>
</configuration>
Having done the above steps we can start utilizing MTOM immediately. The following code example shows
a client application requesting for the GetFile WebMethod. Because we are using MTOM WSE will manage the
retrival of the byte array automatically. The byte array will be retrieved from the Web service and written to hard
disk on the client side.
Here’s the client implementing below.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace MTOMClient
{
class Program
{
static void Main(string[] args)
{
WSEProxy.ServiceWse wseproxy =
new MTOMClient.WSEProxy.ServiceWse();
byte [] content = wseproxy.GetFile("test.txt");
File.WriteAllBytes("test.txt", content);
}
}
}
640
The Complete Reference To Professional SOA with Visual Studio 2005
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.IO
Module Module1
Sub Main()
Dim wseproxy As WSEProxy.ServiceWse = _
New VBMTOMClient.WSEProxy.ServiceWse()
Dim content As Byte() = wseproxy.GetFile("test.txt")
File.WriteAllBytes("test.txt", content)
End Sub
End Module
Summary
In this chapter we have explored using WSE to implement WS-Security. The WS-Security specification defines
SOAP extensions for message integrity, message confidentiality, and single message authentication. These
mechanisms can be used to accommodate a wide variety of security models and encryption technologies. WS-
Security is implemented at the message level rather than transport.
Using WSE we have implemented message authentication using security tokens based on username and
password. We have also implemented digital signature and encryption using X.509 certificates.
The best method of security is through a combination of security over transport using SSL/HTTPS (poing-
to-point security) as well as SOAP message signing and encryption (end-to-end security).
In this chapter we have also examined Message Transmission Optimization Mechanism (MTOM). MTOM
combines the composability of Base 64 encoding with the transport efficiency of SOAP with Attachment (SwA).
MTOM is the new binary standard that will be supported by Windows Communication Foundation (WCF).
Using WSE 3.0 will give us a lot more communication security options. WSE 3.0 supports the latest WS-*
specifications. The same ones will be supported by Windows Communication Foundation. This makes WSE 3.0
and WCF wire-compatible and thus allow WCF clients to interoperate with WSE 3.0 services and vice versa.
641
The Complete Reference To Professional SOA with Visual Studio 2005
* Duplex Communication
642
The Complete Reference To Professional SOA with Visual Studio 2005
Note: In order to compile the examples in this chapter you will need to download “WinFx Runtime” which can be found when you search at
http://www.microsoft.com/download/. Once the runtime has been installed “Orcas” which contains the Development Tools for WinFX
should also be installed. Orcas can also be found at http://www.microsoft.com/download/.
WCF Foundamentals
A WCF Service is a program that exposes a collection of Endpoints. Each Endpoint is a portal for
communicating with the world. A WCF endpoint is composed of three parts, address, binding and contracts.
These are also referred to as the ABCs of WCF see figure 16-1.
* "A" stands for Address - Refers to where is the the service located? The Address is a network address where
the Endpoint resides. It can be a URI, an Identity or a collection of headers. The headers are used to provide
additional addressing information beyond the Endpoint's URI. For example, address headers are useful for
differentiating between multiple Endpoints that share the same address URI.
643
The Complete Reference To Professional SOA with Visual Studio 2005
* "B" stands for Binding – Refers to how do we communicate with the service? The Binding specifies how the
Endpoint communicates with the world including things like transport protocol (TCP, HTTP), encoding (text,
binary), and security requirements (SSL, SOAP message security). A Binding has a name, a namespace, and a
collection of composable binding elements. The Binding's name and namespace uniquely identify it in the
service's metadata. Each binding element describes an aspect of how the Endpoint communicates with the
world. Each BindingElement defines how to communicate with the Endpoint. The
TcpTransportBindingElement indicates that the Endpoint will communicate with the world using TCP as the
transport protocol. ReliableSessionBindingElement indicates that the Endpoint uses reliable messaging to
provide message delivery assurances. SecurityBindingElement indicates that the Endpoint uses SOAP message
security. Each binding element usually has properties that further describe the specifics of the how to
communicating with the Endpoint.
* "C" stands for Contract – Refers to what can the service do for us? The Contract specifies what the Endpoint
communicates to the outside world. Each operation is a simple message exchange, for example one-way or
request/response message exchange. The ContractDescription class is used to describe WCF Contracts and
their operations. Inside a ContractDescription, exist a Contract operation has a corresponding
OperationDescription. This describes aspects of the operation such as whether the operation is one-way or
request/ response. Each OperationDescription also describes the messages that make up the operation using a
collection of MessageDescriptions.
Contracts
In WCF we can define several different types of contracts.
* ServiceContract - A service contract resides on the service side to specify which of the service’s endpoint
should be exposed to callers. It is also used on the client side to specify the contract of the endpoint with which
the client communicates and, in the case of duplex contracts, to specify the callback contract that the client
must implement in order to participate in a duplex conversation.
* OperationContract - The OperationContract declares that a method is an operation in a service contract. In the
WCF model we must explicitly mark all operations that we want to expose. Only methods decorated with the
OperationContract attribute are exposed as service operations. A service contract without any methods marked
with the OperationContract attribute exposes no operations.
* DataContract – The data contract provide information about the items that flow across service boundaries.
* FaultContract - The FaultContract attribute is used to declare one or more specific exception conditions that are
added to the Web Service Description Language (WSDL) description of the method as explicit SOAP fault
messages returned by the method.
* MessageContract- MessageContract attribute defines the structure of the message types our service uses.
644
The Complete Reference To Professional SOA with Visual Studio 2005
within the scope of an application shall indeed be publicly visible to the outside world is an entirely different
matter altogether. However, there might cases where it is desirable to enforce that a method that's designed
exclusively for accessing the application from the outside is not accidentally invoked from within the
application. Under such circumstances, a method might be best declared as "private" towards the inside of the
application, but is indeed made accessible to outside callers.
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.
645
The Complete Reference To Professional SOA with Visual Studio 2005
[DataContract]
public class Person
{
[DataMember]
public int Id;
[DataMember]
public string FirstName;
[DataMember]
public string LastName;
}
<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.
// Version 1
646
The Complete Reference To Professional SOA with Visual Studio 2005
[DataContract]
public class Person
{
[DataMember]
private string Phone;
}
' Version 1
<DataContract()> _
Public Class Person
<DataMember()> _
Private Phone As String
End Class
In versioning we can also force a check for a particular DataMember by using the IsRequired attribute.
[DataContract]
public class Person
{
[DataMember]
public int Id;
[DataMember]
public string FirstName;
[DataMember]
public string LastName;
647
The Complete Reference To Professional SOA with Visual Studio 2005
[DataMember(IsRequired = true)]
public string MiddleName;
}
<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.
648
The Complete Reference To Professional SOA with Visual Studio 2005
{
UpdateIfModified,
FailIfModified
}
[DataContract]
public class UpdateBehavior
{
[DataMember]
public UpdateConcurrency UpdateConcurrencyMode;
}
[MessageContract]
public class StorePersonMessage
{
[MessageHeader]
public UpdateBehavior UpdateBehavior;
[MessageBody]
public Person Person;
}
[ServiceContract]
public interface IPeople
{
[OperationContract]
void StorePerson(StorePersonMessage storePersonMessage);
}
Listing 16-10. Demonstrates implementing MessageContract and MessageBody in Visual Basic .NET
<DataContract()> _
Public Class UpdateBehavior
<DataMember()> _
Public UpdateConcurrencyMode As UpdateConcurrency
End Class
<MessageContract()> _
Public Class StorePersonMessage
<MessageHeader()> _
Public UpdateBehavior As UpdateBehavior
<MessageBody()> _
Public Person As Person
End Class
<ServiceContract()> _
Public Interface IPeople
<OperationContract()> _
649
The Complete Reference To Professional SOA with Visual Studio 2005
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.
[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.
[ServiceContract]
public interface IPeople
{
[OperationContract]
public void StorePerson(Message msg);
}
Listing 16-14. Demonstrates implementing Message argument using Visual Basic .NET
<ServiceContract()> _
Public Interface IPeople
<OperationContract()> _
Sub StorePerson(msg As Message)
End Interface
WCF is responsible for dispatching the messages to the correct operation. Messages that are received that do
not have a matching Action header to the contract’s OperationContract Attribute are rejected. If we would like to
accept all messages regardless of their Action header we can set a wildcard indicator which is represented by a
single asterisk (“*”). If this operation is present, all messages that cannot be matched are sent to this operation.
Which results in more flexibility to the SOAP messaging endpoint.
650
The Complete Reference To Professional SOA with Visual Studio 2005
[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
Class Description
CustomBinding Custom binding allows us to tailor our need to define a new binding from a set of binding elements.
MsmqIntegrationBinding The MsmqIntegrationBinding binding can be used to map Microsoft Message Queuing Service
(MSMQ) messages to Windows Communication Foundation (WCF) messages.
NetMsmqBinding The NetMsmqBinding binding provides support for loosely coupled applications for queuing with
Microsoft Message Queue (MSMQ). This allows services to scale with failure isolation, load leveling and
disconnected operations.
NetNamedPipeBinding This binding provides a secure and reliable binding for same machine communication.
NetPeerTcpBinding The NetPeerTcpBinding binding provides support for TCP transport. This is used to support peer-to-
peer or multiparty applications.
NetTcpBinding The NetTcpBinding creates a run-time communication stack by default. NetTcpBinding utilizes WS-
ReliableMessaging for reliability. It also ensures message security and authentication by using Windows
651
The Complete Reference To Professional SOA with Visual Studio 2005
Security. NetTcpBinding uses TCP for message delivery, and a binary message encoding.
WSDualHttpBinding This binding uses HTTP for message delivery. The WSDualHttpBinding create a runtime stack
implementing WS-ReliableMessaging for reliability, WS-Security for message security and authentication.
This binding requires that the client has a public URI that provides a callback endpoint for the service.
WSHttpBinding This binding uses HTTP for message delivery. The WSHttpBinding is used for non-duplex service
contracts and provides support for securing with WS-Federation protocol.
Each of the predefined bindings supports some degree of customization of their respective features. If we
examine the configuration file required when specifying a particular binding there exists a <bindings> section
under this section where the binding used by WCF is defined. We can add a number of named customizations to
these subsections. The concrete binding that is used for an endpoint is selected by specifying the
bindingSectionName and the respective bindingConfigurationName within the definition for the endpoint.
Below shows an example of binding configuration in WCF.
<bindings>
<!-- configure a WSDualHttpBinding that supports duplex
communication -->
<wsDualHttpBinding>
<binding name="Binding1"
clientBaseAddress="http://localhost:8000/myClient/"
useDefaultWebProxy="true"
bypassProxyOnLocal="false">
<security mode="None">
<message algorithmSuite="Default"
clientCredentialType="Windows"
negotiateServiceCredential="true" />
</security>
</binding>
</wsDualHttpBinding>
</bindings>
In WCF an endpoint is defined with an <endpoint> element beneath the <service> element. The address of
the endpoint specifies the network address of the service. The bindingConfiguration refers to the predefined or
custom binding to be used and the contractType points to the interface class that hold the WCF [ServiceContract]
for the endpoint contract. If a class implements multiple service contracts, we will need to configure an endpoint
for each contract and all contracts must reside at distinct network addresses. A contract implementation for
which no endpoint is configured is not reachable everything must be explicit.
<endpoint address="http://localhost:10433/service/Service.svc"
binding="wsDualHttpBinding" bindingConfiguration="Binding1"
contract="Client.ICalculatorDuplex" />
A service can define any number of endpoints for each contract it implements. If we want a service to listen
to messages on HTTPS using the BasicHttpBinding with transport-level authentication, and on HTTP using the
WSHttpBinding with WS-Security in-message authentication, alongside the secure-by-default NetTcpBinding
for binary TCP transport, we can easily do so by adding the respective endpoints to the configuration and clients
can subsequently talk to the service through any endpoint they prefer. The service will listen to all these
endpoints in parallel.
652
The Complete Reference To Professional SOA with Visual Studio 2005
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.
Select WinFX Service under Templates, then select Location and choose the preferred programming language.
Notice immediately that the template for WinFX is different to that of the standard Web service.
Listing 16-17. Demonstrates the WinFX Service default template using Visual C#
using System;
using System.ServiceModel;
using System.Runtime.Serialization;
653
The Complete Reference To Professional SOA with Visual Studio 2005
[ServiceContract()]
public interface IMyService
{
[OperationContract]
string MyOperation1(string myValue1);
[OperationContract]
string MyOperation2(DataContract1 dataContractValue);
}
[DataContract]
public class DataContract1
{
string firstName;
string lastName;
[DataMember]
public string FirstName
{
get { return firstName;}
set { firstName = value;}
}
[DataMember]
public string LastName
{
get { return lastName;}
set { lastName = value;}
}
}
Listing 16-18. Demonstrates the WinFX Service Template using Visual Basic .NET
Imports System
Imports System.ServiceModel
Imports System.Runtime.Serialization
<ServiceContract()> _
Public Interface IMyService
<OperationContract()> _
Function MyOperation1 _
654
The Complete Reference To Professional SOA with Visual Studio 2005
<OperationContract()> _
Function MyOperation2 _
(ByVal dataContractValue1 As DataContract1) As String
End Interface
End Class
<DataContract()> _
Public Class DataContract1
Private m_firstName As String
Private m_lastName As String
End Class
The listings above shows the default template when a new WinFX Service is first created.
In the following example we will create a WCF Service that will retrieve as well as update contact information that is
stored within the Adventureworks SQL server database.
655
The Complete Reference To Professional SOA with Visual Studio 2005
Listing 16-19. Demonstrates the content of the WCF service using Visual C#
using System;
using System.ServiceModel;
using System.Runtime.Serialization;
using System.Data.SqlClient;
using System.Configuration;
using System.Data;
[ServiceContract()]
public interface IMyService
{
[OperationContract]
EmployeeContactDataContract RetrieveEmployeeContact(int EmployeeID);
[OperationContract]
void UpdateEmployeeContact(EmployeeContactDataContract dataContractValue);
}
public 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;
}
656
The Complete Reference To Professional SOA with Visual Studio 2005
sqlcmdEmployee.ExecuteNonQuery();
transaction.Commit();
sqlcon.Close();
}
}
[DataContract]
public class EmployeeContactDataContract
{
private string title;
private string firstName;
private string middleName;
private string lastName;
private int contactID;
[DataMember]
public int ContactID
{
get { return contactID; }
set { contactID = value; }
}
[DataMember]
public string Title
{
get { return title; }
set { title = value; }
}
[DataMember]
public string FirstName
{
get { return firstName;}
657
The Complete Reference To Professional SOA with Visual Studio 2005
[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
658
The Complete Reference To Professional SOA with Visual Studio 2005
End Class
<DataContract()> _
Public Class EmployeeContactDataContract
Private _title As String
Private _firstName As String
Private _middleName As String
Private _lastName As String
Private _contactID As Integer
<DataMember()> _
Public Property ContactID() As Integer
659
The Complete Reference To Professional SOA with Visual Studio 2005
Get
Return _contactID
End Get
Set(ByVal value As Integer)
_contactID = value
End Set
End Property
<DataMember()> _
Public Property Title() As String
Get
Return _title
End Get
Set(ByVal value As String)
_title = value
End Set
End Property
<DataMember()> _
Public Property FirstName() As String
Get
Return _firstName
End Get
Set(ByVal value As String)
_firstName = value
End Set
End Property
<DataMember()> _
Public Property MiddleName() As String
Get
Return _middleName
End Get
Set(ByVal value As String)
_middleName = value
End Set
End Property
<DataMember()> _
Public Property LastName() As String
Get
Return _lastName
End Get
Set(ByVal value As String)
_lastName = value
End Set
End Property
End Class
660
The Complete Reference To Professional SOA with Visual Studio 2005
have also decorated the two methods with the OperationContract attribute. This is similar to the WebMethod
attribute in that each attribute defines the attached method as an exposed operation.
We have also created a Class called EmployeeContactDataContract. This class is decorated with the
DataContract attribute, the DataContract attributes declares the class as a structural contract type in WCF. The
DataContract declaration specifies how a .NET type is represented in an XML Schema. Within the DataContract
we have also specified DataMembers. DataMembers are needed to specify exactly which properties are needed so
that when the DataContract is serialized over the wire only those that have been marked with DataMember will
be sent.
In the EmployeeContactDataContract method we are taking a ContactID as a parameter and returning an
EmployeeContactDataContract object.
In the UpdateEmployeeContact method we are receiving an EmployeeContactDataContract object and
updating the values within the object to the database.
Build the project if the project builds without error press F5 to Start Debugging.
661
The Complete Reference To Professional SOA with Visual Studio 2005
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
SvcUtil.exe will create both code and configuration information. We can add the addresses and bindings
into the configuration file (or incorporate it in code). The contract proxy classes should be added in our own
custom code. SvcUtil will create the contract proxies, contract interfaces, endpoint configuration information,
and more. Here is an example of source code output from Svcutil:
662
The Complete Reference To Professional SOA with Visual Studio 2005
Listing 16-21. Shows the generated proxy code from Svcutil using Visual C#
using System.Runtime.Serialization;
[System.CodeDom.Compiler.GeneratedCodeAttribute
("System.Runtime.Serialization", "3.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute()]
public partial class EmployeeContactDataContract : object,
System.Runtime.Serialization.IExtensibleDataObject
{
private System.Runtime.Serialization.ExtensionDataObject
extensionDataField;
[System.Runtime.Serialization.DataMemberAttribute()]
public int ContactID
{
get
{
return this.ContactIDField;
}
set
{
this.ContactIDField = value;
}
}
[System.Runtime.Serialization.DataMemberAttribute()]
public string FirstName
{
get
{
return this.FirstNameField;
}
set
{
663
The Complete Reference To Professional SOA with Visual Studio 2005
this.FirstNameField = value;
}
}
.
.
.
[System.CodeDom.Compiler.GeneratedCodeAttribute
("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute()]
public interface IMyService
{
[System.ServiceModel.OperationContractAttribute
(ProtectionLevel=System.Net.Security.ProtectionLevel
.EncryptAndSign,
Action="http://tempuri.org/IMyService/RetrieveEmployeeContact",
ReplyAction="http://tempuri.org/IMyService/
RetrieveEmployeeContactResponse")]
EmployeeContactDataContract RetrieveEmployeeContact(int EmployeeID);
[System.ServiceModel.OperationContractAttribute
(ProtectionLevel=System.Net.Security.ProtectionLevel
.EncryptAndSign,
Action="http://tempuri.org/IMyService/UpdateEmployeeContact",
ReplyAction="http://tempuri.org/IMyService/
UpdateEmployeeContactResponse")]
void UpdateEmployeeContact(EmployeeContactDataContract
dataContractValue);
}
[System.CodeDom.Compiler.GeneratedCodeAttribute
("System.ServiceModel", "3.0.0.0")]
public interface IMyServiceChannel : IMyService,
System.ServiceModel.IClientChannel
{
}
[System.CodeDom.Compiler.GeneratedCodeAttribute
("System.ServiceModel", "3.0.0.0")]
public partial class MyServiceProxy :
System.ServiceModel.ClientBase<IMyService>, IMyService
{
public MyServiceProxy()
{
}
664
The Complete Reference To Professional SOA with Visual Studio 2005
string remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}
.
.
.
public void UpdateEmployeeContact(EmployeeContactDataContract
dataContractValue)
{
base.InnerProxy.UpdateEmployeeContact(dataContractValue);
}
}
Listing 16-22. Shows the generated proxy code from Svcutil using Visual Basic .NET
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
665
The Complete Reference To Professional SOA with Visual Studio 2005
<System.Runtime.Serialization.DataMemberAttribute()> _
Public Property ContactID() As Integer
Get
Return Me.ContactIDField
End Get
Set
Me.ContactIDField = value
End Set
End Property
<System.Runtime.Serialization.DataMemberAttribute()> _
Public Property FirstName() As String
Get
Return Me.FirstNameField
End Get
Set
Me.FirstNameField = value
End Set
End Property
.
.
.
End Class
<System.CodeDom.Compiler.GeneratedCodeAttribute
("System.ServiceModel", "3.0.0.0"), _
System.ServiceModel.ServiceContractAttribute()> _
Public Interface IMyService
<System.ServiceModel.OperationContractAttribute
(ProtectionLevel:=System.Net.Security.ProtectionLevel
.EncryptAndSign,
Action:="http://tempuri.org/IMyService/RetrieveEmployeeContact",
ReplyAction:="http://tempuri.org/IMyService/
RetrieveEmployeeContactResponse")> _
Function RetrieveEmployeeContact
(ByVal EmployeeID As Integer) As EmployeeContactDataContract
<System.ServiceModel.OperationContractAttribute
(ProtectionLevel:=System.Net.Security.ProtectionLevel
.EncryptAndSign,
Action:="http://tempuri.org/IMyService/UpdateEmployeeContact",
ReplyAction:="http://tempuri.org/IMyService/
UpdateEmployeeContactResponse")> _
Sub UpdateEmployeeContact(ByVal dataContractValue As
EmployeeContactDataContract)
End Interface
<System.CodeDom.Compiler.GeneratedCodeAttribute
("System.ServiceModel", "3.0.0.0")> _
Public Interface IMyServiceChannel
Inherits IMyService, System.ServiceModel.IClientChannel
End Interface
666
The Complete Reference To Professional SOA with Visual Studio 2005
<System.CodeDom.Compiler.GeneratedCodeAttribute
("System.ServiceModel", "3.0.0.0")> _
Partial Public Class MyServiceProxy
Inherits System.ServiceModel.ClientBase(Of IMyService)
Implements IMyService
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
667
The Complete Reference To Professional SOA with Visual Studio 2005
maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32"
maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096"
maxNameTableCharCount="16384" />
<reliableSession ordered="true"
inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Message">
<transport clientCredentialType="None"
proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows"
negotiateServiceCredential="true"
algorithmSuite="Default"
establishSecurityContext="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:27771/
EmployeeDetailService/Service.svc"
binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IMyService"
contract="IMyService"
name="WSHttpBinding_IMyService" />
</client>
</system.serviceModel>
</configuration>
Once the MyService.cs file and the output.config file have been generated be sure to rename output.config
to app.config and include the two files into the client project.
using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
namespace ContactClient
{
class Program
{
static void Main(string[] args)
{
MyServiceProxy proxy =
new MyServiceProxy("WSHttpBinding_IMyService");
EmployeeContactDataContract contactDC =
proxy.RetrieveEmployeeContact(1);
668
The Complete Reference To Professional SOA with Visual Studio 2005
Listing 16-25. Demonstrates implementing the WCF client using Visual Basic
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.ServiceModel
Namespace VBContactClient
Module Module1
Sub Main()
Dim proxy As MyServiceProxy = _
New MyServiceProxy("WSHttpBinding_IMyService")
Dim contactDC As EmployeeContactDataContract _
= proxy.RetrieveEmployeeContact(1)
Console.WriteLine("############***Retrieved Contact***######")
DisplayContact(contactDC)
contactDC.FirstName = "John"
contactDC.MiddleName = "Smith"
contactDC.LastName = "Doe"
proxy.UpdateEmployeeContact(contactDC)
Console.WriteLine("############***Updated Contact***######")
DisplayContact(contactDC)
Console.ReadLine()
669
The Complete Reference To Professional SOA with Visual Studio 2005
End Sub
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.
670
The Complete Reference To Professional SOA with Visual Studio 2005
Implementing Hosting
Windows Communication Foundation supports self-hosting and web hosting. Self hosting refers to the
application being able to be hosted within any of the .NET applications without the reliance on IIS this is very
similar to .NET Remoting. While Web hosting refers to hosting the WCF service application in Internet
Information Services (IIS). The onus is on the developer to pick the right hosting model for the right application.
It is important to note that WCF services aren’t tied to a specific application model and can support self-hosted
to remotely hosted scenarios.
In order to implement hosting we need to develop our service in a class library instead of using WinFX
Service. Create a new console application by File-> New->Project chose the preferred language and then select
Class Library from under Templates.
671
The Complete Reference To Professional SOA with Visual Studio 2005
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 EmployeeContactDataContract
RetrieveEmployeeContact(int ContactID)
{
// retrieve employee contact details
string sql = String.Format
("select ContactID, Title, FirstName, MiddleName, LastName" +
" from Person.Contact where ContactID = {0}", ContactID);
SqlCommand sqlcmd = new SqlCommand(sql, sqlcon);
sqlcon.Open();
SqlDataReader dreader = sqlcmd.ExecuteReader();
dreader.Read();
EmployeeContactDataContract contactDC =
new EmployeeContactDataContract();
contactDC.ContactID = (int)dreader["ContactID"];
contactDC.Title = dreader["Title"].ToString();
contactDC.FirstName = dreader["FirstName"].ToString();
contactDC.MiddleName = dreader["MiddleName"].ToString();
contactDC.LastName = dreader["LastName"].ToString();
sqlcon.Close();
return contactDC;
672
The Complete Reference To Professional SOA with Visual Studio 2005
sqlcmdEmployee.ExecuteNonQuery();
transaction.Commit();
sqlcon.Close();
}
}
[DataContract]
public class EmployeeContactDataContract
{
private string title;
private string firstName;
private string middleName;
private string lastName;
private int contactID;
[DataMember]
public int ContactID
{
get { return contactID; }
set { contactID = value; }
}
[DataMember]
public string Title
{
673
The Complete Reference To Professional SOA with Visual Studio 2005
[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
674
The Complete Reference To Professional SOA with Visual Studio 2005
<DataContract()> _
Public Class EmployeeContactDataContract
Private _title As String
Private _firstName As String
Private _middleName As String
675
The Complete Reference To Professional SOA with Visual Studio 2005
<DataMember()> _
Public Property ContactID() As Integer
Get
Return _contactID
End Get
Set(ByVal value As Integer)
_contactID = value
End Set
End Property
<DataMember()> _
Public Property Title() As String
Get
Return _title
End Get
Set(ByVal value As String)
_title = value
End Set
End Property
<DataMember()> _
Public Property FirstName() As String
Get
Return _firstName
End Get
Set(ByVal value As String)
_firstName = value
End Set
End Property
<DataMember()> _
Public Property MiddleName() As String
Get
Return _middleName
End Get
Set(ByVal value As String)
_middleName = value
End Set
End Property
<DataMember()> _
Public Property LastName() As String
Get
Return _lastName
End Get
Set(ByVal value As String)
_lastName = value
End Set
End Property
End Class
676
The Complete Reference To Professional SOA with Visual Studio 2005
Once complete build the class library to ensure that it builds without error. Now we will add a console
application project to the solution. Add a VB Console Application to the current project. File->Add->New
Project Select the language then Console Application under templates. We will call this new project Host.
Tip: we’re not limited to only console applications; we can host the WCF service in any windows application.
Also add the reference to the System.ServiceModel .NET assembly as well as the
System.Runtime.Serialization assembly to the project.
Once the .NET references have been added, add another reference to the service library we had just created
above.
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.
using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
namespace Host
{
class Program
{
static void Main(string[] args)
{
Type serviceType = typeof(MyService);
string httpBaseAddress = "http://localhost:8020/Contact";
string tcpBaseAddress = "net.tcp://localhost:8021/Contact";
Uri httpBaseAddressUri = new Uri(httpBaseAddress);
677
The Complete Reference To Professional SOA with Visual Studio 2005
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.ServiceModel
Imports VBHost
Namespace Host
Class Program
678
The Complete Reference To Professional SOA with Visual Studio 2005
httpbinding, httpBaseAddress)
host.AddServiceEndpoint _
(GetType(VBServiceLibrary.IMyService), _
tcpbinding, tcpBaseAddress)
host.Open()
Console.WriteLine("WCF service start")
Console.ReadLine()
host.Close()
Finally
CType(host, IDisposable).Dispose()
End Try
End Sub
End Class
End Namespace
In the above listing the hosting code is placed inside the Main method of the console application. Whenever
the console application runs the WCF service will startup with the application. We first create an array of Uris
these are what we intend to use as the end point addresses. We have specified both a HTTP location as well as a
TCP location.
string tcpBaseAddress = "net.tcp://localhost:8021/Contact";
679
The Complete Reference To Professional SOA with Visual Studio 2005
By browsing to the location of our HTTP binded endpoint we can view the service running (see figure 16-
10. above). We can also view the WSDL generated by this service simply by adding the traditional “?wsdl” at
the end of the service name. For example:
http://localhost:8020/contact?wsdl
680
The Complete Reference To Professional SOA with Visual Studio 2005
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
The ability to host a WCF application within any windows application adds a great deal of flexibility. We
can create a windows service application that will start running every windows starts up.
681
The Complete Reference To Professional SOA with Visual Studio 2005
682
The Complete Reference To Professional SOA with Visual Studio 2005
In the following example we will specify reliableSession using the WCF Contact Service example we had
created earlier.
Open the EmployeeDetailService, simply select the configuration file in the solution explorer in our case the
Web.config file. Right mouse click and there is a new menu selection Edit WCF Configuration this is a menu
option that is added after installing the WinFX windows SDK. Click on the selection.
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.
683
The Complete Reference To Professional SOA with Visual Studio 2005
Selecting the Create a New Binding will bring up a “Create a New Binding” dialog window. Select
wsHttpBinding, since we will be communicating via HTTP and we also want to specify reliable messaging this
is required.
Click OK once complete
This will add a new wsHttpBinding node under Bindings. Select the name attribute under configuration and
change the name from NewBinding to reliableBinding. Then under ReliableSession Properties change Enabled
from False to True.
684
The Complete Reference To Professional SOA with Visual Studio 2005
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.
685
The Complete Reference To Professional SOA with Visual Studio 2005
Select the File menu -> Save to commit the changes to Web.config file.
<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<appSettings>
<add key="ConnectionString"
value="Data Source=localhost;Initial Catalog=AdventureWorks;
Persist Security Info=True;User ID=Book;Password=Book" />
</appSettings>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="reliableBinding">
<reliableSession enabled="true" />
</binding>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="returnFaults" name="MyService">
<endpoint binding="wsHttpBinding"
bindingConfiguration="reliableBinding"
name="reliableEndpoint" contract="IMyService" />
</service>
</services>
<behaviors>
<behavior name="returnFaults" returnUnknownExceptionsAsFaults="true" />
</behaviors>
</system.serviceModel>
<system.web>
<compilation debug="true"/>
</system.web>
</configuration>
By completing the above steps we have created a service which uses reliable session. As reliability is a two
way operation we will also need to do the same for the client side application. Open the ContactClient
application in Visual Studio. Select app.config in the solution explorer right mouse click to bring the “Edit WCF
Configuration” menu. Select it. The difference between client and server configuration is that the binding and
endpoint for the client has already been specified. This is because when we generated the client proxy using
SvcUtil.exe the utility has already automatically created the binding and endpoint configuration for us. So it is
just a simple matter of selecting the existing binding and under ReliableSession Properties change the Enabled
attribute from False to True.
686
The Complete Reference To Professional SOA with Visual Studio 2005
687
The Complete Reference To Professional SOA with Visual Studio 2005
contract="IMyService"
name="WSHttpBinding_IMyService" />
</client>
</system.serviceModel>
</configuration>
Selecting the Create a New Binding will bring up a “Create a New Binding” dialog window. Select
customBinding, this is required as we need to select reliable session.
688
The Complete Reference To Professional SOA with Visual Studio 2005
Selecting this the customBinding will create a new node under Bindings called NewBinding. Right mouse
click this new binding and select the “Add Binding Element Extension(s)…” option.
689
The Complete Reference To Professional SOA with Visual Studio 2005
Selecting the option will bring up the “Adding Binding Element Extensions Sections” simply select
reliableSession and click Add.
By adding the reliableSession element to the binding we now have a new node under NewBinding called
reliableSession.
690
The Complete Reference To Professional SOA with Visual Studio 2005
The default values for reliableSession are shown below in the table.
We will leave the default values as they are. This will create the reliableSession element. Because the values
are default the element that will be created will only be a single element of <reliableSession /> however
alternatively we could also specify each attribute as shown below:
<reliableSession acknowledgementInterval="00:00:00.2000000"
enableFlowControl="true" maxTransferWindowSize="32"
inactivityTimeout="00:10:00" maxPendingChannels="128"
maxRetryCount="8" ordered="true" />
We also need to adjust the customBinding as by default the transport mode is set to tcpTransport. To change
this right mouse click on the tcpTransport select Remove Extension.
691
The Complete Reference To Professional SOA with Visual Studio 2005
Select the NewBinding(customBinding) node and change the Name to reliableBinding. Then right mouse
click on reliableBinding select “Add Binding Element…” and select httpTransport. This will add httpTransport
as our selected mode for communication.
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.
692
The Complete Reference To Professional SOA with Visual Studio 2005
We also need to add security to this customBinding. To do this right click on reliableBinding click on “Add
Binding Element Extension(s)”. Select security and click Add.
By adding the security extension. A new node under customBinding will appear. Security properties can be
easily configured through the Service Configuration Editor. For the purpose of this example we will leave them
as they are.
693
The Complete Reference To Professional SOA with Visual Studio 2005
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.
Selecting the customBinding option will result in the BindingConfiguration being automatically filled in.
694
The Complete Reference To Professional SOA with Visual Studio 2005
<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<appSettings>
<add key="ConnectionString"
value="Data Source=localhost;Initial Catalog=AdventureWorks;
Persist Security Info=True;User ID=Book;Password=Book" />
</appSettings>
<system.serviceModel>
<bindings>
<customBinding>
<binding name="reliableBinding">
<textMessageEncoding />
<reliableSession />
<security>
<issuedTokenParameters>
<issuer address="" />
<issuerMetadata address="" />
</issuedTokenParameters>
<secureConversationBootstrap />
</security>
<httpTransport />
695
The Complete Reference To Professional SOA with Visual Studio 2005
</binding>
</customBinding>
</bindings>
<services>
<service behaviorConfiguration="returnFaults" name="MyService">
<endpoint binding="customBinding"
bindingConfiguration="reliableBinding"
name="reliableEndpoint" contract="IMyService" />
</service>
</services>
<behaviors>
<behavior name="returnFaults"
returnUnknownExceptionsAsFaults="true" />
</behaviors>
</system.serviceModel>
<system.web>
<compilation debug="true"/>
</system.web>
</configuration>
Now we will have successfully enabled a reliable session for our service. Reliability needs to be
implemented on both ends so we will need to do the same for our client application. The only exception being
that instead of specifying the endpoint under Services specify it under Client.
696
The Complete Reference To Professional SOA with Visual Studio 2005
One thing to note is that the order of which the Extensions are executed are important. With Service
Configuration Editor its quite easy to change the ordering of these extensions. If any extensions are out of sync
between the client and the server then the two can not communicate. We should also always move security
towards the lower end position of execution so that security can include higher level operations.
697
The Complete Reference To Professional SOA with Visual Studio 2005
* Asynchronous message delivery. The sender and recipient do not need to be running at the same time.
* Message logging services. A journal of all messages sent can be recorded and stored for later review.
* Security. Access permission can be set on queues and the message bodies themselves can automatically be
encrypted.
WCF has the ability to bind with Microsoft Message Queue. This allows us to develop infrastructures to
create queued channels. Using queues can be particularly important in distributed systems where services can get
bogged down with one-way requests. Rather than rejecting requests it is a good idea to store them away so that
they can be processed at a later time.
698
The Complete Reference To Professional SOA with Visual Studio 2005
In this section we will be implementing a client purchase ordering system using Microsoft Message Queue.
To support implementing MSMQ we need to first install it on our system. This can be done by choosing “Add or
Remove Programs from the Windows Control panel”. Then click “Add/Remove Windows Components”.
Browse to “Application Server” in the Windows Components Wizard window as shown below and click on the
details button.
If the Message Queuing is not checked in the Application Server window, as shown below. Then check it,
and click on the OK button and then on the Next button in the Windows Components Wizard and follow the
instruction son the subsequent screens to install MSMQ.
699
The Complete Reference To Professional SOA with Visual Studio 2005
Now to create the order processing service first create a Console application called MSMQ. The
implementation is shown below:
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);
Queue.ReceiveCompleted +=
new ReceiveCompletedEventHandler(ProcessOrder);
Queue.BeginReceive();
Console.WriteLine("Order Service is running");
Console.ReadLine();
}
700
The Complete Reference To Professional SOA with Visual Studio 2005
Queue.BeginReceive();
}
catch (System.Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Messaging
Imports System.Configuration
Imports Order.MSMQ
Namespace MSMQ
Class Program
701
The Complete Reference To Professional SOA with Visual Studio 2005
Catch ex As System.Exception
Console.WriteLine(ex.Message)
End Try
End Sub
End Class
End Namespace
</configuration>
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.
if (!MessageQueue.Exists
702
The Complete Reference To Professional SOA with Visual Studio 2005
(ConfigurationManager.AppSettings["queueName"]))
MessageQueue.Create
(ConfigurationManager.AppSettings["queueName"], true);
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.
703
The Complete Reference To Professional SOA with Visual Studio 2005
using System;
using System.Text;
namespace MSMQ
{
// Define the Purchase Order Line Item
[Serializable]
public class PurchaseOrderLineItem
{
704
The Complete Reference To Professional SOA with Visual Studio 2005
Listing 16-45. Shows implementing the order class using Visual Basic .NET
Imports System
Imports System.Text
Namespace MSMQ
705
The Complete Reference To Professional SOA with Visual Studio 2005
<Serializable()> _
Public Class PurchaseOrderLineItem
Public productId As String
Public unitCost As Single
Public quantity As Integer
<Serializable()> _
Public Class PurchaseOrder
Public poNumber As String
Public customerId As String
Public orderLineItems As PurchaseOrderLineItem()
Public orderStatus As OrderStates
706
The Complete Reference To Professional SOA with Visual Studio 2005
using System;
using System.Collections.Generic;
using System.Text;
using System.Transactions;
using System.ServiceModel.MsmqIntegration;
using System.ServiceModel;
using System.Messaging;
namespace MSMQ
{
class Program
{
static void Main(string[] args)
{
// Create the purchase order
PurchaseOrder po = new PurchaseOrder();
po.customerId = "xyz customer id";
po.poNumber = Guid.NewGuid().ToString();
PurchaseOrderLineItem lineItem1 =
new PurchaseOrderLineItem();
lineItem1.productId = "Blue Widget";
lineItem1.quantity = 10;
lineItem1.unitCost = 15.58F;
PurchaseOrderLineItem lineItem2 =
new PurchaseOrderLineItem();
lineItem2.productId = "Red Widget";
707
The Complete Reference To Professional SOA with Visual Studio 2005
lineItem2.quantity = 890;
lineItem2.unitCost = 45.89F;
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
708
The Complete Reference To Professional SOA with Visual Studio 2005
<Serializable()> _
Public Class PurchaseOrder
Public poNumber As String
Public customerId As String
Public orderLineItems As PurchaseOrderLineItem()
Public orderStatus As OrderStates
709
The Complete Reference To Professional SOA with Visual Studio 2005
In the Client implementation the order is set before it is sent to the message queue. We will be relying on
WCF to send the message to the queue. By using the System.ServiceModel.MsmqIntegration.MsmqMessage. The
MsmqMessage class encapsulates an MSMQ message that is sent and received, over a MSMQ integration
channel, to and from an existing MSMQ application.
MsmqMessage<PurchaseOrder> ordermsg =
new MsmqMessage<PurchaseOrder>(po);
using (TransactionScope scope =
new TransactionScope(TransactionScopeOption.Required))
{
orderProcessor.SubmitPurchaseOrder(ordermsg);
scope.Complete();
}
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.
710
The Complete Reference To Professional SOA with Visual Studio 2005
6. Select the Security tab on OrderProcessorBinding and change the security Mode to None.
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.
711
The Complete Reference To Professional SOA with Visual Studio 2005
<system.serviceModel>
<bindings>
<msmqIntegrationBinding>
<binding name="OrderProcessorBinding">
<security mode="None" />
</binding>
</msmqIntegrationBinding>
</bindings>
<client>
<endpoint
address="msmq.formatname:DIRECT=OS:.\private$\Orders"
binding="msmqIntegrationBinding"
bindingConfiguration="OrderProcessorBinding"
contract="Client.MSMQ.IOrderProcessor"
name="OrderResponseEndpoint" />
</client>
</system.serviceModel>
</configuration>
Now we can execute the application. Since we’re using MSMQ as middleware we don’t have to start both
applications at the same time. The results are shown below in figure 16-37 and figure 16-38.
712
The Complete Reference To Professional SOA with Visual Studio 2005
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.
[ServiceContract(Session=true)]
public interface IMyService
{
[OperationContract]
int Add(int num);
}
<ServiceContract(Session:=True)> _
Public Interface IMyService
<OperationContract()> _
Function Add(ByVal num As Integer) As Integer
End Interface
713
The Complete Reference To Professional SOA with Visual Studio 2005
WCF Transactions
WCF supports a variety of transacted communications. The following code demonstrates a transacted service
operation. To enable a transaction in WCF, use the transaction parameters within the OperationBehavior
attribute, the listing 16-52 and listing 16-53 shows an example of implementing automatic transaction by setting
TransactionAutoComplete = true.
[ServiceContract(Session=true)]
public interface IMyService
{
[OperationContract]
[OperationBehavior(
TransactionScopeRequired = true,
TransactionAutoComplete= true)]
int Add(int num);
}
<ServiceContract(Session:=True)> _
Public Interface IMyService
<OperationContract()> _
<OperationBehavior(TransactionScopeRequired:=True,_
TransactionAutoComplete:=True)> _
Function Add(ByVal num As Integer) As Integer
End Interface
Duplex Communication
Traditional remote procedure calls (RPCs) use in-and-out operations. WCF supports multichannel inout
operations, otherwise known as duplex communication. These are implemented using duplex contracts. A duplex
Contract defines two logical sets of operations, A set that the Service exposes for the Client to call and a set that
the Client exposes for the Service to call. The programming model for defining a duplex Contract is to split each
set in a separate type (each type must be a class or an interface). We should use ServiceContract to define our
inputs and CallContract to define the outputs. In the following example we will be developing a duplex WCF
service that performs a large operation before sending a response back to the client on a separate channel see
listing 16-54 and listing 16-55.
Listing 16-54. Demonstrates service implementation using Duplex communication using Visual C#
using System;
using System.ServiceModel;
using System.Threading;
[ServiceContract(Namespace = "http://WCF.Duplex",
Session = true, CallbackContract=typeof(ICalculatorDuplexCallback))]
public interface ICalculatorDuplex
{
714
The Complete Reference To Professional SOA with Visual Studio 2005
[OperationContract(IsOneWay=true)]
void Clear();
[OperationContract(IsOneWay = true)]
void VeryLongAddOperation(double n);
}
[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>();
}
totalDuration = (TimeSpan)DateTime.Now.Subtract(start);
}
}
Listing 16-55. Demonstrates using Duplex communication using Visual Basic .NET
Imports System
Imports System.ServiceModel
715
The Complete Reference To Professional SOA with Visual Studio 2005
Imports System.Runtime.Serialization
Imports System.Threading
<ServiceContract(Namespace:="http://WCF.Duplex", _
Session:=True, CallbackContract:=GetType(ICalculatorDuplexCallback))> _
Public Interface ICalculatorDuplex
<OperationContract(IsOneWay:=True)> _
Sub Clear()
<OperationContract(IsOneWay:=True)> _
Sub VeryLongAddOperation(ByVal n As Double)
End Interface
<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
716
The Complete Reference To Professional SOA with Visual Studio 2005
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:
<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:
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”.
717
The Complete Reference To Professional SOA with Visual Studio 2005
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”
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.
<?xml version="1.0"?>
718
The Complete Reference To Professional SOA with Visual Studio 2005
<configuration>
<system.serviceModel>
<behaviors>
<behavior name="CalculatorServiceBehavior"/>
</behaviors>
<bindings>
<wsDualHttpBinding>
<binding name="duplexBinding">
<security mode="None" />
</binding>
</wsDualHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="CalculatorServiceBehavior"
name="CalculatorService">
<endpoint binding="wsDualHttpBinding"
bindingConfiguration="duplexBinding"
contract="ICalculatorDuplex" />
</service>
</services>
</system.serviceModel>
<system.web>
<compilation debug="true"/></system.web></configuration>
Implementing the client application for duplex communication is not very different to how we normally
develop. All the duplex specification is handled by WCF at the binding level. The only thing to keep in mind is
that we do need to wait for the WCF service to return the result from the execution. As the client does not wait
for the service to return and this causes an exception to be thrown when the server tries to return the result and
realize the proxy is out of scope.
To implement the client first create a new console application and call it Client. Then use the svcutil to
generate the proxy by:
svcutil http://localhost:10433/Service/Service.svc
Or for Visual Basic .NET:
svcutil http://localhost:10433/Service/Service.svc /language:vb
Include the output.config and the generated CalculatorService class to the project rename the output.config
file to App.config.
using System;
using System.ServiceModel;
719
The Complete Reference To Professional SOA with Visual Studio 2005
Console.WriteLine("Equals({0})", result);
}
class Client
{
static void Main()
{
// Construct InstanceContext to handle messages on callback
// interface
InstanceContext instanceContext =
new InstanceContext(new CallbackHandler());
// Complete equation
proxy.Clear();
System.Threading.Thread.Sleep(5000);
}
Console.WriteLine();
Console.WriteLine("Press <ENTER> to terminate client.");
Console.ReadLine();
}
}
Listing 16-62. Demonstrates duplex client implementation using Visual Basic .NET
Imports System
Imports System.ServiceModel
Imports System.Runtime.Serialization
Imports System.Threading
<ServiceContract(Namespace:="http://WCF.Duplex", _
Session:=True, CallbackContract:=GetType(ICalculatorDuplexCallback))> _
Public Interface ICalculatorDuplex
<OperationContract(IsOneWay:=True)> _
720
The Complete Reference To Professional SOA with Visual Studio 2005
Sub Clear()
<OperationContract(IsOneWay:=True)> _
Sub VeryLongAddOperation(ByVal n As Double)
End Interface
<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
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.
721
The Complete Reference To Professional SOA with Visual Studio 2005
InstanceContext instanceContext =
new InstanceContext(new CallbackHandler());
722
The Complete Reference To Professional SOA with Visual Studio 2005
Now we need to examine the configuration for the WCF client application. Using the svcutil.exe we have
already generated the output.config file which we have renamed to App.config. Simply right mouse click the
App.config file in solution explorer select “Edit WCF Configuration”. Expand the Advanced node, under
Bindings selet the wsDualHttpBinding node add an address of http://localhost:8000/myClient/ to the
ClientBaseAddress property. We need to add this address because when the WCF service returns the result this
is the address from which the WCF service will call.
Select File->Save to commit the changes to the App.config file.
Summary
In this chapter, we have covered the fundamentals of WCF ABCs. We have also learnt to implement WCF
service as well as creating WCF client with the help of SvcUtil.exe to automatically create client side proxy and
configuration.
We have walked through developing hosting environment for a WCF service from which a WCF service can
be launched.
We have also covered developing for secure and reliable messaging. While configuring the WCF service
and client with Microsoft Service Configuration Editor (SvcConfigEditor) which helps to fast track WCF
configuration files.
We have explored the concept of bindings and endpoints and looked at developing and implementing both.
We have also covered how to implement custom bindings to mix and match our requirement in protocols with
WCF.
In this chapter we have also looked at using WCF to communicate with a Microsoft Message Queue
(MSMQ). This allows the client to submit orders to the middleware queue regardless of the status of the
processing service.
Lastly we have implemented duplex communication with the new WCF duplex model.
723
The Complete Reference To Professional SOA with Visual Studio 2005
* 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.
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
724
The Complete Reference To Professional SOA with Visual Studio 2005
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.
725
The Complete Reference To Professional SOA with Visual Studio 2005
Item Description
Pointer The pointer tool is used for selecting and moving objects
Connection The connection tool is used to link two application prototype endpoints
Comment The comment tools creates a comment text box
WebServiceEndpoint Represents a connection endpoint for a web service provider/consumer
WebContentEndpoint Represents a connection endpoint for a web content provider/consumer
GenericEndpoint Represents a connection point to services of a generic type
provider/consumer
WindowsApplication Represents a windows application
ASP.NETWebService An ASP.NET web service application that includes a web service endpoint
ASP.NETWebApplication An ASP.NET web application that includes a web content endpoint
OfficeApplication Represents a Microsoft Office application (Excel, Word and Outlook
templates)
ExternalWebService A reference to a single web service defined by a single Web Service
Description Language .wsdl file
ExternalDatabase Represents a database system
BizTalkWebService Reprents a BizTalkWebService
GenericApplication A generic user-defined application that supports user-defined settings and
constraints.
Click the ASP.NETWebService Tool from under the Applications section of the toolbar and drag and drop it
on to the design surface. This will create an ASP.NETWebApplication shape onto our designer see figure 17-3.
By default the the ASP.NETWebApplication shape has one Web service endpoint called WebService1.
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.
726
The Complete Reference To Professional SOA with Visual Studio 2005
Right Click on the database shape and select properties, by default the name is Database1 change the name
to AdventureWorks. This will change the name of the endpoint, this implies that other applications will be
connecting to the AdventureWorks database.
Creating connections is fairly straight forward. The application designer contains constraints about
connections for example we can not connect a connection between a Web service endpoint and that of a
Database endpoint see figure 17-6. Logically it doesn’t make sense as a Web service endpoint provides service
functionalities and the endpoint itself is to be consumed. While a database endpoint is used by an application to
connect to the database. So if we tried to drag and drop a connection from a Web service endpoint to a database
endpoint the designer will not allow us to establish the connection.
727
The Complete Reference To Professional SOA with Visual Studio 2005
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.
TIP: If we’re only whiteboarding our idea to designer we don’t have to specify the connection details simply click cancel to configure the
connection at a later time.
To verify the connection properties, right-click the database consumer endpoint of our web service and
select Properties. In the properties section the connection information is stored under Connection String, as
shown in figure 17-8 (below). This Connection String property will be generated into the Web.config file of the
AdventureWorks application when it is implemented.
728
The Complete Reference To Professional SOA with Visual Studio 2005
Now we should have a diagram which look like the figure below.
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:
729
The Complete Reference To Professional SOA with Visual Studio 2005
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
Name="AdventureWorks" Version="1.0.0.0"
Culture="en-US" DocumentLanguage="en-US"
xmlns="http://schemas.microsoft.com/SystemDefinitionModel/2005/1">
<Import Alias="System" Name="System" Version="1.0.50729.0" />
<Import Alias="MicrosoftDatabase"
Name="Microsoft.Database" Version="1.0.50729.0" />
<Import Alias="MicrosoftData"
Name="Microsoft.Data" Version="1.0.50729.0" />
<DesignData>
<VisualStudio
xmlns="http://schemas.microsoft.com/SystemDefinitionModel/2005/1/
DesignData/VisualStudio">
<ModelElement Id="25efdca4f5544980a3349613dabd38cb"
Type="Microsoft.VisualStudio.EnterpriseTools.Application
.Modeling.SoftwareComponentDocument">
<Property Name="Version" Value="1" />
</ModelElement>
</VisualStudio>
</DesignData>
<SystemDefinition Name="AdventureWorks"
Extends="MicrosoftDatabase:Database" SimulationRoot="false">
<DesignData>
<VisualStudio xmlns="http://schemas.microsoft.com/
SystemDefinitionModel/2005/1/DesignData/VisualStudio">
<ModelElement
Type="Microsoft.VisualStudio.EnterpriseTools.Application
.Modeling.PlugIns.DeployedDBComponentType">
<Property Name="State" Value="Implemented" />
<Property Name="Realization" Value="External" />
</ModelElement>
</VisualStudio>
</DesignData>
<EndpointDefinition Name="DatabaseProviderEndpoint1"
Extends="MicrosoftData:DataServer">
<DesignData>
<VisualStudio xmlns="http://schemas.microsoft.com/
SystemDefinitionModel/2005/1/DesignData/VisualStudio">
<ModelElement Type="Microsoft.VisualStudio.EnterpriseTools
.Application.Modeling.ApplicationPortType" />
</VisualStudio>
</DesignData>
</EndpointDefinition>
<Endpoint Name="AdventureWorks"
Definition="AdventureWorks.DatabaseProviderEndpoint1"
MinOccurs="1" MaxOccurs="1" Reference="false">
<DesignData>
<VisualStudio
xmlns="http://schemas.microsoft.com/SystemDefinitionModel/
2005/1/DesignData/VisualStudio">
<ModelElement
Type="Microsoft.VisualStudio.EnterpriseTools.Application
730
The Complete Reference To Professional SOA with Visual Studio 2005
.Modeling.PlugIns.DeployedDBProviderPort">
<Property Name="State" Value="Implemented" />
<Property Name="NeedsGeneration" Value="true" />
</ModelElement>
</VisualStudio>
</DesignData>
</Endpoint>
<Containment Name="AdventureWorksContainment"
Definition="MicrosoftDatabase:DatabaseContainsDataServer"
ChildMember="AdventureWorks" />
</SystemDefinition>
</SystemDefinitionModel>
In the above listing we can see that the diagram object has a state of Implemented. This is also categorized
by the object’s shadow over its shape see figure 17-9.
There are several different endpoints that are used for different providers. We can only connect a consumer
endpoint to only a single provider endpoint. The Table 17-2 illustrates the different shapes for different
endpoints and their associated meanings.
Endpoint Description
Generic endpoint
Database endpoint
* We can create connections between existing endpoints, or if an application does not have endpoints, we can
add them, if supported by the application type.
* Endpoints define their role in communication as consumers or providers of services. Therefore, the direction in
which we draw a connection does not affect the direction of that connection.
* When an application or endpoint is selected, choosing the Connect command from the Diagram or context
menu opens a connection dialog box. In the connection dialog box, we can choose a compatible application and
a provider endpoint on that application to complete the connection.
* We can begin a connection from a provider endpoint by using the Connection tool or the Connect command.
731
The Complete Reference To Professional SOA with Visual Studio 2005
* We cannot draw connections directly between applications using the Connection tool. However, we can draw a
connection between an application and a suitable provider endpoint, starting from either the application or the
provider endpoint.
* If compatible provider and consumer endpoints exist, we can connect them by beginning the connection from
either endpoint using the Connection tool or Connect command.
* If a connection has been deleted, we can reconnect the disconnected applications directly between their
endpoints.
To add these operations Click <add operation> and type the name AddContact.
1. Click the plus sign next to the AddContact function to reveal the <add parameter> section.
2. Then click <add parameter> and add the following parameters: FirstName, MiddleName, LastName change
their Type to String.
3. Following the above steps add the operations for UpdateContactByID, RemoveContactByID and
SelectContactByID see figure 17-11 below.
732
The Complete Reference To Professional SOA with Visual Studio 2005
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 () {
[WebMethod]
public string HelloWorld1() {
return "Hello World";
}
[WebMethod]
public string HelloWorld2()
{
return "Hello World";
733
The Complete Reference To Professional SOA with Visual Studio 2005
[WebMethod]
public string HelloWorld3()
{
return "Hello World";
}
}
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class Service
Inherits System.Web.Services.WebService
<WebMethod()> _
Public Function HelloWorld1() As String
Return "Hello World"
End Function
<WebMethod()> _
Public Function HelloWorld2() As String
Return "Hello World"
End Function
<WebMethod()> _
Public Function HelloWorld3() As String
Return "Hello World"
End Function
End Class
To add the above implementation or any WSDL document to the designer as an endpoint simply right
mouse-click the ASP.NETWebApplication object and select “Create Web Service Endpoint From WSDL” see
figure 17-12.
734
The Complete Reference To Professional SOA with Visual Studio 2005
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.
This will result in another Web service endpoint called Service see figure 17-14 below.
735
The Complete Reference To Professional SOA with Visual Studio 2005
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.
1. Click ASP.NETWebApplication in the application diagram and right mouse click and select Properties. In the
Implementation section, select the language to generate as Visual C# figure 17-16.
736
The Complete Reference To Professional SOA with Visual Studio 2005
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.
4. The Save File dialog box appears we’re prompted to save the Application Designer Prototype. Click Save, and
WebserviceContactManager is added to our Toolbox see figure 17-18.
737
The Complete Reference To Professional SOA with Visual Studio 2005
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.
738
The Complete Reference To Professional SOA with Visual Studio 2005
2. Select OK and wait for the application code to be generated inside the solution. We may receive a warning that
the connection string is being written into the configuration files unencrypted see figure 17-20. Select close to
let the process continue.
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.
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.
739
The Complete Reference To Professional SOA with Visual Studio 2005
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
namespace WebserviceContactManagement
{
[System.Web.Services.WebServiceBinding(
Name = "WebService1",
ConformsTo = System.Web.Services.WsiProfiles.BasicProfile1_1,
EmitConformanceClaims = true),
System.Web.Services.Protocols.SoapDocumentService()]
public class WebService1 : System.Web.Services.WebService
{
/// <summary>
/// Add a contact
/// </summary>
[System.Web.Services.WebMethod(),
System.Web.Services.Protocols.SoapDocumentMethod
(Binding = "WebService1")]
public void AddContact(string FirstName,
string MiddleName, string LastName)
{
throw new System.NotImplementedException();
}
/// <summary>
/// Update a contact detail by ID
/// </summary>
[System.Web.Services.WebMethod(),
System.Web.Services.Protocols.SoapDocumentMethod(Binding =
"WebService1")]
public void UpdateContactByID(int ContactID,
string FistName, string MiddleName, string LastName)
{
throw new System.NotImplementedException();
}
/// <summary>
740
The Complete Reference To Professional SOA with Visual Studio 2005
/// <summary>
/// Select a contact by ID
/// </summary>
[System.Web.Services.WebMethod(),
System.Web.Services.Protocols.SoapDocumentMethod
(Binding = "WebService1")]
public DataSet SelectContactByID(int ContactID)
{
throw new System.NotImplementedException();
}
}
}
Listing 17-5. Demonstrates the newly generated code in Visual Basic .NET
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
Namespace WebserviceContactManagement
<System.Web.Services.WebServiceBinding(Name:="WebService1", _
ConformsTo:=System.Web.Services.WsiProfiles.BasicProfile1_1, _
EmitConformanceClaims:=True)> _
<System.Web.Services.Protocols.SoapDocumentService()> _
Public Class WebService1
''' <summary>
''' Add a contact
''' </summary>
<System.Web.Services.WebMethod()> _
<System.Web.Services.Protocols.SoapDocumentMethod _
(Binding:="WebService1")> _
Public Sub AddContact(ByVal FirstName As String, _
ByVal MiddleName As String, ByVal LastName As String)
End Sub
''' <summary>
''' Update a contact detail by ID
''' </summary>
741
The Complete Reference To Professional SOA with Visual Studio 2005
<System.Web.Services.WebMethod()> _
<System.Web.Services.Protocols.SoapDocumentMethod _
(Binding:="WebService1")> _
Public Sub UpdateContactByID(ByVal ContactID As Integer, _
ByVal FirstName As String, ByVal MiddleName As String, _
ByVal LastName As String)
End Sub
''' <summary>
''' Remove a contact detail by ID
''' </summary>
<System.Web.Services.WebMethod()> _
<System.Web.Services.Protocols.SoapDocumentMethod _
(Binding:="WebService1")> _
Public Sub RemoveContactByID(ByVal ContactID As Integer)
End Sub
''' <summary>
''' Select a contact by ID
''' </summary>
<System.Web.Services.WebMethod()> _
<System.Web.Services.Protocols.SoapDocumentMethod _
(Binding:="WebService1")> _
Public Function SelectContactByID(ByVal ContactID As Integer) _
As System.Data.DataSet
End Function
End Class
End Namespace
Now we will be implementing a new WebMethod called FindContactByFirstName see listing 17-6 and
listing 17-7.
/// <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();
}
<System.Web.Services.WebMethod(), _
System.Web.Services.Protocols.SoapDocumentMethod(Binding="WebService1")> _
742
The Complete Reference To Professional SOA with Visual Studio 2005
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.
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.
743
The Complete Reference To Professional SOA with Visual Studio 2005
We will complete the rest of the implementation of the Web service by using the code in the listing 17-8 and
listing 17-9.
Listing 17-8. The full implementation of the Web service code using Visual C#.
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
namespace WebserviceContactManagement
{
[System.Web.Services.WebServiceBinding(Name = "WebService1",
ConformsTo = System.Web.Services.WsiProfiles.BasicProfile1_1,
EmitConformanceClaims = true),
System.Web.Services.Protocols.SoapDocumentService()]
public class WebService1 : System.Web.Services.WebService
{
SqlConnection sqlcon = new SqlConnection
(ConfigurationManager.AppSettings["ConnectionString"]
.ToString());
/// <summary>
/// Add a contact
/// </summary>
[System.Web.Services.WebMethod(),
System.Web.Services.Protocols.SoapDocumentMethod
(Binding = "WebService1")]
public void AddContact(string FirstName,
string MiddleName, string LastName)
{
sqlcon.Open();
SqlTransaction transaction =
this.sqlcon.BeginTransaction("ContactTran");
sqlcmdEmployee.ExecuteNonQuery();
transaction.Commit();
sqlcon.Close();
744
The Complete Reference To Professional SOA with Visual Studio 2005
/// <summary>
/// Update a contact detail by ID
/// </summary>
[System.Web.Services.WebMethod(),
System.Web.Services.Protocols.SoapDocumentMethod
(Binding = "WebService1")]
public void UpdateContactByID(int ContactID, string FirstName,
string MiddleName, string LastName)
{
sqlcon.Open();
SqlTransaction transaction =
this.sqlcon.BeginTransaction("ContactTran");
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");
745
The Complete Reference To Professional SOA with Visual Studio 2005
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);
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);
return ds;
}
746
The Complete Reference To Professional SOA with Visual Studio 2005
}
}
Listing 17-9. The full implementation of the Web service code using Visual Basic .NET
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.Data
Imports System.Data.SqlClient
Namespace WebserviceContactManagement
<System.Web.Services.WebServiceBinding(Name:="WebService1", _
ConformsTo:=System.Web.Services.WsiProfiles.BasicProfile1_1, _
EmitConformanceClaims:=True)> _
<System.Web.Services.Protocols.SoapDocumentService()> _
Public Class WebService1
Private sqlcon As SqlConnection = New SqlConnection _
(ConfigurationManager.AppSettings("ConnectionString").ToString())
''' <summary>
''' Add a contact
''' </summary>
<System.Web.Services.WebMethod()> _
<System.Web.Services.Protocols.SoapDocumentMethod _
(Binding:="WebService1")> _
Public Sub AddContact(ByVal FirstName As String, _
ByVal MiddleName As String, ByVal LastName As String)
sqlcon.Open()
Dim transaction As SqlTransaction = _
Me.sqlcon.BeginTransaction("ContactTran")
Dim sqlcmdEmployee As SqlCommand = _
New SqlCommand("insert into Person.Contact (FirstName," & _
" MiddleName, LastName) Values (@FirstName, @MiddleName, " & _
" @LastName)", sqlcon)
sqlcmdEmployee.Transaction = transaction
sqlcmdEmployee.Parameters.Add("@FirstName", SqlDbType.VarChar, _
50).Value = FirstName
sqlcmdEmployee.Parameters.Add("@MiddleName", SqlDbType.VarChar, _
50).Value = MiddleName
sqlcmdEmployee.Parameters.Add("@LastName", SqlDbType.VarChar, _
50).Value = LastName
sqlcmdEmployee.ExecuteNonQuery()
transaction.Commit()
sqlcon.Close()
End Sub
''' <summary>
''' Update a contact detail by ID
747
The Complete Reference To Professional SOA with Visual Studio 2005
''' </summary>
<System.Web.Services.WebMethod()> _
<System.Web.Services.Protocols.SoapDocumentMethod _
(Binding:="WebService1")> _
Public Sub UpdateContactByID(ByVal ContactID As Integer, _
ByVal FirstName As String, ByVal MiddleName As String, _
ByVal LastName As String)
sqlcon.Open()
Dim transaction As SqlTransaction = _
Me.sqlcon.BeginTransaction("ContactTran")
Dim sqlcmdEmployee As SqlCommand = New SqlCommand _
("update Person.Contact set FirstName = @FirstName, " & _
" MiddleName = @MiddleName, LastName = @LastName " & _
" where Person.Contact.ContactID = @ContactID;", sqlcon)
sqlcmdEmployee.Transaction = transaction
sqlcmdEmployee.Parameters.Add("@ContactID", SqlDbType.Int) _
.Value = ContactID
sqlcmdEmployee.Parameters.Add("@FirstName", _
SqlDbType.VarChar, 50).Value = FirstName
sqlcmdEmployee.Parameters.Add("@MiddleName", _
SqlDbType.VarChar, 50).Value = MiddleName
sqlcmdEmployee.Parameters.Add("@LastName", _
SqlDbType.VarChar, 50).Value = LastName
sqlcmdEmployee.ExecuteNonQuery()
transaction.Commit()
sqlcon.Close()
End Sub
''' <summary>
''' Remove a contact detail by ID
''' </summary>
<System.Web.Services.WebMethod()> _
<System.Web.Services.Protocols.SoapDocumentMethod _
(Binding:="WebService1")> _
Public Sub RemoveContactByID(ByVal ContactID As Integer)
sqlcon.Open()
Dim transaction As SqlTransaction = _
Me.sqlcon.BeginTransaction("ContactTran")
Dim sqlcmdEmployee As SqlCommand = _
New SqlCommand("delete from Person.Contact where " & _
" Person.Contact.ContactID = @ContactID;", sqlcon)
sqlcmdEmployee.Transaction = transaction
sqlcmdEmployee.Parameters.Add("@ContactID", SqlDbType.Int) _
.Value = ContactID
sqlcmdEmployee.ExecuteNonQuery()
transaction.Commit()
sqlcon.Close()
End Sub
''' <summary>
''' Select a contact by ID
''' </summary>
<System.Web.Services.WebMethod()> _
748
The Complete Reference To Professional SOA with Visual Studio 2005
<System.Web.Services.Protocols.SoapDocumentMethod _
(Binding:="WebService1")> _
Public Function SelectContactByID(ByVal ContactID As Integer) _
As System.Data.DataSet
Dim sql As String = String.Format("select ContactID, Title, " & _
" FirstName, MiddleName, LastName from Person.Contact where" & _
" ContactID = {0}", ContactID)
Dim sqlcmd As SqlCommand = New SqlCommand(sql, sqlcon)
Dim da As SqlDataAdapter = New SqlDataAdapter(sql, sqlcon)
Dim ds As DataSet = New DataSet
da.Fill(ds)
sqlcon.Close()
Return ds
End Function
''' <summary>
''' Find a contact by first name
''' </summary>
<System.Web.Services.WebMethod()> _
<System.Web.Services.Protocols.SoapDocumentMethod(Binding:="WebService1")> _
Public Function FindContactByFirstName(ByVal FirstName As String) _
As System.Data.DataSet
Dim sql As String = String.Format("select ContactID, " & _
" Title, FirstName, MiddleName, LastName from Person.Contact " & _
" where FirstName like '%{0}%'", FirstName)
Dim sqlcmd As SqlCommand = New SqlCommand(sql, sqlcon)
Dim da As SqlDataAdapter = New SqlDataAdapter(sql, sqlcon)
Dim ds As DataSet = New DataSet
da.Fill(ds)
sqlcon.Close()
Return ds
End Function
End Class
End Namespace
To test the service press F5 to start the WebService1.asmx. Select the SelectContactByID link and enter a
ContactID to test the service see figure 17-25.
749
The Complete Reference To Professional SOA with Visual Studio 2005
750
The Complete Reference To Professional SOA with Visual Studio 2005
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.
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.
7. The completed diagram is shown in figure 17-28. It is also a good idea to illustrate the diagram by drag and
drop the comment tool from the Toolbox.
751
The Complete Reference To Professional SOA with Visual Studio 2005
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.
In the new Web Application project that Visual Studio has automatically created, a web reference to the
Web service project is automatically added to the project. To create a simple user interface (UI) for our contact
management system edit Default.aspx see figure 17-30.
752
The Complete Reference To Professional SOA with Visual Studio 2005
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.
753
The Complete Reference To Professional SOA with Visual Studio 2005
<table>
<th colspan="2" style="height: 21px">
Get Contact By ID</th>
<tr>
<td>
<asp:TextBox ID="TextbxGetContactContactID"
runat="server"></asp:TextBox><br />
</td>
<td>
<asp:Button ID="BtnContactByID" runat="server"
OnClick="BtnContactByID_Click"
Text="Get Contact By ID" />
</td>
</tr>
<td colspan="2">
<asp:GridView ID="GridView1" runat="server">
</asp:GridView>
</td>
</table>
<hr />
<table>
<th colspan="2">
Update Contact</th>
<tr>
<td>
Contact ID</td>
<td>
<asp:TextBox ID="txtbxContactID" runat="server">
</asp:TextBox></td>
</tr>
<tr>
<td>
First Name</td>
<td>
<asp:TextBox ID="txtbxFirstName" runat="server">
</asp:TextBox></td>
</tr>
<tr>
<td>
Middle Name</td>
<td>
<asp:TextBox ID="txtbxMiddleName" runat="server">
</asp:TextBox></td>
</tr>
<tr>
<td>
Last Name</td>
<td>
<asp:TextBox ID="txtbxLastName" runat="server">
</asp:TextBox></td>
</tr>
<tr>
<td colspan="2" style="height: 26px">
754
The Complete Reference To Professional SOA with Visual Studio 2005
755
The Complete Reference To Professional SOA with Visual Studio 2005
</tr>
</table>
<hr />
<table>
<th colspan="2">
Find User by First Name
</th>
<tr>
<td>
First Name
</td>
<td>
<asp:TextBox ID="TextbxFindUserFirstName"
runat="server"></asp:TextBox>
</td>
</tr>
<tr>
<td colspan="2">
<asp:Button ID="ButtonFindUser" runat="server"
OnClick="ButtonFindUser_Click" Text="Find User" />
</td>
<td>
</td>
</tr>
<tr>
<td colspan="2">
<asp:GridView ID="GridView2" runat="server">
</asp:GridView>
</td>
</tr>
</table>
</div>
</form>
</body>
</html>
The listing below demonstrates the code used to implement our calls to the web service from the Web
Application.
Listing 17-11. Demonstrates the implementation of the ASP.NET code in the code behind using Visual C#
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using WebApplicationWSConsumer.WebServiceProxies;
756
The Complete Reference To Professional SOA with Visual Studio 2005
{
protected void Page_Load(object sender, EventArgs e)
{
Listing 17-12. Demonstrates the implementation of the ASP.NET code in the code behind using Visual Basic .NET
Imports System.Data
Imports WebApplicationWSConsumer.WebServiceProxies
757
The Complete Reference To Professional SOA with Visual Studio 2005
The result of the Web application querying the Web service is shown in the figure 17-31.
758
The Complete Reference To Professional SOA with Visual Studio 2005
1. Select a Web service object then open the Settings and Constraints window.
2. Select the Operation System checkbox to enable it, see figure 17-32.
759
The Complete Reference To Professional SOA with Visual Studio 2005
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.
System Designer
The System Designer is another designer from the Distributed System Designer suite. This allows us to
configure the actual deployment of a particular configured use of the applications but does not refer to the
deployment of the application themselves. In other words it describes the deployment of the application systems
to reflect the deployable system. For example we are to deploy the system we had built from the previous section
from the Application Designer to two separate systems where each requires a different configuration of the same
basic functions. This might be a necessary case if our Database and Web service is to be hosted internally while
the Web application can be hosted externally on a separate machine all together.
Before we begin we should clarify the meaning of a System. A System described by the System designer
defines the architectural representation of a system and how it looks within the deployed environment.
In the following examples we will be creating a System Designer using the Application Designer diagram
we had designed earlier. In this example we will be creating two environments one for the intranet where our
Database and our Web service will sit for secured internal use. Whilst our Web based application will be hosted
externally for public access.
760
The Complete Reference To Professional SOA with Visual Studio 2005
1. Start the System Designer by right clicking on the Application Designer project within the solution explorer.
2. Select “New Distributed System Diagram…” see figure 17-34.
3. This will bring up a “Add New Item” dialog window. Select Distributed System diagrams from the Categories
section and select System Diagram from the Templates section. Rename the Diagram as Internal.sd see figure
17-35.
761
The Complete Reference To Professional SOA with Visual Studio 2005
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.
4. Select the objects from the System View on the left hand side see figure 17-36. Drag and drop the objects onto
the work space. The system box on screen represents an implementation of the deployed internal architecture.
5. Complete the implementation by dragging the WebserviceContactManagement (Web service) and the
AdventureWorks (Database) objects onto the workspace.
6. Use the connection tool from the Toolbox to connect the objects figure 17-37.
762
The Complete Reference To Professional SOA with Visual Studio 2005
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.
Now we have a complete internal representation of what we had implemented through Application designer.
To implement the external system where our Web application will be hosted follow the following steps:
8. In the solution explorer right-click Solution Items and select Add-> New Distributed System Diagram. In the
Add New Item dialog box, select System Diagram, Name it External.sd and click Add.
9. Now with a new empty work space drag and drop WebApplicationWSConsumer onto the designer.
763
The Complete Reference To Professional SOA with Visual Studio 2005
10. Right click on the Web service endpoint and select Add Proxy Endpoint.
11. Then use the connection tool from the Toolbox and select the Web content endpoint the select the edge of the
system boundry. We should have something that look like figure 17-39.
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.
16. This will create a blank work space for a new system diagram select Internal and External from the Systems
folder under System View and drag and drop them onto the designer.
17. Then use the connection tool to link the endpoints together see figure 17-40.
764
The Complete Reference To Professional SOA with Visual Studio 2005
Figure 17-40. Over all representation of internal and external System Diagram
With a nested multilevel system diagram we can easily traverse the different system diagram levels by right
clicking on a sub system diagram and selecting “Open in System Designer” see figure 17-41.
1. Right click on the Solution Items and select Add -> New Distributed System Diagram.
2. Select Distributed System Diagrams from the Categories and Logical Datacenter Diagram from the Templates.
Rename the diagram as Infrastructure.ldd figure 17-42.
765
The Complete Reference To Professional SOA with Visual Studio 2005
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.
766
The Complete Reference To Professional SOA with Visual Studio 2005
Tools Description
Pointer Used to drag and drop objects on the diagram
Connection Used to connect two similar endpoints
Comment Used to add a comment to the diagram
WebSiteEndpoint Manages Serverside communication with a logical IIS web server
HTTPClientEndpoint Manages clientside communication with a logical IIS web server
DatabaseClientEndpoint Manages client-side communication with a logical database server
GenericServerEndpoint Manages server-side communication with a logical generic server
GenericClientEndpoint Manages client-side communication with a logical generic server
ZoneEndpoint Manages communication on the boundry of a zone
WindowsClient Corresponds to a Windows client or server that hosts a Windows Application
IISWebServer Corresponds to a IIS Web server
DatabaseServer Corresponds to a database server
GenericServer Corresponds to a user-defined server or component
Zone Zones can be nested. A zone corresponds to a logical boudry that is separate
from other portions of a datacenter.
Generally an infrastructure is protected through firewalls. A zone as such defines the communication boundaries
within the Logical Datacenter Designer. They are used to define communication boundaries, physical boundaries
or security boundaries.
Let’s add the internal and external zones to the designer:
1. Select the zone tool from the Toolbox and drag and drop it onto the designer surface.
2. Rename the zone by clicking on the Zone1 text and renaming it to Internal
767
The Complete Reference To Professional SOA with Visual Studio 2005
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.
Communication between zones are managed through the zone endpoints. The communications can be
inbound, outbound, or bidirectional. The arrows used between the zones are used to represent the communication
flow.
To implement connection between the zones, we will start with implementing the connection for the internal
zone. Follow the following steps:
4. Select connection tool from the Toolbox. Select the inbound arrow (>) in dark grey in the diagram and then
select one of the WebSiteEndpoint for the IISWebServer object. This will create an incoming communication
flow.
5. To create an outgoing communication flow select the outbound arrow (>) in lighter colour and select the other
not yet assigned WebSiteEndpoint in the IISWebServer.
We also need to establish a database connection from the IIS web server to the DatabaseServer.
768
The Complete Reference To Professional SOA with Visual Studio 2005
6. Select the DatabaseClientEndpoint and drag and drop the tool onto the IISWebServer.
7. Then select the connection tool from the Toolbox and select the DatabaseClientEndpoint on the IISWebServer
and then select the DatabaseServer’s DatabaseServerEndpoint.
Having completed the above steps the diagram should look similar to the figure 17-46.
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.
769
The Complete Reference To Professional SOA with Visual Studio 2005
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.
770
The Complete Reference To Professional SOA with Visual Studio 2005
1. Right click on the Logical Server Settings. The context menu contains an option to Import Settings see figure
17-50.
771
The Complete Reference To Professional SOA with Visual Studio 2005
Select the option this will bring up a wizard see figure 17-51.
2. Select Next to continue the process. This will bring us to an IIS setting window. Incase the IIS web server is
not on the same machine as Visual Studio we can specify the necessary information in this window to connect
to the IIS Web server see figure 17-52.
772
The Complete Reference To Professional SOA with Visual Studio 2005
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.
4. We will be prompted to confirm the process before the imported setting overwrites the current settings
associated for the Endpoint figure 17-54.
773
The Complete Reference To Professional SOA with Visual Studio 2005
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.
774
The Complete Reference To Professional SOA with Visual Studio 2005
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.
775
The Complete Reference To Professional SOA with Visual Studio 2005
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.
776
The Complete Reference To Professional SOA with Visual Studio 2005
This will result in the generation of an Overall1.dd deployment diagram see figure 17-59 below.
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.
If this results in an incorrect binding between application and server then a cross will be shown figure 17-61.
777
The Complete Reference To Professional SOA with Visual Studio 2005
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.
6. Because the web service consumer is situated outside on the external infrastructure we will select
IISWebServerExternal (this is the name of the IIS Web server we had specified in Logical Datacenter
Designer). The application is now associated with the logical server see figure 17-64.
778
The Complete Reference To Professional SOA with Visual Studio 2005
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.
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.
Once the process is complete all the application under the System View window should be shown as
<Bound> see figure 17-67 below.
779
The Complete Reference To Professional SOA with Visual Studio 2005
Each of the logical servers in the deployment diagram also shows to have an application to have bound to
them figure 17-68.
780
The Complete Reference To Professional SOA with Visual Studio 2005
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.
To check what actually resulted in the warning. Simply double click on the warning to view the
inconsistency. In this case the two IIS Web application settings are inconsistent. We’re brought to the System
Diagram which resulted in the inconsistency. The object in question now has a red cross on the diagram, figure
17-71.
781
The Complete Reference To Professional SOA with Visual Studio 2005
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.
Going back to the deployment designer right click on the screen and select Validate Diagram again to make
sure that there is no more errors left, figure 17-73.
782
The Complete Reference To Professional SOA with Visual Studio 2005
1. Right click on the deployment diagram and select Generate Deployment Report figure 17-74.
The Overall1 HTML report is generated. It’s a large document which contains all system diagrams and
logical datacenter diagrams as well as all details on endpoints, resources and settings see figure 17-75.
783
The Complete Reference To Professional SOA with Visual Studio 2005
We can also view this document in the web browser simply right click on the document and select View in
Browser.
Summary
In this chapter we have learnt how to conceptually represent diagrams using the four designers from the
Distributed Systems Designer suite: Application Designer, System Designer, Logical Datacenter Designer and
Deployment Designer.
The application designer can be used to construct diagrams that represent the actual software system. We
can represent different types of application using the application designer then using the connection tool to
establish the links between the systems.
The system designer can be used to configure the deployment view of a particular use of the actual
application system. Using the diagrams that we have configured in the system designer we can also specify the
logical datacenter diagram. This diagram represents the infrastructure of a datacenter.
Once the diagrams had been completed we can consolidate all the information acquired into a deployment
diagram. This is where application systems are consolidated to specific logical servers. Through the deployment
diagram we can validate settings and constraints that we had specified at different levels of the diagram. From
the deployment diagram we can also generate a deployment report. The report contains all information about the
deployable components and infrastructures. It is a very detailed report that can be used as reference in future.
784
The Complete Reference To Professional SOA with Visual Studio 2005
Indexes
& C
& .........................................................................137
' .........................................................................137 CacheDuration .................................................... 419, 424
> .............................................................................137 Call Stack Window ..................................................... 362
< ..............................................................................137 CDATA ...................................................................... 138
" .........................................................................137 CDATA sections......................................................... 138
Choreography ............................................................... 53
Cities............................................................................. 24
. Class View.................................................................. 114
ClickOnce ........................................................... 399, 403
.NET Data Provider.....................................................189 Code Coverage............................................................ 378
.NET DataSets.............................................................185 ColumnChanged ......................................................... 218
.NET Deployment .......................................................389 ColumnChanging........................................................ 218
.NET Framework.........................................................100 Command.................................................................... 186
.NET Framework 2.0...................................................103 Common Language Runtime (CLR)........................... 102
.NET Framework class libraries ..................................101 Common Type System (CTS)..................................... 102
.NET Serialization.......................................................271 Confidentiality .............................................................. 61
.NET Web Service Message Flow...............................124 Connected System Strategy .......................................... 71
.NET XML Serialization .............................................271 Connection.................................................................. 186
ConnectionString ........................................................ 190
A Continuous Track.......................................................... 86
Controlled code sharing .............................................. 389
ADO.NET ...................................................................182 Controlling Serialization............................................. 282
ADO.NET DataSet Events ..........................................218 Coordination Services................................................... 55
ADO.NET DataSets ....................................................213 Copying DataSet Contents.......................................... 216
Advanced Web Service Programming ........................419 Creating Data Views ................................................... 217
Application Proxy .........................................................68 Creating XML Web Services...................................... 316
Architectural Tradeoff Matrix .......................................26 Cross Entities Query ..................................................... 52
Architectural Tradeoff Triangle ....................................26
Assembly Information.................................................390
Asymmetric (Public) Key Encryption ...........................65 D
Async Data Access......................................................183 Data Adapters ............................................................. 195
Asynchronous Web service .........................................432 Data Encoding ............................................................ 161
Attributes and Namespaces .........................................136 Data Providers ............................................................ 186
Authentication...............................................................60 DataAdapter................................................................ 187
Authorization ................................................................60 Data-Centric Services ................................................... 48
Autos Window ............................................................362 DataReader ......................................................... 186, 197
DataRow ..................................................................... 208
B DataSet........................................................................ 207
DataTable.................................................................... 207
Basic services ................................................................48 Datatype picker ........................................................... 155
BEA ..............................................................................45 Date............................................................................. 143
BeginExecuteReader ...................................................183 dateTime ..................................................................... 144
BeginExecuteXmlReader ............................................183 decimal........................................................................ 144
binding ........................................................................177 definitions ................................................................... 175
Boolean .......................................................................143 DeleteCommand ......................................................... 196
Breakpoint Window ....................................................363 Deploying Track ........................................................... 85
Budget Consideration....................................................81 Deployment ................................................................ 389
Buffering .....................................................................419 Description.................................................................. 419
BufferResponse ...........................................................419 Description for a Web Method.................................... 425
Business and IT.............................................................80 Developing Track ......................................................... 84
Business Benefits of SOA .............................................27 Distributed Event Driven Architecture and SOA........ See
Business Process Execution Language for Web Services EDA
(BPEL4WS).............................................................54 Document.................................................................... 114
Byte .............................................................................143 Document Object Model............................................. 240
785
The Complete Reference To Professional SOA with Visual Studio 2005
786
The Complete Reference To Professional SOA with Visual Studio 2005
787
The Complete Reference To Professional SOA with Visual Studio 2005
788