To a server application, a Web service is little more than a URL that returns XML code when invoked. A .NET Web service is a URL with an .asmx extension—an extension that enables special attributes to extend the syntax of Visual Basic (VB) and C#, the languages that programmers use most frequently to write Web services.

To invoke a Web service, you can use any technique that lets you call a URL, including HTML <form> tags and client-side, Windows Scripting Host (WSH)-fueled scripts. COM objects capable of making HTTP calls are also potential Web service clients. Let's look at the MSXML2.XmlHTTP object, which lets you invoke URLs over HTTP from within ASP pages. The following code demonstrates how to connect to a Web service (i.e., using the URL), execute a method, and build an XML DOM tree with the XML data it returns.

<%@language=VBScript%>
<%
Dim srvXmlHttp, xmlResult

Set srvXmlHttp = Server.CreateObject("MSXML2.XMLHTTP")
Set xmlResult = Server.CreateObject("MSXML2.DomDocument")

srvXmlHttp.open "GET", url, false
srvXmlHttp.send ""
Set xmlResult = srvXmlHttp.responseXML

Response.Write xmlResult.xml
%>

The variable URL hides both the path to the URL and the name of the method. Assuming that the Web service's URL is server/service.asmx, you use the following URL to run the method Hello:

http://server/service.asmx/Hello

The method name follows the URL, as do the arguments necessary to run it. The arguments take the form of name/value pairs, where the name is the formal name of the argument. For example,

http://server/service.asmx/Hello?param=World

.NET Clients
A .NET client can access a Web service in two basic ways: Using the URL-based approach that we just discussed, and using a client proxy. Let's look at how the proxy mechanism works.

A proxy class is a .NET wrapper class that Visual Studio.NET generates automatically when you indicate that you want to use a Web service from within a project. The proxy class gives a .NET application the same programming interface of the Web service that the application arose from. As a result, clients make calls into a local .NET class and program against a remote Web service. Any call to methods of this proxy class become roundtrip calls to the Web service server, but this transaction is well hidden in your code.

Visual Studio.NET uses a command-line tool called webserviceutil.exe to generate the wrapper proxy class. The syntax for webserviceutil.exe is

webserviceutil /c:proxy /l:VB /pa:url?sdl

You can use the following switches with the tool:

  • /a Name of the assembly that contains the Web service
  • /c Type of output to generate: proxy, Web Service Description Language (WSDL)
  • /l Language for the code to generate: C#, VB, JavaScript
  • /n Namespace to generate the code in
  • /o Where to create the files
  • /pa Local or URL path to retrieve the Web service from

From a Web service located at a specific URL, you ask the tool to generate a proxy class in a certain language. The tool returns a source file that you can add to your project. Note that the ability to build proxy classes from Web services is limited to Web services that you have written with .NET.

Note: In beta 2 of the .NET platform, Microsoft has renamed the webserviceutil.exe to wsdl.exe.

The Web Service Description Language
The Web Service Description Language (WSDL) is the XML-based language that describes the functionality that a Web service provides. For a .NET Web service, the WebServiceUtil.exe can build the WSDL description by finding and interpreting all the methods marked with a special, language-specific attribute. In VB.NET, this attribute is <WebMethod()>, as shown in the following example:

public Function <WebMethod()> Show() As String

For C#, this syntax changes to \[WebMethod()\], as shown in the following example:

