Excerpted with permission from The Book of VB .NET, by Matthew MacDonald, No Starch Press, Copyright 2002.
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
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
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,
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
Touching Up Your Web Service
To improve your Web Service, you might want to add a description to the
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.
Part 2 will appear tomorrow.
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).