As discussed in Chapter 1, the advanced Web services specifications championed by IBM, Microsoft, and other industry leaders provide a platform for extending the functionalities of Web services without sacrificing interoperability. Because standardization and industry adoption promotes interoperability, developers on disparate platforms will need only to implement Web services against these widely adopted Web service specifications. For .NET Web services, this still leaves the difficulty of having to either serialize and deserialize the necessary SOAP headers manually or else directly leverage the .NET Framework to create custom filters to handle these headers.
Fortunately, to ease your pain when developing Web services, Microsoft has developed a product offering that extends the .NET Framework to support these evolving Web service interoperability standards. Known collectively as Web Services Enhancements (WSE), this offering is made up of a set of classes that implement these new protocols as well as a set of filters that intercept incoming and outgoing SOAP messages and interpret or generate the SOAP headers to support the requested functionalities. The specifications supported by version 2.0 of WSE include
WS-Security Leverages XML Encryption and XML Signature to specify how to build security features into a SOAP message. Describes how to bind security tokens to a SOAP message as well as how to encrypt and digitally sign part or all of the message. WSE also supports X.509 and Kerberos-specific extensions to WS-Security. I discuss support for WS-Security and related specifications in Chapter 5.
WS-SecureConversation Extends WS-Security to enable secure communication between parties in a Web service interaction by defining a mechanism for initiating and sharing security contexts and deriving shared session keys. I discuss support for this specification in Chapter 8.
WS-Trust Extends WS-Security to define a mechanism to enable parties in a Web service interaction to request security tokens to verify trust relationships. I discuss support for this specification in Chapter 8.
WS-Policy Defines a mechanism that enables both parties in a Web service interaction to publish and enforce a set of messaging requirements that must be met for a SOAP message to be accepted. Policy can also be used to automatically enforce requirements for outbound messages. In addition to WS-Policy, WSE also supports related specifications, such as WS-SecurityPolicy and WS-PolicyAssertion, which extends WS-Policy with respect to security requirements. I discuss support for these policy specifications in Chapter 6.
WS-Addressing Enables the description of complex message paths in SOAP message headers. This message addressing enables intermediate message handling, message forwarding, and multiple message transports in a single message path . I cover WSE support for this specification in Chapter 4.
WS-Referral Specifies a WSE-specific method for forwarding Web service requests to other Web services while preserving the appropriate header information. I describe WSE support for this specification in Chapter 4.
WS-Attachments and DIME Describes how to use Direct Internet Message Encapsulation (DIME) messages in a SOAP messaging context. DIME is a transport protocol being developed by the Internet Engineering Task Force (IETF) and is designed specifically for encapsulating and transporting SOAP messages with binary files, arbitrary XML, and even other SOAP messages. I discuss support for these specifications in Chapter 3.
As this book goes to press, the WSE team is deciding whether or not to remove support for WS-Routing and most of WS-Referral that was included in WSE 1.0 from the final release of the 2.0 version, so don t be surprised to find changes in these messaging functionalities in the final version of the product.
The engine that drives Web Services Enhancements is a separate WSE runtime that s integrated with the .NET Framework and can be hosted by ASP.NET. 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 handle SOAP messages transported over both HTTP and TCP. The process for receiving and handling a SOAP message using ASP.NET and WSE is represented in Figure 2-5.
In this process, each filter reads its associated SOAP header, if available, and generates an object that s added to the SoapContext class for the message that represents the information in that particular header. This is repeated for each WSE filter before the message (with these headers removed) is passed back to ASP.NET for normal handling. After all of the message headers have been read, the Policy Input Filter can check for message compliance against the Web service s published policies.
Conversely, WSE is employed in a similar fashion when an outgoing response method is created, as shown in Figure 2-6.
The filters and the WSE runtime are implemented by the Microsoft.Web.Services assembly (Microsoft.Web.Services.dll), and WSE provides a low-level API that lets you programmatically determine the behavior of these input 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 supported 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.
Since WSE leverages both the Microsoft .NET Framework and Microsoft Internet Information Services (IIS), WSE can be run on almost any machine running a recent version of the Windows operating system. The exact system requirements for WSE version 2.0 are as follows :
Microsoft Windows 2000 Server with Service Pack 3 or later
Microsoft Windows XP Professional with Service Pack 1 or later
Microsoft Windows Server 2003
Microsoft Internet Information Services (IIS) 5.0 or later
One of the following:
Microsoft Visual Studio .NET 2003
Microsoft Windows .NET Framework version 1.1
Note that not all features are supported on all platforms. For example, Kerberos security tokens are supported only on Windows XP and Windows Server 2003. For a complete list of requirements, see the WSE documentation.
Since the .NET assembly that implements WSE is contained in a single library file, installation is simple. During setup, the WSE 2.0 installation program copies the Microsoft.Web.Services.dll file into C:\Program Files\Microsoft WSE\v2.0 and adds this assembly to the global assembly cache (GAC).
To be able to use WSE with an ASP.NET-hosted Web service, you need to also add some information to the Web.Config configuration file for the Web service. If you have ever modified these XML-based ASP.NET configuration files, you know that it is fairly easy to make a mistake that can break your application. Fortunately, Microsoft also provides the WSE Settings tool that integrates with Visual Studio .NET and can be used to automatically make the needed modifications to these configuration files. If you re not using Visual Studio .NET, you ll still need to manually configure WSE settings. However, WSE documentation tells you how to do this, and I won t cover it in this book.
The WSE Settings tool is a component of the WSE install program, and it requires that Visual Studio .NET already be installed. With the WSE Settings tool installed, it is simple to enable any Web service or client that consumes such a Web service to use the WSE runtime. To configure WSE settings for a Visual Studio .NET application, simply right-click on the desired project in the Solution Explorer window in Visual Studio .NET and click WSE Settings. This displays the WSE Settings tool, as shown in Figure 2-7.
With this tool, enabling WSE for an ASP.NET Web service is as simple as selecting both check boxes on the General tab. To enable WSE for a application consuming a WSE-enabled Web service, you need only select the Enable This Project For Web Services Enhancements check box. The rest of the tabs in this tool allow you to configure various components of WSE that correspond to the specifications that the Web service needs to use. I will discuss each of these in the corresponding chapters later in this book. WSE optionally installs a set of stand-alone configuration tools as well as a tool that simplifies the process of finding and using X.509 certificates with WSE.
WSE includes a full API that allows you to programmatically control the behavior of the runtime and each of the message filters. The WSE runtime can be configured to use TCP/IP as a transport for SOAP instead of HTTP, and it also supports asynchronous messaging. However, since most Web services implement synchronous SOAP messaging over HTTP, I won t be discussing these other WSE programming options in this book.
When using SOAP over HTTP provided by ASP.NET, the SoapContext class provides the core control of the behavior of WSE, meaning which specific interoperability headers are supported for a given SOAP message. In the WSE programming model, when a SOAP message is received, the runtime generates a RequestSoapContext object for the incoming request. The SoapContext for the message can then be accessed by the RequestSoapContext.Current property, which enumerates the information contained in the WSE-specific header elements of the message. For example, if an incoming message has a WS-Addressing prescribed From element, the sender information for the message can be accessed using the SoapContext.From property, as follows:
// Get the SoapContext of the incoming message
SoapContext myContext = RequestSoapContext.Current;
// Get the Addressing.From object from SoapContext
From myFrom = myContext.From;
// Get the Addressing.Address object for the incoming message sender
Address mySender = myFrom.Address;
Uri senderUri = mySender.Value;
// Do something with this URI
In a similar fashion, headers can be added to outgoing SOAP response messages by setting properties of the SoapContext class defined for a ResponseSoapContext object. The following code tells the DIME attachments filter to send a DIME message containing both a binary document file and a SOAP response message:
// Get the SoapContext of the outgoing message
SoapContext myResponse = ResponseSoapContext.Current;
// Call the AddAttach method to build a new DimeAttachmentCollection object
// containing the requested documents
DimeAttachmentCollection myAttachments = AddAttach(documentID);
// Add the attachments to the outgoing SOAP response in the DIME message
myResponse.Attachments = myAttachments;
In this example, the WSE runtime creates a DIME message in which the first DIME record contains the SOAP response message and the second record contains the document file attachment. A WSE-enabled client application can then use the SoapContext object to access the attachment independently of the SOAP response message.
When you re programming a client application that consumes WSE-based Web services, the proxy class that represents the Web service in the .NET Web services client programming model must inherit from the Microsoft.Web.Services.WebServicesClientProtocol class. The WSE Settings Tool should automatically generate a new proxy class with Wse appended to the name . For example, WebServiceProxyClass would be changed to WebServiceProxyClassWse with the correct inheritance added. You can also manually add this inheritance to the proxy class by modifying the Reference.cs file that is automatically generated by the Add Web Reference tool. After adding the Web reference, open Reference.cs and add the WebServiceClientProtocol inheritance as in the following example:
public class WebServiceProxyClass :
Once the proxy has been modified, the SoapContext can be set on outgoing request messages using the RequestSoapContext property of the proxy class. The following example demonstrates how to use SoapContext to add a username security token to a request message:
// Create an instance of a ServiceProxy Web service proxy
ServiceProxy myProxy = new ServiceProxy();
// Gets the SoapContext associated with the SOAP request
SoapContext myContext = myProxy.RequestSoapContext;
// Create a new username token to send without a password
UsernameToken myToken = new UsernameToken(userName,
// Add the token to the SOAP header