public class MyService : WebService \{
\[WebMethod()\]
     public int DoSomething() \{…\}

The WebServiceUtil tool can generate the class only from a valid and significant WSDL script, which is why you must postpone the ?sdl at the end of your Web service URL when making the call to WebServiceUtil. Either you pass the tool an already available WSDL file, or you ask the tool to generate one on the fly and process it to generate a wrapper class.

Note: In beta 2 of the .NET platform, SDL is known as WSDL.

A WSDL script contains different types of information. The script holds the WSDL file's schema information, which includes XML elements for all the public methods and their return values, plus one element for all the types involved with input arguments. Within an WSDL document, you also find three tags—<soap>, <httpget>, and <httppost>—each of which describes how to make the call according to the specific protocol.

WSDL is not something specific of the .NET platform. In fact, WSDL will soon become a standardized, general-purpose and platform-independent language that describes Web services. When that happens, the .NET infrastructure will only provide special system support for WSDL to applications.

Once you've written a .NET Web service, you can test it in a far simpler and quicker way than writing a wrapper class. If you point your browser to the .asmx URL, you connect to a default page that presents one hyperlink for each of the methods you have made public. Another link lets you see the WSDL script for that Web service. These features demonstrate that you can use a simple URL to call a Web service—and doing so turns out to be a handy way to test whether the return value for each method is what you expect. Once you see the behavior you expect, you can take the next step and create a wrapper class.

Proxy Classes—Some Tips and Tricks
You must follow a few simple, but critical, rules to write effective proxy classes. For example, when manually generating a proxy class, you must add ?sdl to the Web service URL. If you use Visual Studio.NET to generate the proxy class, right-click on the Reference node in the Solution Explorer and select Add Web Reference. Next, when you start using a class in your code, make sure that you add the following assemblies to the project's reference list:

  • System.Xml.Serialization.dll
  • System.Web.Services.dll

If you don’t add the assemblies, you'll use code functionalities that you haven't linked to the final executable code, and you'll receive a compilation error.

Also, remember that the system processes each call you make to a method in a roundtrip process. With that in mind, when designing a Web service's interface, try to aggregate as much functionality as possible in one method, using arguments to select the particular functions you want. This recommendation goes against programming styles that have gained acceptance lately (i.e., styles that call for simpler objects and stateless methods), but a Web service is a particular software component that calls for a different approach.

When you generate a proxy class, try to wrap it in a namespace. The namespace isn't mandatory, but it'll make your life easier. The following code uses a proxy class to call a remote method of a Web service:

Dim ct As New MyNS.CurrentTime()
MsgBox ct.Show()

The MyNS.CurrentTime class wraps a Web service, but you'd never guess it from looking at the client code.

Discovering Web Services
We've discussed how to write and use a Web service. But how do you know whether a Web service is available on a given Web site? You can determine this information in one of two ways. You might know about a Web service because someone told you about it or you read about it in some documentation, or you might find out about it from automatic discovery of Web services. With automatic discovery of Web services, .disco files, which are located in the root of a Web server, give you a list of all the Web services that are available on a server. A .disco file doesn't give you detailed information about a Web service's programming interface, but instead provides a list of what's available and a pointer to an WSDL file that you can consult for more information. I'll devote my next article to .disco files and other technologies that relate to the automatic discovery of Web services.

.NET Clients
A .NET client can access a Web service in two basic ways: Using the URL-based approach that we just discussed, and using a client proxy. Let's look at how the proxy mechanism works.

A proxy class is a .NET wrapper class that Visual Studio.NET generates automatically when you indicate that you want to use a Web service from within a project. The proxy class gives a .NET application the same programming interface of the Web service that the application arose from. As a result, clients make calls into a local .NET class and program against a remote Web service. Any call to methods of this proxy class become roundtrip calls to the Web service server, but this transaction is well hidden in your code.

Visual Studio.NET uses a command-line tool called webserviceutil.exe to generate the wrapper proxy class. The syntax for webserviceutil.exe is

webserviceutil /c:proxy /l:VB /pa:url?sdl

You can use the following switches with the tool:

