The Book of VB .NET: .NET Insight for VB Developers
Author: Matthew MacDonald
Built on the Microsoft .NET framework, Visual Basic .NET allows programmers to create everything from full-featured Internet applications to sophisticated Windows programs with the latest eye-catching interfaces. This comprehensive guide is organized into a series of lightning tours and real-world examples, covering web development, XML, databases, and user interface design. Each chapter begins with an overview of changes from Visual Basic 6. The book also includes extra code examples, references to additional online material, and helpful tips about planning, design, and architecture.
Read Chapter 13: Web Services from this book.
ISBN: 1886411824 Buy this book now!
Excerpted with permission from The Book of VB .NET, by Matthew MacDonald, No Starch Press, Copyright 2002.
|
WEB SERVICES
Web Services are a new introduction to Visual Basic .NET, and
are being touted by Microsoft as a new and revolutionary way to
program with the Internet. All this excitement raises the inevitable
question: Are Web Services really the future of programming, and a
sound career investment, or are they doomed to become the "next great
thing" that wasn't?
A little background on the subject should help us find the answers. First of
all, the concept of Web Services hasn't been created by Microsoft. It represents
an exciting new area that several companies are clamoring to gain control of,
including such heavyweights as Sun Microsystems and IBM. However, Microsoft
has been planning their implementation of Web Services for quite a while, and
it shows. Microsoft has made Web Services incredibly easy to program in .NET,
while retaining the ability to let Web Services work seamlessly across different
browsers and operating systems. A great deal of thought has gone into Web
Services, and there is good reason to believe that they are destined to become
another powerful tool in the advanced programmer's arsenal, along with
ActiveX, COM, and other revolutionary technologies from the past.
This article starts by asking "What is a Web Service?" and takes you
through the process of creating, deploying, and interacting with one. Luckily,
.NET makes Web Services so quick and convenient that you can be creating simple
examples in no time at all. However, it may take many more months of
experimentation before you start to realize all of the possible ways Web Services
can be used. The end of this article includes some helpful web links to live
examples of Web Services.
New in .NET
Web Services are making their debut in Visual Studio .NET-they haven't existed
in any form before. Some developers may have created custom Web Service
implementations using Microsoft's SOAP toolkit, but only for highly specialized
applications.
In fact, Web Services are so new and so promising that they are sometimes
identified synonymously with the entire .NET platform. Of course, now that you
have read Chapter 1 of The Book of VB .NET, you know what .NET is really about. How
large a part Web Services will play in Microsoft's strategy of integrating languages,
embracing open standards, and programming the Internet remains to
be seen.
The Vision of the Interactive Web
What is a Web Service anyway? Clearly, many sites on the Internet provide useful
"services." A common example is a shipping company, which allows you to
look up the location and delivery date of packages using a tracking number. Is
this a Web Service?
The delivery date lookup meets one of the criteria of a Web Service-it's a
discrete unit of functionality that serves a single purpose: returning information
about your package. But in order to get this information, you have to navigate
to the correct HTML page, select an option from a menu, and then enter
your tracking number. In other words, you have to use an Internet application-
represented by the shipping company's website-in order to get the information
you need.
Web Services: COM for the Internet?
One of the great developments in Windows programming was COM (some parts
of which are also called ActiveX), a technology that allows code components to
be easily shared among applications. When COM was introduced, it added flexibility.
Instead of using monolithic applications, custom utilities could be created
that reused a subset of all the capabilities provided in COM components.
In this respect, Web Services are like COM for the Internet. With a Web
Service, you can take a unit of logic in a web application, and allow it to be
seamlessly accessed and used by other Windows or Internet applications, in a
variety of different ways. A Web Service is like a business object: It accepts information
and returns information. Your program uses Web Services, without
needing to involve the user, and takes care of providing the appropriate user
interface. This is particularly important in the world of the Internet, where a
user might be accessing information from a full-featured Internet Explorer
browser, or from a stripped down interface on a cell phone or other wireless
device. In this case, the Web Service used would be the same, but a different
application would take care of the display. Like a COM object, a Web Service
doesn't need to be tied to any specific interface.
In one important way, however, Web Services are not like COM technology.
COM relies on a proprietary Windows standard, which means that it's useless
for Macintosh computers, UNIX systems, or any other non-Microsoft platform.
Web Services, however, are built on open standards such as SOAP, XML, and
WSDL, which will be described in this article. This means that any application
can interact with them (though none so easily as a .NET application), and that
they can transmit data painlessly over HTTP. Because data is exchanged in a text
XML format, there's also no problem sending a Web Service request or receiving
its response, even when the Web Service is behind a corporate firewall.
Web Services Today
You are probably already making use of "first generation" Web Services. These
are examples of Internet procedures that are integrated into desktop programs,
but require company-specific and site-specific standards. For example, you may
use a personal finance desktop application that can automatically retrieve stock
portfolio information from the Internet. This type of application retrieves information
from the Internet, and doesn't bother you with the details of the
process. However, it relies on having information provided in a specific way,
which was been planned and set up in advance, according to the particular
application. It does not use an independent, widely accepted standard, as Web
Services will with .NET. As a consequence, other applications can't easily extend
or work with its functions and features. They must be recreated for every application
that require them.
Now imagine a world with thousands of Web Service components, where a
desktop application has access to all kind of features that require up-to-theminute
information from the Web. In all likelihood, everyone will have some
type of "always on" broadband Internet access, and you won't even be aware
when your application is interacting with the Web. Programmers will no longer
have to try and constantly redesign off-the-cuff solutions that schedule Internet
downloads or parse HTML files manually, looking for specific information.
Of course, that's the future. Today, Web Services will allow you to further
modularize Internet applications, and provide components that can be consumed
and reused by any other application. Web Services can also use authentication
and login procedures, allowing you to support various subscription models.
In other words, you can sell units of application functionality to other
developers, just like programmers sell ActiveX controls today.
Are Web Services Objects?
Web Services are not objects, at least not in the traditional sense of the word.
The main distinction is that Web Services don't maintain state, unless you specifically
take extra steps to store information in a database or ASP.NET's Session
state collection. In fact, a Web Service that maintains state is rarely a good idea
because it means the web server must allocate a portion of its precious memory
for each client, which can quickly impose a noticeable performance penalty as
the number of clients increases.
Web Services also don't support object-oriented basics like overloaded functions
and property procedures. Constructors work, but the Web Service class is
destroyed and reconstructed with each request, even if the client maintains a reference.
This makes sure that Web Services perform well, but it also means that
they can't be used like a local business object. It's best to think of a Web Service
as a utility class made up of shared members. You can call a remote function to
get a piece of information, but you shouldn't expect to keep a Web Service
around and store information in it.
Creating Your First Web Service
Creating a Web Service is easier than you might think. All you have to do is
create a class that incorporates some useful functions. This class should inherit
from the System.Web.Services.WebService class (for maximum convenience),
and all the methods that are going to be made available over the Web must be
marked with attributes.
To start creating this application, begin a new project and choose ASP.NET
Web Service. A series of support files will be created, as with an ASP.NET application.
The actual Web Service is contained in the .asmx file (named
Service1.asmx by default). The design view of the .asmx file isn't used, but the
code view will start off with a couple of sample lines needed to define the Web
Service class.
NOTE A Web Service, like the ASP.NET applications we saw in the previous chapter of The Book of VB .NET, must be
hosted on a web ser ver in a virtual directory. The Web Service examples for this article
are contained in the NoStarchWeb virtual directory. Web Service clients, on the other
hand, can be located in any directory.
Now consider a very rudimentary example of a Web Service class for providing
information about a package tracked with a shipping company:
Imports System.Web.Services
Public Class PostalWebService
Inherits System.Web.Services.WebService
<WebMethod> Public Function GetDeliveryDate(ByVal TrackID As String) As Date
Dim PackageInfo As Package
PackageInfo = GetPackageRecordFromDB(TrackID)
Return PackageInfo.Date
End Function
Private Function GetPackageRecordFromDB(ByVal TrackID As String) As Package
' Some database access code here.
End Function
End Class
Public Class Package
Public PackageID As String
Public DeliveryDate As Date
End Class
The Package class encapsulates information about a package. Notice that it
doesn't inherit from WebService class or use the attribute
because it isn't a Web Service. Instead, it is used internally in the PostalWebService
class, to pass information.
The PostalWebService class has two functions. The GetDeliveryDate function
is marked with a special attribute, , which indicates that it
will be provided in the public interface of the Web Service. No other functions
are available. GetPackageRecordFromDB is used internally by your code to get
information, but it is not made available to any clients.
Now, believe it or not, any application using this Web Service will have
access to the features and operations of the GetDeliveryDate function. All you
need is a class that inherits from the basic WebService class, and uses the attribute. Could it be any easier?
Touching Up Your Web Service
To improve your Web Service, you might want to add a description to the attribute. This description may be displayed for the client developing
the application that will use your Web Service, depending on the type of development
tool they are using.
<WEBMETHOD(DESCRIPTION:="USE THIS FUNCTION TO...")>
You should also specify a namespace for your Web Service. Ideally, your
namespace should be uniquely identified with you-your company name, for
example, or best of all, your web address. If you do not specify a namespace, the
default (http://tempuri.org/) will be used. Be aware that this is an XML namespace,
not a .NET namespace. An XML namespace looks like an URL, but it
doesn't need to correspond to a valid Internet location (although it often does).
XML namespaces are just used to distinguish portions of an XML document.
To specify a namespace, change the first line of your class declaration to use
the WebService attribute:
<WEBSERVICE(NAMESPACE:="HTTP://MYCOMPANY.COM/POST")> _
Public Class PostalWebService
Enhancing the PostalWebService class
You can also make a more useful Web Service that returns a custom object with
several pieces of information at once, as shown in the following example. Notice
that the Package information has been separated into two classes; we'll assume
here that you will not want to provide the entire database record to the client, in
case it includes sensitive information (such as a credit card number).
Public Class PostalWebService
Inherits System.Web.Services.WebService
<WEBMETHOD> Public Function GetPackageInfo(ByVal TrackID As String) _
As ClientPackageInfo
Dim PackageInfo As Package
PackageInfo = GetPackageRecordFromDB(TrackID)
Return PackageInfo.BasicInfo
End Function
Private Function GetPackageRecordFromDB(ByVal TrackID As String) As Package
' Some database access code here.
Dim PackageInfo As New Package()
' To perform a crude test, uncomment the following two lines.
' PackageInfo.BasicInfo.PackageID = TrackID
' PackageInfo.BasicInfo.DeliveryDate = Now
Return PackageInfo
End Function
End Class
Public Class Package
Public BasicInfo As New ClientPackageInfo
Public CreditCardNumber As String
End Class
Public Class ClientPackageInfo
Public PackageID As String
Public DeliveryDate As Date
End Class
Database and OOP mavens will realize that there are many different ways to
implement this type of scenario. (You may also wonder why the credit card is
stored with each package.) In a real world example, security concerns will shape
the whole construction of the database.
In any case, this example demonstrates that a .NET Web Service can pass
many types of information to the client, including DataSets, .NET objects, arrays,
and simple variables. Keep in mind, however, that if you were to pass an object
with a built-in method, the method would be lost. Only the data is preserved.
Testing Your Web Service
So now that you have created a Web Service, how can you use it? Or maybe
you're still wondering exactly what is provided with the Web Service we've created.
Fortunately, Internet Explorer includes a handy feature that allows you to
preview and perform a limited test on any Web Service.
Your Web Service in Action
To try out this useful feature, run your Web Service. Remember, Web Services
are designed to be used from inside other applications, not executed directly.
However, when you choose to run a Web Service in Visual Studio .NET, your
browser will display the test page shown in Figure 13-1.
This window lists all the available Web Service methods. (In this case, only
one, GetPackageInfo, is available.) The Service Descriptions link will display the
WSDL description of your Web Service. (WSDL is described in the next section
of this article.)
Figure 13-1: The Internet Explorer test page
Click on the GetPackageInfo link, and the following test page will appear:
Ignore the puzzling XML code at the bottom of the page for now, and concentrate
on the first portion of the page, which provides a prefabricated way for
you to test your application. Try it by entering a package ID and clicking on
Invoke. If you've entered the preceding example, and uncommented the hardcoded
package values, you will receive the result shown in Figure 13- 3.
Figure 13-2: Testing a Web Service method
Figure 13- 3: AWeb Service response
At this point you'll probably start to wonder if your Web Service has worked
at all. However, on close examination, it turns out that the appropriate information
is present; it's just been marked up in a special XML format. What you have
received is a translated version of the ClientPackageInfo class. The class is
marked with a beginning and an ending tag, and inside are the members,
including a PackageID and a DeliveryDate field.
You don't need to understand the format of this information if you are programming
in Visual Basic .NET. As you'll discover later in this article, .NET
provides special utilities that abstract away this layer of XML. These features
allow you to call a Web Service and retrieve its data as thought it were a local
function inside your application. However, understanding this format can give
you some additional insight into what's really going on with Web Services.
The Open Standards Plumbing
Much of the excitement over Web Services results from the fact that they are
built on open standards. It's this foundation that makes them more flexible and
extensible than previous attempts at allowing distributed component-based programming,
including such existing standards as DCOM (Microsoft's own Distributed
COM), and RMI (Java's Remote Method Invocation).
XML and WSDL
Web Services use remote function calls written in XML language. XML language
is ideally suited to Web Services because it is text-based, which means that
unlike binary data, for instance, it can easily flow over normal HTTP channels
on the Internet without getting stopped by corporate firewalls. XML is also
excellent because it is self-describing, and it provides a way to identify (or "mark
up") information.
XML, however, is only the starting point. XML is just a tool for describing
data, much as SQL is a tool for accessing databases. Both are generic, and both
can be used in countless different ways. What is needed is an agreed-upon standard
for encoding information in XML, guaranteeing that other clients will be
able to decode the information by following a uniform set of rules.
The standard way of describing your .NET Web Services is WSDL, an XMLbased
language that has been accepted by Microsoft, IBM, and a host of other
vendors. If you want to find out all the low-level details of WSDL, you can read
up on it at http://msdn.microsoft.com/xml/general/wsdl.asp. However, for
most developers, these details won't hold any more interest than the kinds of
technology that underlie many of the other aspects of the .NET platform. What
is more interesting is examining the WSDL information that Visual Basic .NET
generates automatically for your particular Web Service. To display this information,
click on the Service Description link on the Internet Explorer Web Service
test page. You'll see a lengthy-and perhaps intimidating-document that
describes the types and the functions used in your Web Service.
A portion of the WSDL document for the PostalWebService is shown in
Figure 13- 4
.
Figure 13- 4: Part of the WSDL document describing a Web Service
SOAP
WSDL describes your Web Service, but another standard is needed to communicate
with it. In fact, there are three different ways to communicate with a Web
Service. The first is HTTP GET, which Internet Explorer uses automatically
when you click on Invoke on your test page. The second is HTTP POST, which
is very similar to HTTP GET. Internet veterans will realize that a POST request
sends information in the body of an HTTP request instead of in the query
string. The final method is SOAP, which is what .NET will use transparently
when you create a client later in this article.
SOAP is another XML-based standard, and it predates the .NET platform.
Essentially, when you send information to and retrieve information from your
Web Service in a .NET application, your requests and responses are packaged in
the SOAP format. The SOAP format looks similar to the HTTP response we got
before, but it is not identical. The test web page shows the actual format for
SOAP and HTTP requests and responses when you click on a method.
Accessing a Web Service Directly
Now that you understand a little bit about the standards underlying Web Services,
you may realize that you don't really need to go through the Internet
Explorer test page, although it is very convenient.
To see the WSDL contract for a Web Service, just add ?WSDL after the filename
in your Internet browser. This works for any .NET Web Service, including
those that have been created by other developers. The Web Service WSDL contract
for the PostalWebService can be retrieved with this line (assuming it's in a
virtual directory called NoStarchWeb on the local computer):
http://localhost/NoStarchWeb/PostalWebService.asmx?WSDL
You can also interact with the Web Service through HTTP GET by typing
the parameter list into the URL. In fact, if you enter the value 221 for the Get-
PackageInfo function and click Invoke, this is what Internet Explorer links to:
http://localhost/NoStarchWeb/PostalWebService.asmx/GetPackageInfo?TrackID=221
In other words, Internet Explorer just passes the function name and the
TrackID parameter as part of an HTTP GET request. At this point, you might
start to realize that if communicating with Web Services is this straightforward,
it really is possible to access them on different operating systems and platforms.
When IIS receives a web request like the one shown above, it passes it to the
ASP.NET worker process, which then creates the Web Service. The Web Service
runs the appropriate function, returns the result as an XML page, and is
destroyed. The end result appears as a page in your Internet browser.
The next section looks at how .NET applications consume Web Services by
using SOAP calls, which allows you to retrieve the results of a Web Service in a
.NET program instead of a browser.
Consuming a Web Service
At this point, you've seen your Web Service in action, but you haven't usefully
incorporated it into another program. Clearly, if users had to rely on the Internet
Explorer test page, they would be better off with a full-featured Internet
application!
In this section you'll learn how to create a Web Service client in VB .NET.
Best of all, you'll learn how to get Visual Basic .NET to create all the infrastructure
code you need.
The Proxy Class
Web Service clients communicate with Web Services through a proxy class that
you can create automatically with the .NET framework. The proxy class translates
your actions into the appropriate SOAP calls, and then interacts with the
Web Service. The whole process is seamless, so you might not have even realized
it was happening if you hadn't seen the following diagram:
Figure 13-5: Web Service interaction
Adding a Web Reference
To create the proxy class, you need to add a web reference in Visual Basic .NET.
First, add a new Windows application project to the current solution by rightclicking
on the Solution Explorer and selecting Add • New Project. This project
should not be created in the virtual directory where the Web Service is located
because it will not be hosted on the web server.
Then, right- click on the new project and select Set As StartUpProject. Now,
right-click one more time, and choose Add Web Reference. The Add Web Reference
window will appear (Figure 13- 6).
Figure 13- 6: Adding a web reference
To add a web reference, you need to supply a discovery file. A discovery file
is the first step in the interaction process; it's where an application "discovers"
what Web Services are available, what methods they have, and what information
they require and return.
You may have noticed that Visual Basic .NET automatically added a .vsdisco
file to your Web Service project. This is the file you now need to select. Click
the Web References on Local Server link. On the right, a list will appear of the
discovery files residing on your current computer. If you have already created an
ASP.NET application, you may find more than one discovery file. Choose the
one that is in the appropriate directory.
Once you have made your selection, information will appear about the Web
Services specified by the discovery document you've chosen. You can click on
the View Contract button to see all the WSDL information again, or click on the
Add Reference button to link to this Web Service and generate the required
proxy class automatically.
Inspecting the Proxy Class
Visual Basic .NET hides the proxy class it creates from you, because you don't
really need to see it or modify it directly. However, it's always a good idea to
peek under the hood of an application and get a better understanding of what's
really happening along the way.
To see the proxy class, select Project • Show All Files from the menu. Then,
look for the folder under Web References with the .WSDL file. Double- click to
expand this entry, and you'll see the Visual Basic proxy file (typically called
Reference.vb), as shown in Figure 13-7.
Figure 13- 7: The hidden proxy class
This file includes all the methods from your WebService, in slightly modified
form. It also includes the ClientPackageInfo class that you need to use to
retrieve the information from the GetPackageInfo method. Interestingly, Visual
Basic .NET is intelligent enough to leave out the Package class, so the client will
have no idea that the Web Service uses this class internally and won't be able to
snoop out its internal details.
Take a quick look at the modified version of the GetPackageInfo function contained
in the proxy class. (The attributes that precede it are not included here.)
Public Function GetPackageInfo(ByVal TrackID As String) As ClientPackageInfo
Dim results() As Object = Me.Invoke("GetPackageInfo", New Object() {TrackID})
Return CType(results(0), ClientPackageInfo)
End Function
This function converts the TrackID input string into a generic object, and
retrieves the result as a generic object, which is then converted into the appropriate
ClientPackageInfo object. In between, it accesses the Web Service through the
appropriate SOAP request and waits for the response, although all this is taken
care of automatically in the Me.Invoke method, with the help of the .NET attributes
that provide additional information to the Common Language Runtime.
Another interesting aspect of the proxy class is the constructor, which sets
the URL. If you change the location of your Web Service, you can modify this
method, rather than regenerating the proxy class. Notice, however, that
localhost is specified, regardless of the name of your computer. Localhost is a
"loopback" alias that always points to the current computer.
Public Sub New()
MyBase.New
Me.Url = "http://localhost/WebService/PostalWebService.asmx"
End Sub
Using the Proxy Class
The proxy class is the key to using a Web Service. Essentially, you create an
instance of this class, and call the appropriate methods on it. You treat the
proxy class as though it were a local class that contained the same functions and
methods as the Web Service.
Add the following code to the Load event of your startup Windows Form:
Dim ServiceInstance As New localhost.PostalWebService()
Dim PackageInfo As New localhost.ClientPackageInfo()
PackageInfo = ServiceInstance.GetPackageInfo("221")
MessageBox.Show("Received the delivery date: " & PackageInfo.DeliveryDate)
Now run the application. If Visual Studio .NET loads up the Web Service
web page, you have to stop the project and set the Windows application as the
startup project, using the right-click menu in the Solution Explorer window.
If you have configured everything correctly, you'll see the window in
Figure 13- 8.
Figure 13- 8: The Web Service results
Once again, the technical details are pretty sophisticated, but the actual
implementation is hidden by the .NET framework. Calling a Web Service is as
easy as creating one, once you have set up the web reference.
Debugging a Web Service Project
When debugging a solution that includes a Web Service project and client, you
will find that any breakpoints or watches you set for the Web Service code are
ignored. That is because, by default, Visual Studio .NET only loads the debug
symbols for the startup project, which is the client.
To solve this problem, you need to configure Visual Studio .NET to load
both projects at once. Right- click on the solution item in the Solution Explorer,
and select Properties. Then, browse to the Common Properties • Startup
Project tab, and specify Multiple Startup Projects, so that both your client and
the Web Service will be built when you click the start button (Figure 13- 9).
Figure 13-9: Starting multiple projects
You still need to make one more change. By default, Visual Studio .NET
starts the Web Service project by displaying the Internet Explorer test page. In
this case, however, you don't want any action to be taken other than loading the
debug symbols so that the Web Service code is available for debugging.
Right- click on the Web Service project, and select properties. In the Configuration
Properties • Debugging tab, select "Wait for an external process to connect"
as your start action (Figure 13-10). You can now use the full complement
of debugging tools with your Web Service and client code.
Figure 13-10: Loading the Web Service debug symbols
Asynchronous Web Service Calls
You may have noticed that the proxy class actually contains more than just the
GetPackageInfo function. It also includes BeginGetPackageInfo and EndGet-
PackageInfo procedures. These routines allow you to retrieve a Web Service
result asynchronously. For example, your code can submit a request with Begin-
GetPackageInfo, perform some additional tasks, and then retrieve the result
with EndGetPackageInfo. This allows your program to remain responsive, even
when waiting for a response over a slow Internet connection.
Dim ServiceInstance As New localhost.PostalWebService()
Dim PackageInfo As New localhost.ClientPackageInfo()
' Create a special handle that will allow us to retrieve the result.
Dim ResultHandle As IAsyncResult
' Submit the request.
ResultHandle = ServiceInstance.BeginGetPackageInfo("221", Nothing, Nothing)
' (Perform other time-consuming tasks.)
' Retrieve the final result, using the ResultHandle.
PackageInfo = ServiceInstance.EndGetPackageInfo(ResultHandle)
MessageBox.Show("Received the delivery date: " & PackageInfo.DeliveryDate)
In this example, ResultHandle is a special IAsyncResult object that tracks
the current request. You can have multiple asynchronous web requests submitted
at the same, as long as you keep track of them with different IAsyncResult
objects.
When the EndGetPackageInfo method is called, the request becomes synchronous.
That means that if the response has not yet been received from the
Web Service, your code will wait until it is received (or until the request times
out, according to the proxy class Timeout property).
Alternatively, you can call BeginGetPackageInfo with the address of a subroutine
in your program. When the Web Service result is received, this routine
will be called automatically. This technique is ideal if you are requesting some
information that is not critical, and you want to allow your application to continue
its normal behavior. By using a callback, you can respond immediately
when the information arrives, but your application doesn't need to sit idle waiting
for it.
Here's an example where a button click submits an asynchronous request
with a callback:
Private ServiceInstance As New localhost.PostalWebService()
Private Sub cmdAsyncCallback_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles cmdAsyncCallback.Click
' Create a special handle that will allow us to retrieve the result.
Dim ResultHandle As IAsyncResult
' Submit the request, with a callback.
ServiceInstance.BeginGetPackageInfo("221", AddressOf ResultReceived, Nothing)
End Sub
When the result is received, the ResultReceived subroutine will be called
immediately, and a MessageBox will appear alerting the user. (A more common
action might be to use the information to update a portion of the user interface.)
The PostalClient included with the online samples demonstrates these different
ways of retrieving information from a Web Service asynchronously.
Private Sub ResultReceived(ByVal ar As IAsyncResult)
' Retrieve the final result, using the ar event arguments..
Dim PackageInfo As New localhost.ClientPackageInfo()
PackageInfo = ServiceInstance.EndGetPackageInfo(ar)
MessageBox.Show("Received the delivery date: " & PackageInfo.DeliveryDate)
End Sub
TIP You could also use the threading techniques described in Chapter 10 of The Book of VB .NET. For example, you
could create a procedure that calls a series of web methods on a separate thread and then
raises an event to notify your program.
Web Service Discovery
One aspect of this process that I've glossed over a bit is the discovery file. The
discovery file represents Microsoft's goals for easily sharing Web Services and
making them available to the appropriate clients. You don't need to worry about
these sharing issues if you are creating a Web Service exclusively for use in your
company website, or with a few select clients. However, if you are trying to
develop and market a Web Service that provides powerful features that you want
to provide as a subscription service, discovery matters quite a lot.
Discovery is the process that allows a client to find the WSDL information
that describes your Web Service. Your server may have one discovery document
that points to multiple Web Services, or it may have several different discovery
files in various virtual directories. Alternatively, you might not use a discovery
file at all.
A discovery document is yet another type of XML file. All it contains is a list
of web links (URLs) to the WSDL document of various Web Services. Here is a
sample discovery file for our PostalWebService:
<?xml version="1.0" encoding="utf-8" ?>
<disco:discovery xmlns:disco="http://schemas.xmlsoap.org/disco"
xmlns:wsdl="http://schemas.xmlsoap.org/disco/wsdl">
<wsdl:contractRef ref="http://fariamat/NoStarchWeb/PostalWebService.asmx?WSDL"
</disco:discovery>
By default, discovery files use dynamic discovery, and look a little different.
With dynamic discovery, every subdirectory in the current directory will be
scanned for Web Services. Here is a sample dynamic discovery file:
<?xml version="1.0" encoding="utf-8" ?>
<dynamicDiscovery xmlns="urn:schemas-dynamicdiscovery:disco.2000-03-17">
<exclude path="_vti_cnf" />
<exclude path="_vti_pvt" />
<exclude path="_vti_log" />
<exclude path="_vti_script" />
<exclude path="_vti_txt" />
<exclude path="Web References" />
</dynamicDiscovery>
The exclude path attributes tell the discovery process not to look in those
folders. This can be used to save time (for example, by restricting directories
that contain only images), or to restrict a Web Service from appearing in a discovery
process (although it will still be accessible unless you have specifically
written authentication or security code).
TIP How can you add a web reference if you don't have a discovery file? You can manually
type the Web Service location into the address bar of the Add Reference window. You
don't even need to worry about supplying the ?WSDL at the end to locate the WSDL
document, because Visual Studio .NET is smart enough to add that for you
automatically.
What Comes Next?
This article has provided an overview of how Web Services work, and how to
use them. Leading edge companies and developers have already started inventing
all kinds of imaginative Web Services. Some examples include Microsoft's Passport,
which allows other companies to provide authentication using the engine
that powers the Hotmail email system, and CodeSwap (www.vscodeswap.net),
a Microsoft-supported initiative that allows you to share code fragments with
other developers as easily as you could once share MP3 files in the original
Napster program.
If you want to continue learning about and working with Web Services, here
are some interesting places to start:
• Microsoft provides a Web Services portal that provides such information as
low-level technical information about the SOAP and WSDL standards, code
samples of professional Web Services, and white papers discussing the best
ways to design Web Services. Check it out at http://msdn.microsoft.com/
webservices.
• UDDI (Universal Description, Discovery, and Integration) is an emerging
standard that will make it easy for developers to locate discovery files and
available Web Services on the Internet. You can find more information, and
some interesting examples of Web Services, at http://uddi.microsoft.com/
visualstudio.
• Various other Web Service search engines are appearing on the Internet.
You can use them to see what other developers are up to. To get
started, try out http://www.gotdotnet.com/playground/services and
http://www.xmethods.com.
• Remember, you can enable Session support in a Web Service, and use some
of the same techniques that you would use for authentication in an ASP.NET
application. For more information, check out the MSDN help library.
Matthew MacDonald, an author, educator and MCSD developer, has worked with Visual Basic and ASP since their inceptions. He is the author of The Book of VB .NET (No Starch Press) and ASP.NET: The Complete Reference (Osborne McGraw-Hill) and co-author of Programming .NET Web Services (O'Reilly).