Web-Service Descriptions Web-Service Discovery

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