  • /a Name of the assembly that contains the Web service
  • /c Type of output to generate: proxy, Web Service Description Language (WSDL)
  • /l Language for the code to generate: C#, VB, JavaScript
  • /n Namespace to generate the code in
  • /o Where to create the files
  • /pa Local or URL path to retrieve the Web service from

From a Web service located at a specific URL, you ask the tool to generate a proxy class in a certain language. The tool returns a source file that you can add to your project. Note that the ability to build proxy classes from Web services is limited to Web services that you have written with .NET.

Note: In beta 2 of the .NET platform, Microsoft has renamed the webserviceutil.exe to wsdl.exe.

The Web Service Description Language
The Web Service Description Language (WSDL) is the XML-based language that describes the functionality that a Web service provides. For a .NET Web service, the WebServiceUtil.exe can build the WSDL description by finding and interpreting all the methods marked with a special, language-specific attribute. In VB.NET, this attribute is <WebMethod()>, as shown in the following example:

public Function <WebMethod()> Show() As String

For C#, this syntax changes to \[WebMethod()\], as shown in the following example:

public class MyService : WebService \{
\[WebMethod()\]
     public int DoSomething() \{…\}

The WebServiceUtil tool can generate the class only from a valid and significant WSDL script, which is why you must postpone the ?sdl at the end of your Web service URL when making the call to WebServiceUtil. Either you pass the tool an already available WSDL file, or you ask the tool to generate one on the fly and process it to generate a wrapper class.

Note: In beta 2 of the .NET platform, SDL is known as WSDL.

A WSDL script contains different types of information. The script holds the WSDL file's schema information, which includes XML elements for all the public methods and their return values, plus one element for all the types involved with input arguments. Within an WSDL document, you also find three tags—<soap>, <httpget>, and <httppost>—each of which describes how to make the call according to the specific protocol.

WSDL is not something specific of the .NET platform. In fact, WSDL will soon become a standardized, general-purpose and platform-independent language that describes Web services. When that happens, the .NET infrastructure will only provide special system support for WSDL to applications.

Once you've written a .NET Web service, you can test it in a far simpler and quicker way than writing a wrapper class. If you point your browser to the .asmx URL, you connect to a default page that presents one hyperlink for each of the methods you have made public. Another link lets you see the WSDL script for that Web service. These features demonstrate that you can use a simple URL to call a Web service—and doing so turns out to be a handy way to test whether the return value for each method is what you expect. Once you see the behavior you expect, you can take the next step and create a wrapper class.

Proxy Classes—Some Tips and Tricks
You must follow a few simple, but critical, rules to write effective proxy classes. For example, when manually generating a proxy class, you must add ?sdl to the Web service URL. If you use Visual Studio.NET to generate the proxy class, right-click on the Reference node in the Solution Explorer and select Add Web Reference. Next, when you start using a class in your code, make sure that you add the following assemblies to the project's reference list:

  • System.Xml.Serialization.dll
  • System.Web.Services.dll

If you don’t add the assemblies, you'll use code functionalities that you haven't linked to the final executable code, and you'll receive a compilation error.

Also, remember that the system processes each call you make to a method in a roundtrip process. With that in mind, when designing a Web service's interface, try to aggregate as much functionality as possible in one method, using arguments to select the particular functions you want. This recommendation goes against programming styles that have gained acceptance lately (i.e., styles that call for simpler objects and stateless methods), but a Web service is a particular software component that calls for a different approach.

When you generate a proxy class, try to wrap it in a namespace. The namespace isn't mandatory, but it'll make your life easier. The following code uses a proxy class to call a remote method of a Web service:

Dim ct As New MyNS.CurrentTime()
MsgBox ct.Show()

The MyNS.CurrentTime class wraps a Web service, but you'd never guess it from looking at the client code.

Discovering Web Services
We've discussed how to write and use a Web service. But how do you know whether a Web service is available on a given Web site? You can determine this information in one of two ways. You might know about a Web service because someone told you about it or you read about it in some documentation, or you might find out about it from automatic discovery of Web services. With automatic discovery of Web services, .disco files, which are located in the root of a Web server, give you a list of all the Web services that are available on a server. A .disco file doesn't give you detailed information about a Web service's programming interface, but instead provides a list of what's available and a pointer to an WSDL file that you can consult for more information. I'll devote my next article to .disco files and other technologies that relate to the automatic discovery of Web services.