The Book of VB .NET: Web Services, Part 2
Debugging a Web Service Project
When debugging a solution that includes a Web Service project and client, youwill find that any breakpoints or watches you set for the Web Service code areignored. That is because, by default, Visual Studio .NET only loads the debugsymbols for the startup project, which is the client.
To solve this problem, you need to configure Visual Studio .NET to loadboth projects at once. Right- click on the solution item in the Solution Explorer,and select Properties. Then, browse to the Common Properties / StartupProject tab, and specify Multiple Startup Projects, so that both your client andthe 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 .NETstarts the Web Service project by displaying the Internet Explorer test page. Inthis case, however, you don't want any action to be taken other than loading thedebug symbols so that the Web Service code is available for debugging.
Right- click on the Web Service project, and select properties. In the ConfigurationProperties / Debugging tab, select "Wait for an external process to connect"as your start action (Figure 13-10). You can now use the full complementof 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 theGetPackageInfo function. It also includes BeginGetPackageInfo and EndGet-PackageInfo procedures. These routines allow you to retrieve a Web Serviceresult asynchronously. For example, your code can submit a request with Begin-GetPackageInfo, perform some additional tasks, and then retrieve the resultwith EndGetPackageInfo. This allows your program to remain responsive, evenwhen 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 tracksthe current request. You can have multiple asynchronous web requests submittedat the same, as long as you keep track of them with different IAsyncResultobjects.
When the EndGetPackageInfo method is called, the request becomes synchronous.That means that if the response has not yet been received from theWeb Service, your code will wait until it is received (or until the request timesout, according to the proxy class Timeout property).
Alternatively, you can call BeginGetPackageInfo with the address of a subroutinein your program. When the Web Service result is received, this routinewill be called automatically. This technique is ideal if you are requesting someinformation that is not critical, and you want to allow your application to continueits normal behavior. By using a callback, you can respond immediatelywhen the information arrives, but your application doesn't need to sit idle waitingfor it.
Here's an example where a button click submits an asynchronous requestwith 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 calledimmediately, and a MessageBox will appear alerting the user. (A more commonaction might be to use the information to update a portion of the user interface.)The PostalClient included with the online samples demonstrates these differentways 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. Thediscovery file represents Microsoft's goals for easily sharing Web Services andmaking them available to the appropriate clients. You don't need to worry aboutthese sharing issues if you are creating a Web Service exclusively for use in yourcompany website, or with a few select clients. However, if you are trying todevelop and market a Web Service that provides powerful features that you wantto provide as a subscription service, discovery matters quite a lot.
Discovery is the process that allows a client to find the WSDL informationthat describes your Web Service. Your server may have one discovery documentthat points to multiple Web Services, or it may have several different discoveryfiles in various virtual directories. Alternatively, you might not use a discoveryfile at all.
A discovery document is yet another type of XML file. All it contains is a listof web links (URLs) to the WSDL document of various Web Services. Here is asample 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 bescanned 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 thosefolders. This can be used to save time (for example, by restricting directoriesthat contain only images), or to restrict a Web Service from appearing in a discoveryprocess (although it will still be accessible unless you have specificallywritten authentication or security code).
TIP How can you add a web reference if you don't have a discovery file? You can manuallytype the Web Service location into the address bar of the Add Reference window. Youdon't even need to worry about supplying the ?WSDL at the end to locate the WSDLdocument, because Visual Studio .NET is smart enough to add that for youautomatically.
What Comes Next?
This article has provided an overview of how Web Services work, and how touse them. Leading edge companies and developers have already started inventingall kinds of imaginative Web Services. Some examples include Microsoft's Passport,which allows other companies to provide authentication using the enginethat powers the Hotmail email system, and CodeSwap (www.vscodeswap.net),a Microsoft-supported initiative that allows you to share code fragments withother developers as easily as you could once share MP3 files in the originalNapster program.
If you want to continue learning about and working with Web Services, hereare some interesting places to start:
- Microsoft provides a Web Services portal that provides such information aslow-level technical information about the SOAP and WSDL standards, codesamples of professional Web Services, and white papers discussing the bestways to design Web Services. Check it out at http://msdn.microsoft.com/webservices.
- UDDI (Universal Description, Discovery, and Integration) is an emergingstandard that will make it easy for developers to locate discovery files andavailable Web Services on the Internet. You can find more information, andsome 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 getstarted, try out http://www.gotdotnet.com/playground/services andhttp://www.xmethods.com.
- Remember, you can enable Session support in a Web Service, and use someof the same techniques that you would use for authentication in an ASP.NETapplication. 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).
Page 2 of 2