335
7.3 Web-Service Descriptions
Web Service Description Language WSDL is a specification for encoding the definition of a web service as an XML document. This is analogous to providing type information for traditional COM
software components. A web-service description identifies the name and URL of a web service, the web methods that are available from that service, the methods parameter names and types, and the
methods return types.
ASP.NET automatically generates the WSDL documents for web services that it hosts. This document can be viewed by clicking the Service Description link in the service test page refer back to
Figur e 7- 1
. A portion of this document for the HelloWebService service is shown in Figur e 7- 4
.
Figure 7-4. Viewing a WSDL document
As you can see in Figur e 7- 4
, the WSDL document is intended more for tools that can read its contents than it is for humans. As shown in the next section, WSDL documents are used by client
tools to generate code that knows how to talk to the given web service.
7.4 Consuming a Web Service
On the .NET platform, consuming a web service is as easy as creating one. This section contains the steps for creating a web-service client that can call the web service shown in
Ex am ple 7- 1 .
7.4.1 Consuming a Web Service in Visual Studio .NET
To use a web service from a Visual Studio .NET project, right-click on the References node in the Solution Explorer window, and select Add Web Reference. This causes the Add Web Reference
dialog box to appear.
336
In the Address field of the Add Web Reference dialog box, enter the URI of a web-service description document, and click the Add Reference button. When adding references to web services hosted by
ASP.NET, the web-service description document is obtained by appending ?wsdl
to the path of the service itself. For example: http:www.company.commyWebService.asmx?wsdl or
http:localhostWebServicesHello-WebService.asmx?wsdl. Visual Studio .NET reads the web-service description document and builds a corresponding proxy
class that knows how to access the described web service. The proxy class is local and exposes the same functionality as the web service. To call the web service from within the project, instantiate the
proxy class and call its methods. For example, the following code instantiates the HelloWebService class and calls its SayHello method in response to a button click:
Assumes that this code is part of a form having a button named btnOk_Click, a text box named txtName, and a text box named txtResult.
Private Sub btnOk_Click _ ByVal sender As System.Object, _
ByVal e As System.EventArgs _ Handles btnOk.Click
If txtName.Text Then Dim sName As String = txtName.Text
Dim oWS As New localhost.HelloWebService Dim sMsg As String = oWS.SayHellosName
oWS.Dispose txtResult.Text = sMsg
End If End Sub
Note that the web-server machine name is used as the namespace for the web-service class. Thus, for a class called HelloWebService exposed by the same machine as the caller, the namespace is
localhost, and the fully qualified name of the class is localhost.HelloWebService. For machine names containing dots, the order of the parts is reversed. Thus, if the HelloWebService service were exposed
by a machine named webservices.somecompany.com, the HelloWebService class namespace would be com.somecompany.webservices, and the fully qualified class name of the class would be
com.somecompany.webservices.HelloWebService.
Internally, the proxy class packages up method calls into SOAP wrappers and forwards them to the web service. This process is transparent to the client of the proxy class.
7.4.2 Consuming a Web Service in Notepad
To use a web service from a project that is not developed within the Visual Studio .NET IDE, use the command-line wsdl.exe tool to create a proxy class that wraps the web service. For example:
wsdl http:localhostWebServicesHelloWebService.asmx?wsdl language:vb The wsdl.exe tool takes as an argument the URL of a web-service description document. As explained
in the preceding discussion of Visual Studio .NET, when consuming services hosted by ASP.NET, the web-service description document is obtained by appending
?wsdl to the path of the web service, as
was done here. The output of the wsdl.exe tool is a source-code file containing the definition of a proxy class that
knows how to access the described web service. The wsdl.exe tools language
switch controls whether the source is written in Visual Basic .NET or C. The name of the class in the generated
source code is equal to the name of the service, as given in the web-service description document. Ex am ple 7- 2
shows the output of the wsdl.exe tool when run on the HelloWebService service from
337
Ex am ple 7- 1 . Note that several of the lines have been reformatted to make them fit in this book.
Other than that, the code is unchanged.
Example 7-2. Sample output of the wsdl.exe tool
-------------------------------------------------------------------------- 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 --------------------------------------------------------------------------
Option Strict Off Option Explicit On
Imports System Imports System.Diagnostics
Imports System.Web.Services Imports System.Web.Services.Protocols
Imports System.Xml.Serialization This source code was auto-generated by wsdl, Version=1.0.2914.16.
System.Web.Services.WebServiceBindingAttribute _ Name:=HelloWebServiceSoap, _
[Namespace]:=http:yourcompany.com _ Public Class HelloWebService
Inherits System.Web.Services.Protocols.SoapHttpClientProtocol System.Diagnostics.DebuggerStepThroughAttribute _
Public Sub New MyBase.New
Me.Url = http:localhostWebServicesHelloWebService.asmx End Sub
System.Diagnostics.DebuggerStepThroughAttribute , _ System.Web.Services.Protocols.SoapDocumentMethodAttribute _
http:yourcompany.comSayHello, _ RequestNamespace:=http:yourcompany.com, _
ResponseNamespace:=http:yourcompany.com, _ Use:=System.Web.Services.Description.SoapBindingUse.Literal, _
ParameterStyle:= _ System.Web.Services.Protocols.SoapParameterStyle.Wrapped _
Public Function SayHelloByVal Name As String As String Dim results As Object = Me.InvokeSayHello, New Object
{Name} Return CTyperesults0,String
End Function System.Diagnostics.DebuggerStepThroughAttribute _
Public Function BeginSayHello _ ByVal Name As String, _
ByVal callback As System.AsyncCallback, _ ByVal asyncState As Object _
As System.IAsyncResult Return Me.BeginInvokeSayHello, New Object {Name}, callback, _
338
asyncState End Function
System.Diagnostics.DebuggerStepThroughAttribute _ Public Function EndSayHello _
ByVal asyncResult As System.IAsyncResult _ As String
Dim results As Object = Me.EndInvokeasyncResult Return CTyperesults0,String
End Function End Class
After creating the proxy class, write client code to make use of it. Using the proxy class is just like using any other .NET class. The proxy class hides method calls being forwarded over the Web.
Ex am ple 7- 3 shows code that uses the proxy class from
Ex am ple 7- 2 .
Example 7-3. Client code for use with Ex a m ple 7 - 2
Imports System Public Module SomeApplication
Public Sub Main Dim myService As New HelloWebService
Console.WriteLinemyService.SayHelloAnnemarie End Sub
End Module
Note that the client code simply instantiates the proxy class and calls its SayHello method. Lastly, compile the proxy class and the client code together. Heres an example of compiling from the
command line note that this should be entered as a single command and is shown on two lines here only for printing in this book:
vbc SomeApplication.vb HelloWebService.vb reference:System.Web.Services.dll,System.Xml.dll,System.dll
The three assemblies referenced in this command are required by the proxy class.
7.4.3 Synchronous Versus Asynchronous Calls
Web-method calls are synchronous by default. That is, the caller waits while the call is sent over the network and while the result is calculated and sent back. When dealing with the Internet, this can be a
lengthy process a fraction of a second to several seconds. There are times when it would be useful for the client to go off and perform some other processing while waiting for the web method to
complete. Fortunately, the autogenerated proxy class created by either Visual Studio .NET or wsdl.exe provides a way to do this.
Ex am ple 7- 4 shows client code that calls the SayHello web
method asynchronously.
Example 7-4. Calling SayHello asynchronously
Private myService As New HelloWebService Private Sub btnInvoke_Click _
ByVal sender As System.Object, _ ByVal e As System.EventArgs _
Handles btnInvoke.Click Assumes that there is a text box named txtName.
myService.BeginSayHellotxtName.Text, AddressOf MySayHelloCallback, _ Nothing
339
End Sub Private Sub MySayHelloCallbackByVal ar As IAsyncResult
Assumes that there is a text box named txtResult. txtResult.Text = myService.EndSayHelloar
End Sub
For each web method, the web-service proxy class exposes two additional methods, named Begin
WebMethodName and End
WebMethodName , where
WebMethodName is the name of the web
method to be invoked. The purpose of the Begin WebMethodName
method is to invoke the web method and immediately return. This allows client code to continue executing while the web service
processes the request. When the response arrives from the web service, it is held until the client calls the End
WebMethodName method. If the client calls the End
WebMethodName method before the web
methods response arrives, the client blocks until the response arrives. If the client calls the End
WebMethodName method after the response arrives, the method immediately returns with the
response value. The parameters of the Begin
WebMethodName method are exactly the same as the parameters of the
web-method call itself, plus two additional parameters: callback
If the client would like to be notified when the web methods response has arrived, it can pass a delegate reference in this parameter. The type of this parameter is AsyncCallback, which is
defined in the System namespace as:
Public Delegate Sub AsyncCallbackByVal ar As IAsyncResult To pass a callback function to the Begin
WebMethodName method, write a method having the
appropriate signature and then use the AddressOf
operator to create a delegate from that method, as shown in
Ex am ple 7- 4 .
If the client does not want to be notified when the web methods response has arrived, it can pass
Nothing in this parameter.
asyncState If the client would like to provide some arbitrary additional information to the callback function,
it can do so by assigning a value to the asyncState
parameter. This parameter is of type Object, so any value can be passed. The value passed in this parameter is passed on to the
callback function when the web-method call returns. If no additional information needs to be passed to the callback function, pass
Nothing in this parameter.
The Begin WebMethodName
method has no return value. When the callback function is called, it receives a reference to an object that implements IAsyncResult
defined in the System namespace. The AsyncState property of this object holds the value passed in the
asyncState parameter of the Begin
Web -
MethodName method.
The first parameter of the End WebMethodName
method is the IAsyncResult reference obtained in the callback function. Alternatively, the client can pass
Nothing in this parameter if not using a callback
function. The End WebMethodName
method may have additional parameters, depending on whether the corresponding web method has any
ByRef parameters. If there are any such parameters, they
appear here in the signature of the End WebMethodName
method. In addition, the return value of the End
WebMethodName method is the return value of the web method.
340
7.5 Web-Service Discovery
Up to this point, we have assumed that the client of a web service knows where to find that web services WSDL document. This may not always be the case. For example, consider a client
application that runs on a portable device. Its purpose is to make a reservation on the users behalf at the nearest hotel meeting the users preset price and service guidelines. Before the client application
can communicate with a hotels reservation web service, the client must have a way to discover that the service is even there. This is the purpose of web-service directories.
Web-service directories provide a way for clients to find web services that perform a certain task or a certain kind of task. They are like the yellow pages in a telephone directory, in which businesses are
listed according to the product or service they provide. Standards are just now being developed for web-service directories. One strong contender is called Universal Description, Discovery, and
Integration UDDI. Information about this standard and the implementations that currently exist can be found at
ht t p: w w w .uddi.or g .
You may also have heard of DISCO files. DISCO is short for discovery. DISCO is a Microsoft- exclusive specification for encoding the addresses of multiple WSDL documents into a single XML
document. DISCO doesnt have directory capabilities and so is falling into disuse as UDDI grows.
7.6 Limitations of Web Services