In the previous tutorial
I showed you how to build a very basic XML Web Service.
In this tutorial I will show you how to build a consumer for that XML Web Service.
con·sum·er [kon sumer] (plural con·sum·ers)
noun
organism that feeds on others: in an ecological community or food chain, an
organism that feeds on other organisms, or on material derived from them.
Encarta® World English Dictionary © & (P) 1999
Microsoft Corporation. All rights reserved. Developed for Microsoft by Bloomsbury
Publishing Plc.
An XML Web Service consumer is an application that invokes the methods of
an XML Web Service made available by a provider; the consumer feeds on the data
derived from the XML Web Service provider. A consumer application may be another
Web application, XML Web Service, Windows desktop application, or any other
type of application with access to the XML Web Service using HTTP.
Overview
The steps to consuming an XML Web Service are:
- Discover the XML Web Service.
- Create a proxy of the XML Web Service.
- Create an instance of the proxy and invoke a method.
1. Discover the XML Web Service
The discovery of an XML Web Service will typically be done on a business-to-business
level. In other words, two businesses will agree to exchange data using an XML
Web Service, and the provider of the service will inform the consumer about
where to find the service.
Another means of discovering an XML Web Service is by using the Universal
Description, Discovery, and Integration service (http://www.uddi.org).
This is a registry of XML Web Services provided by a number of different companies.
Currently two member companies of UDDI, Microsoft and IBM, provide search engines
for finding an XML Web Service that suits your need. Businesses that are exposing
XML Web Services can be listed in the UDDI registry, detailing information about
the company and the XML Web Services they are making available.
Figure 3.1 shows the UDDI registry entry for DotNetJunkies.com:
Figure 3.1

The result of the discovery process should be the URL to the Web Service Description
Language (WSDL) document. The WSDL is an XML document that describes the XML
Web Service. This is basically the contract that the consumer agrees to; the
WSDL states:
- The URL for invoking the XML Web Service.
- The Web methods available.
- The input arguments expected and their data types for each Web method.
- The output data type for each Web method.
2. Create a Proxy
Proxy, by definition, is the function, power, or capacity to substitute for
another. This definition is perfect for an XML Web Service proxy. The proxy
is a class on the local server that exposes the same interfaces as the XML Web
Service. The proxy acts as a local substitute for the XML Web Service, and handles
the calls to the XML Web Service to invoke the specified Web method.
Using the .NET Framework we can easily create a proxy class with a utility
named WSDL.exe. This utility is shipped with the .NET Framework SDK,
and is a command-line utility. The WSDL.exe utility is used to parse the XML
Web Service WSDL and automatically generate a proxy class for the service.
3. Create an Instance and Invoke
Once we have a proxy we can, anywhere in our application, create an instance
of the proxy class and invoke one of its methods.
When a method of the proxy is invoked, the proxy calls out to the XML Web
Service and invokes the same method. The XML Web Service returns the output
to the proxy instance in the consumer application. The proxy can then expose
the output data to the original caller as if the method were invoked locally.
This is seen in Figure 3.2.
Figure 3.2

Available Protocols
XML Web Service methods can be invoked using, as of this writing, one of three
protocols, HTTP GET, HTTP POST, or SOAP (over HTTP).
HTTP Get
Using HTTP GET any input arguments for the Web method are passed in the request
query string. This limits HTTP GET to only being available for Web methods that
take no inputs, or only inputs of primitive types that can be passed in the
query string, such as strings, integers, doubles, etc.
Using HTTP GET to invoke the SayHello() Web
method from the
last tutorial, the URL would be:
| http://localhost/myservice.asmx/SayHello?YourName=Doug+Seven
|
Using HTTP GET is shown in Figure 3.3.
Figure 3.3

HTTP Post
Using HTTP POST is similar to using HTTP GET, however, the Web method inputs
are passed in the HTTP Request body, not in the URL. The same restrictions on
data types as HTTP GET apply to HTTP POST.
SOAP
A SOAP message can be used to invoke the Web method. The inputs are passed
to the XML Web Service in the SOAP message body - the return data is passed
back to the consumer in the body of a SOAP message. The SOAP message can be
passed to the provider using either HTTP or HTTPS (as of .NET Framework Release
Candidate).
Listing 3.1 shows the SOAP message used to invoke the SayHello()
Web method.
Listing 3.1
POST myservice.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: 72
SOAPAction: "http://tempuri.org/SayHello"
<?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>
<SayHello xmlns="http://tempuri.org/">
<YourName>Doug Seven</YourName>
</SayHello>
</soap:Body>
</soap:Envelope> |
Listing 3.2 shows the SOAP message that is returned to the consumer from the
XML Web Service.
Listing 3.2
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 86
<?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>
<SayHelloResponse xmlns="http://tempuri.org/">
<SayHelloResult>Hello, Doug Seven</SayHelloResult>
</SayHelloResponse>
</soap:Body>
</soap:Envelope> |
Proxy Clients and WSDL.exe
To build a proxy client we can use the WSDL.exe utility - of course we could
also code the proxy client ourselves, but why do that when a utility can do
it for us. WSDL.exe is a command-line utility that we can invoke and it will
generate a proxy client class based on the WSDL document of the XML Web Service
we are creating a proxy for.
Note: Visual Studio .NET uses the WSDL.exe utility to create proxy clients
as well, but this is abstracted under the "Add Web Reference" Project
menu option. We will build a consumer application using Visual Studio .NET
in an upcoming tutorial.
The command to build a proxy class for the MyService XML Web Service from
Chapter 2 would look like this:
| wsdl.exe /out:MyServiceProxy.cs http://localhost/MyService.asmx?WSDL |
This command will execute the WSDL.exe utility and create a file named MyServiceProxy.cs
in the same directory that this command was executed from. The MyServiceProxy.cs
file contains the proxy class for the MyService XML Web Service at http://localhost/MyService.asmx;
it was built using the WSDL document for this XML Web Service as specified using
the ?WSDL query string modifier.
WSDL.exe
Lets break down the WSDL.exe utility. The syntax for executing a WSDL.exe
command is (the italic words are replace by proper values):
wsdl.exe /language:language /protocol:protocol
/namespace:Namespace /out:filename
/username:username /password:password /domain:domain
/appsettingurlkey:keyname
<url or path> |
Note: The WSL.exe command cannot include line breaks. It must be one continuous
line.
Not all of the arguments are required
in fact the only required argument
is the URL or path to the WSDL document. Table 3.1 defines some of the WSDL.exe
options (execute wsdl.exe /? To see a list of
all of the WSDL.exe options).
Table 3.1
| Option (short form) |
Description |
| URL or Path |
A URL or path to the WSDL, XSD schema or .discomap document. |
| /language: (/l:) |
Specifies the language to use when generating the proxy class.
The default is CS (C#). Other options are
VB (Visual Basic .NET), JS
(JScript .NET) or a fully-qualified name for a class implementing System.CodeDom.Compiler.CodeDomProvider. |
| /namespace: (/n:) |
Specifies the namespace the proxy class should be created
in. The default is the global namespace. |
| /out: (/o:) |
Specifies the name of the file that will be created. The
default name is derived from the XML Web Service name. |
| /protocol: |
Specifies the protocol the proxy will use when invoking the
XML Web Service. The default is SOAP - other
options are HttpGet and HttpPost. |
/username: (/u:)
/password: (/p:)
/domain: (/d:) |
Specifies the credentials to use when connecting to a server
that requires authentication. |
| /appsettingurlkey:
(/urlkey:) |
Specifies the name of a configuration file <appsettings>
key. This key specifies the URL to use when invoking methods on the XML
Web Service. The URL in the key/value will be used if it is available, otherwise
the URL that was used to make the proxy will be used. |
The Proxy
We can create a proxy client using the following command (in one continuous
line):
| wsdl.exe /l:cs /out:MyServiceProxy.cs /n:MyClient http://www.dotnetjunkies.com/services/MyService.asmx?WSDL |
The resulting file looks like Listing 3.3.
Listing 3.3
//--------------------------------------------------------------------
// <autogenerated>
// This code was generated by a tool.
// Runtime Version: 1.0.2914.16
//
// Changes to this file may cause incorrect behavior and will be
// lost if the code is regenerated.
// </autogenerated>
//--------------------------------------------------------------------
//
// This source code was auto-generated by wsdl, Version=1.0.2914.16.
//
namespace MyClient {
using System.Diagnostics;
using System.Xml.Serialization;
using System;
using System.Web.Services.Protocols;
using System.Web.Services;
[System.Web.Services.WebServiceBindingAttribute(
Name="MyServiceSoap",
Namespace="http://tempuri.org/")]
public class MyService :
System.Web.Services.Protocols.SoapHttpClientProtocol
{
[System.Diagnostics.DebuggerStepThroughAttribute()]
public MyService()
{
this.Url
=
"http://www.dotnetjunkies.com/services/MyService.asmx";
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Web.Services.Protocols.SoapDocumentMethodAttribute(
"http://tempuri.org/SayHello",
Use=System.Web.Services.Description.SoapBindingUse.Literal,
ParameterStyle=
System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public string SayHello(string
YourName) {
object[]
results = this.Invoke("SayHello",
new object[] {
YourName});
return
((string)(results[0]));
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
public System.IAsyncResult
BeginSayHello(string YourName,
System.AsyncCallback callback, object
asyncState) {
return
this.BeginInvoke("SayHello", new
object[] {
YourName}, callback, asyncState);
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
public string EndSayHello(System.IAsyncResult
asyncResult) {
object[]
results = this.EndInvoke(asyncResult);
return
((string)(results[0]));
}
}
} |
We can see in the code for the proxy that it simply creates an interface for
the XML Web Service. Each method invokes the specified method. The proxy class
itself derives from HttpGetClientProtocol, HttpPostClientProtocol,
or SoapHttpClientProtocol depending on the /protocol:
option we specified when creating the proxy.
The proxy class has two additional methods for each Web method, the BeginMethod()
and EndMethod() methods (BeginSayHello()
and EndSayHello() in the example). These methods
are used to invoke the Web methods asynchronously - without waiting for a
response...sort of the fire-and-forget way to invoke a Web method. We will
get into asynchronous Web method invoking later in this tutorial series.
When we compile this class into an assembly and put the DLL in the \bin
directory of a Web application, we can create instances of this class and invoke
its methods. To compile the proxy class we can use a command-line compiler,
CSC.exe (VBC.exe for Visual Basic .NET applications), as follows:
| csc.exe /t:library /out:MyClient.dll *.cs /r:System.dll,System.Web.dll |
This will create a DLL named MyClient.dll, with one class, MyService.
With this DLL in the \bin directory, we can
create a proxy client - in this case, a Web Form.
The Client
The client for the MyService XML Web Service is relatively simple - it is
a TextBox, a Button and a Label, as seen in Figure 3.4.
Figure 3.4

The Web Form has a TextBox where the Web site visitor can input their name.
This value will be used as the input for the SayHello()
Web method. When the "Invoke MyService" Button is clicked, it triggers
a postback. In the postback handler we create an instance of the MyClient.MyService
proxy class, and invoke the SayHello() method.
The string returned is set as the Label control's Text property.
The code for the Web Form (default.aspx) is shown in Listing 3.4.
Listing 3.4
<%@ Page Inherits="MyClient.CDefault"
%>
<html>
<body>
<form runat="server">
<b>Enter Your Name:</b>
<asp:TextBox runat="server" id="Name"
/>
<asp:Button runat="server" Text="Invoke MyService"
/>
<hr noshade size="1">
<asp:Label runat="server" id="Result"
/>
</form>
</html> |
The code for the CDefault code behind class
is shown in Listing 3.5.
Listing 3.5
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace MyClient
{
public class CDefault : Page
{
protected TextBox Name;
protected Label Result;
public void Page_Load
( Object sender, EventArgs e )
{
if ( Page.IsPostBack
)
{
MyClient.MyService _myService
= new MyClient.MyService();
Result.Text = _myService.SayHello
( Name.Text.Trim() );
}
}
}
} |
In the Page_Load() event handler we evaluate
for a postback. If the current request is a postback we create an instance of
MyClient.MyService and invoke SayHello(),
passing in the user submitted value as the YourName argument. The returned data
is set to the Result Label control's Text property.
Summary
While this chapter dealt with consuming a very simple XML Web Service, the
principals are the same as if we had been consuming a complex XML Web Service.
We used a proxy class to expose the XML Web Service's interface in a local object.
With that local object we were able to invoke a method of the XML Web Service
and catch the return data as if the method were executed locally.
In the next tutorial I will show you how to build a consumer application using
Visual Studio .NET.