Before you can create a client application to interact with the calculator web service, you must first create a proxy class. Once again, you can do this by hand, but that would be hard work. The folks at Microsoft have provided a tool called wsdl that generates the source code for the proxy based on the information in the WSDL file.
To create the proxy, enter wsdl at the Visual Studio .NET command-line prompt followed by the path to the WSDL contract and the /l:vb flag:
wsdl <url> /l:vb
For example, you might enter:
wsdl http://localhost/VBWSCalc/Service1.asmx?wsdl /l:vb
The flag /l:vb tells wsdl to produce a Visual Basic .NET file.
The result is the creation of a Visual Basic .NET client file named Service1.vb, an excerpt of which appears in Example 16-3. You must add the namespace WSCalc because you'll need it when you build your client (the tool does not insert it for you).
'------------------------------------------------------------------------- ' <autogenerated> ' This code was generated by a tool. ' Runtime Version: 1.0.3705.288 ' ' 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.ComponentModel 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.3705.288. ' '<remarks/> Namespace VBWSCalc <System.Diagnostics.DebuggerStepThroughAttribute( ), _ System.ComponentModel.DesignerCategoryAttribute("code"), _ System.Web.Services.WebServiceBindingAttribute(Name:="Service1Soap", [Namespace]: ="http://tempuri.org/")> _ Public Class Service1 Inherits System.Web.Services.Protocols.SoapHttpClientProtocol '<remarks/> Public Sub New( ) MyBase.New( ) Me.Url = "http://localhost/ProgrammingVBNET/VBWSCalc/Service1.asmx" End Sub '<remarks/> <System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/ Add", RequestNamespace:="http://tempuri.org/", ResponseNamespace:="http://tempuri.org/", Use:=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle:=System.Web. Services.Protocols.SoapParameterStyle.Wrapped)> _ Public Function Add(ByVal x As Double, ByVal y As Double) As Double Dim results( ) As Object = Me.Invoke("Add", New Object( ) {x, y}) Return CType(results(0), Double) End Function '<remarks/> Public Function BeginAdd(ByVal x As Double, ByVal y As Double, ByVal callback As System.AsyncCallback, ByVal asyncState As Object) As System.IAsyncResult Return Me.BeginInvoke("Add", New Object( ) {x, y}, callback, asyncState) End Function '<remarks/> Public Function EndAdd(ByVal asyncResult As System.IAsyncResult) As Double Dim results( ) As Object = Me.EndInvoke(asyncResult) Return CType(results(0), Double) End Function '<remarks/> <System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/ Subtract", RequestNamespace:="http://tempuri.org/", ResponseNamespace:="http://tempuri. org/", Use:=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle: =System.Web.Services.Protocols.SoapParameterStyle.Wrapped)> _ Public Function Subtract(ByVal x As Double, ByVal y As Double) As Double Dim results( ) As Object = Me.Invoke("Subtract", New Object( ) {x, y}) Return CType(results(0), Double) End Function '<remarks/> Public Function BeginSubtract(ByVal x As Double, ByVal y As Double, ByVal callback As System.AsyncCallback, ByVal asyncState As Object) As System.IAsyncResult Return Me.BeginInvoke("Subtract", New Object( ) {x, y}, callback, asyncState) End Function '<remarks/> Public Function EndSubtract(ByVal asyncResult As System.IAsyncResult) As Double Dim results( ) As Object = Me.EndInvoke(asyncResult) Return CType(results(0), Double) End Function '<remarks/> <System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/ Mult", RequestNamespace:="http://tempuri.org/", ResponseNamespace:="http://tempuri.org/", Use:=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle:=System.Web. Services.Protocols.SoapParameterStyle.Wrapped)> _ Public Function Mult(ByVal x As Double, ByVal y As Double) As Double Dim results( ) As Object = Me.Invoke("Mult", New Object( ) {x, y}) Return CType(results(0), Double) End Function '<remarks/> Public Function BeginMult(ByVal x As Double, ByVal y As Double, ByVal callback As System.AsyncCallback, ByVal asyncState As Object) As System.IAsyncResult Return Me.BeginInvoke("Mult", New Object( ) {x, y}, callback, asyncState) End Function '<remarks/> Public Function EndMult(ByVal asyncResult As System.IAsyncResult) As Double Dim results( ) As Object = Me.EndInvoke(asyncResult) Return CType(results(0), Double) End Function '<remarks/> <System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/ Div", RequestNamespace:="http://tempuri.org/", ResponseNamespace:="http://tempuri.org/", Use:=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle:=System.Web. Services.Protocols.SoapParameterStyle.Wrapped)> _ Public Function Div(ByVal x As Double, ByVal y As Double) As Double Dim results( ) As Object = Me.Invoke("Div", New Object( ) {x, y}) Return CType(results(0), Double) End Function '<remarks/> Public Function BeginDiv(ByVal x As Double, ByVal y As Double, ByVal callback As System.AsyncCallback, ByVal asyncState As Object) As System.IAsyncResult Return Me.BeginInvoke("Div", New Object( ) {x, y}, callback, asyncState) End Function '<remarks/> Public Function EndDiv(ByVal asyncResult As System.IAsyncResult) As Double Dim results( ) As Object = Me.EndInvoke(asyncResult) Return CType(results(0), Double) End Function '<remarks/> <System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/ Pow", RequestNamespace:="http://tempuri.org/", ResponseNamespace:="http://tempuri.org/", Use:=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle:=System.Web. Services.Protocols.SoapParameterStyle.Wrapped)> _ Public Function Pow(ByVal x As Double, ByVal y As Double) As Double Dim results( ) As Object = Me.Invoke("Pow", New Object( ) {x, y}) Return CType(results(0), Double) End Function '<remarks/> Public Function BeginPow(ByVal x As Double, ByVal y As Double, ByVal callback As System.AsyncCallback, ByVal asyncState As Object) As System.IAsyncResult Return Me.BeginInvoke("Pow", New Object( ) {x, y}, callback, asyncState) End Function '<remarks/> Public Function EndPow(ByVal asyncResult As System.IAsyncResult) As Double Dim results( ) As Object = Me.EndInvoke(asyncResult) Return CType(results(0), Double) End Function End Class End Namespace
This complex code is produced by the wsdl tool to build the proxy DLL you will need when you build your client. The file uses attributes extensively (see Chapter 8), but with your working knowledge of Visual Basic .NET you can extrapolate at least how some of it works.
The file starts by declaring the Service1 class that derives from the class SoapHttpClientProtocol, which occurs in the namespace called System.Web.Services.Protocols:
Public Class Service1 Inherits System.Web.Services.Protocols.SoapHttpClientProtocol
The constructor sets the URL property inherited from SoapHttpClientProtocol to the URL of the .asmx page you created earlier.
The Add( ) method is declared with a host of attributes that provide the SOAP plumbing to make the remote invocation work.
The WSDL application has also provided asynchronous support for your methods. For example, for the Add( ) method, it also created BeginAdd( ) and EndAdd( ). This allows you to interact with a web service without performance penalties.
To build the proxy, place the code generated by WSDL into a Visual Basic .NET Library project in Visual Studio .NET and then build the project to generate a DLL. You may need to add a reference to System.Web.Services. In any case, be sure to write down the location of that DLL, as you will need it when you build the client application.
To test the web service, create a very simple Visual Basic .NET console application. The only trick is that in your client code you need to add a reference to the proxy DLL just created. Once that is done, you can instantiate the web service, just like any locally available object:
Dim theWebSvc As _ New ClassLibrary1.VBWSCalc.Service1( )
You can then invoke the Pow( ) method as if it were a method on a locally available object:
Dim i As Integer Dim j As Integer For i = 2 To 10 For j = 1 To 10 Console.WriteLine("{0} to the power of {1} = {2}", _ i, j, theWebSvc.Pow(i, j)) Next Next
This simple loop creates a table of the powers of the numbers 2 through 9, displaying for each the powers 1 through 9. The complete source code and an excerpt of the output is shown in Example 16-4.
Class Tester
Public Sub Run( )
Dim theWebSvc As _
New ClassLibrary1.VBWSCalc.Service1( )
Dim i As Integer
Dim j As Integer
For i = 2 To 10
For j = 1 To 10
Console.WriteLine("{0} to the power of {1} = {2}", _
i, j, theWebSvc.Pow(i, j))
Next
Next
End Sub
Public Shared Sub Main( )
Dim t As New Tester( )
t.Run( )
End Sub
End Class
Output (excerpt):
2 to the power of 1 = 2
2 to the power of 2 = 4
2 to the power of 3 = 8
2 to the power of 4 = 16
2 to the power of 5 = 32
2 to the power of 6 = 64
2 to the power of 7 = 128
2 to the power of 8 = 256
2 to the power of 9 = 512
2 to the power of 10 = 1024
3 to the power of 1 = 3
3 to the power of 2 = 9
3 to the power of 3 = 27
3 to the power of 4 = 81
3 to the power of 5 = 243
3 to the power of 6 = 729
3 to the power of 7 = 2187
3 to the power of 8 = 6561
3 to the power of 9 = 19683
3 to the power of 10 = 59049
Your calculator service is now more available than you might have imagined (depending on your security settings) through the web protocols of HTTP-Get, HTTP-Post, or SOAP. Your client uses the SOAP protocol, but you could certainly create a client that would use HTTP-Get:
http://localhost/VBWSCalc/Service1.asmx/Add?x=23&y=22
In fact, if you put that URL into your browser, the browser will respond with the following answer:
<?xml version="1.0" encoding="utf-8"?> <double xmlns="http://www.libertyAssociates.com/webServices/">45</double>
The key advantage SOAP has over HTTP-Get and HTTP-Post is that SOAP can support a rich set of datatypes, including all of the Visual Basic .NET intrinsic types (Integer, Double, etc.), as well as enumerations, classes, structures, and ADO.NET DataSets, and arrays of any of these types.
Also, while HTTP-Get and HTTP-Post protocols are restricted to name/value pairs of primitive types and enums, SOAP's rich XML grammar offers a more robust alternative for data exchange.
Top |