.NET for Visual FoxPro Developers

Chapter 12
XML Web Services

It’s nearly impossible to pick up a software-related journal these days that doesn’t contain some mention of XML Web Services. This makes it easy to think of Web Services as pure hype, but in reality they may shape the next generation of software applications. XML Web Services are the other half of ASP.NET (the first half is Web Forms). This chapter helps you understand what XML Web Services are, and how you can use them in your .NET applications.

According to Microsoft’s initial marketing push for .NET, XML Web Services are the cornerstone of .NET and the reason for its very existence. In reality, you may use .NET to create both Windows Forms and Web Forms applications without ever creating an XML Web Service. However, there are good reasons why you should consider doing so.

There’s been a lot of interest in the FoxPro community over the fact that Visual FoxPro can both create and consume XML Web Services. In fact, VFP’s Web Service capabilities are what places it under the “.NET umbrella”. Although it’s not a .NET language, Visual FoxPro allows you to create XML Web Services that can be consumed by .NET and it can consume XML Web Services created in .NET.

What is a Web Service?

A Web Service is a code module containing one or more functions accessible via the
Internet. Desktop applications, Web applications, or even another Web Service can access Web Services. When you access a Web Service, you are making a function or method call over the Internet.

Web Services are:

·         Language independent – They can be written in virtually any computer language and accessed by code written in any language

·         Platform independent – They can run on any operating system and be accessed by client code running on any platform.

·         Self-describing – Each Web Service has associated files that describe the services it provides and allows clients to call its methods.

Although most of the software you run is physically located on your own computer, running code on a computer that resides somewhere across the Internet is actually a common occurrence—it happens all the time as you surf the Web, although surfing the Web is not the same as accessing a Web Service. So, first you’ll look at what happens when you surf the Internet, and then see how Web Services takes this approach a step further.

As you navigate to different sites with your browser, you request Web pages located on Web servers across the Internet. Behind the scenes, especially when accessing Web pages with dynamic content, a Web server runs code in response to your request and sends HTML, script code, and so on, back to your computer. In this manner, you’re indirectly running code that resides on a Web server.

When using technologies such as ASP or ASP.NET pages, the code that’s being executed is often stored in methods of business components located on the Web server. For example, in Chapter 10, “Building Web Applications with ASP.NET”, you created a Web Forms application that allowed users to view and edit orders for a specified customer. As shown in Figure 1, when the user enters a Customer ID and clicks the Submit button, the Web server instantiates the Orders business object and calls its GetOrdersByCustomerID method. The Web Server produces an HTML list of customer orders to send back to your browser.

 

Figure 1. When you access ASP or ASP.NET pages, you are often indirectly causing code to be executed on a Web server.

For the most part, this approach works well. However, XML Web Services let you take this paradigm a step further, giving you greater control. They effectively allow you to call the GetOrdersByCustomerID method of the Orders business object directly. Just think about how useful this is. If you are able to call the method directly, you can retrieve a list of customer orders as an XML string and manipulate it in your own software applications, and even persist it to a local data store. Later in this chapter, you’re going to build a Web Service allowing you to do just that.

This type of Web Service is private by nature, established between business partners. You may have certain clients that you allow to access the Web Service, but you certainly don’t want to provide free access to the rest of the world. In contrast, there are other types of Web Services that are intended for public consumption. For example, Fed-Ex™ has a public Web Service letting you track packages. You simply pass your tracking number to the Web Service and it returns a string containing tracking information.

At this point, you will build an ASP.NET XML Web Service and explore the technologies behind Web Services along the way.


Creating a Customer Orders Web Service

To create a .NET XML Web Service:

1.       Launch Visual Studio .NET, and click the New Project button on the Start Page.

2.       In the left pane of the New Project dialog (Figure 2), select Visual C# Projects or Visual Basic Projects, depending on the language you want to use. In the Templates pane on the right, select ASP.NET Web Service.

3.       Notice the Name text box is disabled and contains the text “WebService1”, and
if you’re creating the Web Service on your local machine, the Location text box contains the text “http://localhost/WebService1”. To change the name of the Web Service, you must change the name of the directory in the Location text box.
Change the name “WebService1” to “Customer Orders Web Service, and then click the OK button.

Figure 2. You can choose to create a C# or Visual Basic ASP.NET Web Service in the New Project dialog.

At this point, Visual Studio .NET briefly displays the Creating the Web dialog while it creates a new ASP.NET Web Service from the template you have selected. After a few moments, a new Web Service file is displayed in the IDE (Figure 3).

Figure 3. VS .NET automatically creates a Web Service file when you create a new ASP.NET Web Service.

Rename this Web Service file so it’s a little more descriptive. To do this, with the Web Service file selected in design mode, go to the Properties Window and change the Name property from “Service1” to “CustomerOrders” (Figure 4).

Figure 4. You change the name of the Web Service in the Visual Studio .NET Properties Window.

You’ll take a closer look at this file soon, but you need to do a little housekeeping first.

Renaming the project namespace

When you create a new Web Service, ASP.NET automatically sets your project’s namespace to the same name as your project (as it also does when building Windows Forms and Web Forms applications). To change the default namespace in VB .NET, you must first close the CustomerOrders page (you don’t need to do this in a C# project). Next, go to the Solution Explorer and right-click on the project (the second node from the top). From the shortcut menu, select Properties, which launches the Property Pages dialog. In the left pane of the dialog, under the Common Properties folder, select General if it’s not already selected.

If you’re using C#, in the right pane, change the Default Namespace from “Customer_Orders_Web_Service” to “HW.NetBook.Samples”. If you’re using Visual Basic .NET, in the right pane, change the Root namespace to “HW.NetBook.Samples”. When you’re done, click the OK button to save changes.

To change all existing references to the original namespace, from the main menu select Edit | Find and Replace | Replace in Files. In the Replace In Files dialog’s Find what text box, enter “Customer_Orders_Web_Service”. In the Replace with text box, enter “HW.NetBook.Samples”, (make sure you enter this with the exact case shown here). Click the Replace All button. This launches a warning dialog—simply press OK to ignore the warning. When the find and replace is finished, it displays a dialog indicating how many occurrences were replaced. If you’re using C#, it should say “4 occurrence(s) replaced”. If you’re using Visual Basic .NET, it should say “2 occurrence(s) replaced”. Click the OK button to close these dialogs.

Web Service virtual directories

When you use Visual Studio .NET to create a Web Service, it automatically creates a virtual directory for you.

Text Box: ¥

For more information on virtual directories, see Chapter 10, “Building Web Applications with ASP.NET”.

This virtual directory contains your new Web Service project and related files (Figure 5). However, as with Web Forms applications, the actual Solution file is stored in a subfolder of the “My Documents\Visual Studio Projects\” directory. Again, this means when you reopen your Web Application after restarting Visual Studio, you will find your solution in this folder.

Figure 5. Visual Studio .NET places a variety of files in your Web Service’s virtual directory.

Before taking a closer look at these files first take a behind-the-scenes look at the Web Service file.

A closer look at the Web Service file

You can view a Web Service file in either design view or code view. To switch to code view, you select the click here to switch to code view hyperlink on the page or right-click the file and select View Code from the shortcut menu. When you do this, you should see the following class definition in C#:

public class CustomerOrders: System.Web.Services.WebService

{

  public CustomerOrders ()

  {

       //CODEGEN: This call is required by the ASP.NET Web Services Designer

       InitializeComponent();

  }

 

  // WEB SERVICE EXAMPLE

  // The HelloWorld() example service returns the string Hello World

  // To build, uncomment the following lines then save and build the project

  // To test this web service, press F5

 

//        [WebMethod]

//        public string HelloWorld()

//        {

//            return "Hello World";

//        }

}

And in Visual Basic .NET:

Public Class CustomerOrders

    Inherits System.Web.Services.WebService

 

    ' WEB SERVICE EXAMPLE

    ' The HelloWorld() example service returns the string Hello World.

    ' To build, uncomment the following lines then save and build the project.

    ' To test this web service, ensure that the .asmx file is the start page

    ' and press F5.

    '

    '<WebMethod()> Public Function HelloWorld() As String

    '  HelloWorld = "Hello World"

    ' End Function

 

End Class

As you can see, this code defines a class named CustomerOrders derived from the .NET Framework’s System.Web.Services.WebService class. Also notice the method that is commented out at the bottom of the class definition. As described in the comments above it, you can uncomment this code and then build and run this sample Web Service, which you will do in the next section

Running the “Hello World” Web Service

To run the sample “Hello World” Web Service, select all of the commented code in the HelloWorld method (including the WebMethod attribute), and then click VS .NET’s Uncomment icon button (Figure 6). Alternately, to uncomment code, you can select Edit | Advanced | Uncomment Selection from the main menu.

Figure 6.You can use the “Uncomment” button to uncomment selected lines of code.

To save, build, and run the Web Service in one step, just press the F5 button. After a few moments, a Web Service help page displays in your Web browser. This page lists all of your Web Service methods and gives you a link to Service method help pages that allow you to test your Web Service methods  (very cool!).

What’s nice about this is the page is generated and displayed for any user who tries to call your Web Service without the proper parameters. You can try this for yourself by typing the URL of your Web Service into your browser’s Address box. For example:

http://localhost/Customer Orders Web Service/Service1.asmx

The upper portion of the Web Service help page (Figure 7) displays the name of your Web Service (CustomerOrders), and a single HelloWorld operation—this is the method that you just uncommented. It also displays a warning about changing the default namespace of your Web service—you’ll do this a bit later.

Figure 7. Visual Studio .NET creates a Web Service help page customized to your Web Service.

To test the Web Service, click the HelloWorld hyperlink. This displays the Service method help page (Figure 8), which includes a description of the operation and an Invoke button that allows you to test the Web Service.

Figure 8. The Service method help page displays a description of the operation and an Invoke button that allows you to call the Web Service method.

At this point, click the Invoke button. Behind the scenes, the Service method help page calls the HelloWorld test method and displays the return value in a new browser window (Figure 9).

Figure 9. The Service method help page launches another browser window that displays the return value passed back from the Web Service method.

As you can see, although the code in the HelloWorld method returns a simple string, it is converted into XML when it returns to the Web Service caller. At this point, close the Browser window, so you can work further with the Web Service project.


Web Service project files

Now that you’ve created a simple .NET Web Service, take a quick look at the files within a Web Service project.

The global.asax file automatically added to your Web Service project by Visual Studio .NET is exactly the same as the global.asax file that it includes in new Web Forms projects. The same is also true of the Web.config file. If you create a new Web Service project and compare these files to a new Web Forms project, you’ll find no differences. For more information on these files, see Chapter 10, “Building Web Applications with ASP.NET”.

The vsdisco file

There is one file you’ll find in Visual Studio .NET Web Service projects you won’t find in a Web Forms application—the vsdisco file. This file is a Web Services discovery file used by Visual Studio .NET as it searches through folders on your development Web server looking for available XML Web Services.

If you look in the Solution Explorer, you will see a file named “Customer Orders Web Service.vsdisco”. If you double-click this file, VS .NET opens it in the IDE. By default, it contains the following XML data:

<?xml versio_="1.0" encodi_g="utf-8" ?>

<dynamicDiscovery xmlns="urn:schemas-dynamicdiscovery:disco.2000-03-17">

<exclude pa_u104 ?="_vti_cnf" />

<exclude pa_h="_vti_pvt" />

<exclude pa_u104 ?="_vti_log" />

<exclude pa_u104 ?="_vti_Ucript" />

<exclude pa_h="_vti_txt" />

<exclude pa_u104 ?="Web References" />

</dynamicDiscovery>

As you can see, the file contains a <dynamicDiscovery> root node with several <exclude> child nodes. The <exclude> nodes contain a relative path to folders VS .NET should not search when it’s going through the directories on your Web server looking for Web Services.

For more information, see the .NET Help topic “Deploying XML Web Services in Managed Code”.

Using business objects

Now it’s time to reference and use the business objects you created in Chapter 9, “Building .NET Windows Forms Applications”. Again, there are a number of ways to accomplish
this, but the easiest method is adding the business object source code files to the Web
Service project.

To add these source code files, right-click on your Web Service project in the Solution Explorer and select Add | Add Existing Item from the shortcut menu. In the Add Existing Item dialog, navigate to the “Simple Windows Application” directory you created in the previous chapter, and select the three business object source code files (Figure 10). These are Business.cs, Data.cs, and OrdersBusiness.cs. If you created a Visual Basic .NET Windows Forms application, these files will have a “vb” extension rather than a “cs” extension. After selecting all three files, click the Open button.

Figure 10. You can add files belonging to one .NET project to any other .NET project

After clicking the Open button, the three files should be listed in the Solution Explorer.

Text Box: ¥

Typically, with business objects that are going to be used from multiple projects, you should create a separate Class Library project in Visual Studio .NET and add your business object source code files to this project. You can then compile a DLL containing just your business object classes. This DLL can then be referenced from multiple projects

Creating custom Web methods

Now, you’re ready to add to the WebService file a custom Web method that instantiates and calls a method of the Orders business object. First, go back to the code-behind file (Service1.asmx.cs or Service1.asmx.vb), and comment out the HelloWorld method you previously uncommented. Make sure you also comment out the line containing “[WebMethod]”. For more information on this attribute, see the section “The WebMethod attribute” later in this chapter.

Next, add the following namespace reference to the top of the code-behind file so you can access the Orders business object class.

In C#:

using HW.NetBook.Samples.Business;

In Visual Basic .NET:

Imports HW.NetBook.Samples.Business

Now, add the following method to the bottom of the CustomerOrders WebService class definition—make sure it’s directly below the commented out Hello World Web Method.

In C#:

[WebMethod (Description="Returns orders for the specified customer")]

public DataSet GetOrdersByCustomerID(string custID)

{

  // Instantiate the Orders business object

  Orders OrderObj = new Orders();

 

  // Call its GetOrdersByCustomerID method

  return OrderObj.GetOrdersByCustomerID(custID);

}

In Visual Basic .NET:

<WebMethod(Description:="Returns orders for the specified customer")> _

Public Function GetOrdersByCustomerID(ByVal custID As String) As DataSet

    ' Instantiate the Orders business object

    Dim OrderObj As New Orders()

 

    ' Call its GetOrdersByCustomerID method

    Return OrderObj.GetOrdersByCustomerID(custID)

End Function 'GetOrdersByCustomerID

This Web method instantiates the Orders business object and calls its GetOrdersByCustomerID method, passing the custID value it receives from the client calling the Web Service. Notice the method specifies a DataSet as the return value. Even though the return value is specified to be a DataSet, if you call the Web Service, you actually get the DataSet returned in XML format.

Unfortunately, Visual FoxPro 7 cannot work with the XML returned from a Web Service in this fashion (this should be fixed in Visual FoxPro 8). If you want to create a Web Service that a Visual FoxPro 7 client can consume, you explicitly convert the DataSet to XML and return the XML string from the Web Service method as shown in the following code (for this example, I leave the GetOrdersByCustomerID method returning a DataSet as shown above).

In C#:

[WebMethod (Description="Returns orders for the specified customer")]

public string GetOrdersByCustomerID(string custID)

{

  // Instantiate the Orders business object

  Orders OrderObj = new Orders();

 

  // Call its GetOrdersByCustomerID method

  DataSet dsOrders = OrderObj.GetOrdersByCustomerID(custID);

  return dsOrders.GetXml();

}

And in Visual Basic .NET

<WebMethod(Description:="Returns orders for the specified customer")> _

Public Function GetOrdersByCustomerID(ByVal custID As String) As String

 

    ' Instantiate the Orders business object

    Dim OrderObj As New Orders()

 

    ' Call its GetOrdersByCustomerID method

    Dim dsOrders As DataSet = OrderObj.GetOrdersByCustomerID(custID)

    Return dsOrders.GetXml()

 

End Function

Before taking a closer look at what happens behind the scenes with the Web Service, first look at the WebMethod and WebService attributes.

The WebMethod attribute

If you place a WebMethod attribute directly above a method declaration, the method is exposed by Visual Studio .NET as a public method of the XML Web Service. A WebService class can have multiple methods, but only those that possess the WebMethod attribute are exposed as part of the Web Service.

As you can see in the new method you created, the WebMethod attribute also allows you to specify a method description. Table 1 lists other properties of the WebMethod attribute that you can also set.

Table 1. WebMethod properties

Property

Description

Default

BufferResponse

Specifies if ASP.NET should buffer the entire response before sending it to the client.

true

CacheDuration

Specifies if the result set of each unique parameter set should be cached, and if so, for how many seconds.

0

Description

Gives a description for the Web Service method.

“”

EnableSession

Specifies if session state is enabled for a Web Service method.

false

MessageName

Specifies an alias for an overloaded method name.

“”

TransactionOption

Specifies transaction options for a Web Service method. Possible values are:

·                      Disabled

·                      Not Supported

·                      Supported

·                      Required

·                      RequiresNew

Disabled

 

For more information on each of these properties, see the .NET Help topic “Using the WebMethod Attribute”.


The WebService attribute

As shown in Figure 7 earlier in this chapter, when you run the HelloWorld Web Service, the Web Service test page displays a warning about changing the name of the Web Service’s namespace from “http://tempuri.org/” to your own, unique namespace. To do this, you need the WebService attribute.

The WebService attribute is applied to a Web Service by placing it directly above the Web Service class definition. For example, place the following attribute definition above the CustomerOrders WebService class definition.

In C#:

[WebService(Namespace="http://servername/xmlwebservices/",

   Description="Customer Orders Web Service")]

In Visual Basic .NET:

<WebService(Namespace:="http://servername/xmlwebservices/", _

   Description:="Customer Orders Web Service")> _

The first part of the WebService attribute declaration specifies the Namespace property. Specifying this value replaces the Web Service’s default “http://tempuri.org/” namespace. When creating a Web Service, you can specify your own unique URL by using the Namespace property. As shown in the second line of the declaration, you can also specify a Description property, which provides a description for the entire Web Service class.

Running the Customer Orders Web Service

Now you’re ready to run the Customer Orders Web Service. To do this, press the F5 key to save all changes, compile the Web Service application, and run it. When your browser is launched, you should see the Web Service help Page shown in Figure 11.

Figure 11. The WebService and WebMethod attributes allow you to specify descriptions (and other properties) for your Web Service and its methods.

Notice the top of the page displays the name of the Web Service class, “CustomerOrders”. Beneath the name is the description you supplied in the WebService attribute. At the bottom of the page is the GetOrdersByCustomerID along with the description you supplied in the WebMethod attribute.

If you click on the GetOrdersByCustomerID link, the Service method help page is displayed (Figure 12).

Figure 12. The Service method help page displays a user input control for each parameter of your Web Service method.

As you can see, the Service Method help page displays an input text box for each parameter of a Web Service method. In this case, you just have one—custID. Enter the value “QUICK” in the custID text box, and then click the Invoke button. A new browser window displays the XML returned from the method (Figure 13).

Figure 13. The Service method help page launches a second browser window that contains the XML returned from the CustomerOrders Web Service.

The Web Services Description Language (WSDL) file

Now that you’ve created and tested a Web Service, you can take a closer look behind the scenes at some of the standards that make XML Web Services possible. I’ll start with the Web Services Description Language (WSDL) file.

A Web Service’s WSDL file (pronounced “wis-dle”) is roughly equivalent to a COM server’s type library. Remember, a type library describes the classes and methods publicly available in a COM server.  In the same way, a WSDL file (also known as a service description document) describes the public classes and methods available in a Web Service.

Type libraries work great for COM servers, but they are Microsoft-specific—and Web Services are not. So, when the W3C committee chose a format to describe Web Services, they chose XML—a widely accepted, platform-neutral, extensible standard. WSDL defines an XML grammar for describing Web Services.

If you want to view your Web Service’s WSDL file, you do so from the Web Service help page (Figure 11). If you click the Service Description link, it launches a browser window that displays your Web Service’s WSDL file (Figure 14).

Figure 14. Visual Studio .NET automatically generates a WSDL file for your Web Services.

As shown in Figure 14, the WSDL file contains information on each public method, along with the method’s parameters and return value (not shown in the figure). By default, when you create a Web Service in Visual Studio .NET, your WSDL file is dynamically generated. You can also create a WSDL file, place it on your Web server, and make its location known to your customers (or the general public) so they can download the file and determine how to access your Web Service.

A full explanation of the structure and contents of a WSDL file is beyond the scope of this book. For more information, see the .NET Help topic “XML Web Service Description”, which also contains a link to the WSDL specification (http://www.w3.org/TR/wsdl).


SOAP

Another XML-based standard key to Web Services is Simple Object Access Protocol (SOAP). SOAP is a protocol for exchanging structured and type information on the Web.

You can actually view some of the SOAP formatting for your Web Service from the Service Method Help Page. For example, here is the SOAP request and response shown on the GetOrdersByCustomerID Service Method Help Page.

Here is the SOAP request:

POST /Customer%20Orders%20Web%20Service/Service1.asmx HTTP/1.1

Host: localhost

Content-Type: text/xml; charset=utf-8

Content-Length: length

SOAPAction: "http://servername/xmlwebservices/GetOrdersByCustomerID"

 

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">

  <soap:Body>

    <GetOrdersByCustomerID xmlns="http://servername/xmlwebservices/">

      <custID>string</custID>

    </GetOrdersByCustomerID>

  </soap:Body>

</soap:Envelope>

And here is the SOAP response:

HTTP/1.1 200 OK

Content-Type: text/xml; charset=utf-8

Content-Length: length

 

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">

  <soap:Body>

    <GetOrdersByCustomerIDResponse xmlns="http://servername/xmlwebservices/">

      <GetOrdersByCustomerIDResult>

        <xsd:schema>schema</xsd:schema>xml</GetOrdersByCustomerIDResult>

    </GetOrdersByCustomerIDResponse>

  </soap:Body>

</soap:Envelope>

For more information on the SOAP standard, check out the .NET Help topic “XML Web Service Wire Formats”, which contains a link to the W3C Web site (http://www.w3.org/soap).

Consuming Web Services

As mentioned earlier in this chapter, desktop applications, Web applications, or other Web Services can consume Web Services.  In this section, you will create a desktop application that accesses the Customer Orders Web Service.

The ability to access a Customer Orders Web Service from a desktop application can be extremely useful. For example, if you have placed orders with one of your suppliers, it would be great to call a Web Service on your supplier’s Web site that allowed you to retrieve all of your orders and display them within one of your own desktop applications. This is good for your supplier, because they don’t have to pay a humanoid to research the information and send it to you. It’s also good for you, because not only can you display this information in your own custom application, you can now manipulate and store the information in your own database.

Before going any further, close your Web Service application. Next, to create a new Windows Application, from the Start Page of VS .NET, click the New Project button. In the left pane of the New Project dialog, select either Visual C# Projects or Visual Basic Projects. In the Templates pane on the right, select Windows Application. In the Name text box, enter “WinForms Web Service Consumer”, and specify the desired location for your new project in the Location text box (Figure 15). When you’re done, click the OK button to create your new Windows application.

Figure 15. You can consume a Web Service from a Windows application (shown here), a Web Forms application, or another Web Service.

When Visual Studio .NET finishes creating your new project, you see a new form named “Form1” in the IDE. You will use this form to display the user interface controls and call the Web Service. This is different than what you did in Chapter 9, “Building .NET Windows Forms Applications”, because in this case, you just need a bare bones application to call your Web Service. First, you need to make a few changes to the form. With the form selected in the IDE, go to the Properties Window, change the Name property to “WebServiceConsumerForm”, the Size property to 640, 260, and the Text property to “Web Service Consumer”.

Now you need to perform one additional step, which is different depending on whether you’re using C# or Visual Basic .NET. In C#, right-click on the form and select View Code from the shortcut menu. At the bottom of the code-behind file, find the line of code that calls Application.Run:

Application.Run(new Form1());

And change it to:

Application.Run(new WebServiceConsumerForm());

In Visual Basic .NET, go to the Solution Explorer, right-click the project node (second from the top), and select Properties from the shortcut menu. This launches the Property Pages dialog. In the left pane, under the Common Properties node, select General. In the right pane, change the Startup Object to “WebServiceConsumerForm”, and then click OK to save the change.

Now select Form1 in design mode and drag and drop a DataGrid control from the VS .NET Toolbox onto the form. If the Toolbox is not visible in the IDE, select View | Toolbox from the main menu. Change the DataGrid properties to the values shown in Table 2.

Table 2. DataGrid properties

Property

Value

Name

grdOrders

Location

40, 30

Size

550, 140

 

Next, drag a Button from the VS .NET Toolbox to the form and set its properties to the values shown in Table 3.

Table 3. Button properties

Property

Value

Name

btnCallWS

Location

345, 195

Size

100, 23

Text

Call Web Service

 

Next, drag and drop a TextBox from the Toolbox onto the form and sets its properties to the values shown in Table 4.


Table 4. Text Box properties

Property

Value

Name

txtCustomerID

Location

185, 195

Size

135, 20

Text

(empty string)

 

When you’re done, your form should look like the form shown in Figure 16.

Figure 16. This Windows form is used to access the Customer Orders Web Service.

Adding a reference to the Web Service

Now it’s time to add a reference to the Customer Orders Web Service to your project. To do this, go to Solution Explorer, right-click the References node, and select Add Web Reference from the shortcut menu (Figure 17).

Figure 17. You can add a reference to a Web Service to your project by right-clicking References in the Solution Explorer and selecting Add Web Reference from the shortcut menu.

Selecting this option launches the Add Web Reference dialog. The left pane of the dialog displays information about the UDDI Directory. You’ll look at this later, but for now, you just want to reference the local Customer Orders Web Service.

The Address combo box at the top of the dialog allows you to select a previously used Web Service or enter a URL and file name for the Web Service you want to reference. In this case, you want to enter a reference to your Web Service’s .asmx file:

http://localhost/Customer Orders Web Service/Service1.asmx

When you enter this URL and press enter, it shows the familiar Web Service help page displaying a description of the Web Service and its operations (Figure 18). In the right pane, there are View Contract and View Documentation hyperlinks. If you click the View Contract link, it displays the WSDL file in the dialog’s left pane. If you click the View Documentation link, it displays any extra documentation you created for your Web Service.

Figure 18. The Add Web Reference dialog allows you to search for Web Services you can reference in your .NET projects.

To add a reference to the Customer Orders Web Service to your project, click the Add Reference button. If you look in the Solution Explorer, you can see this adds a new localhost node containing three new files (Figure 19). Visual Studio.NET uses the name of this node as part of the namespace for the Web Service so, rename it to something more informative. To do this, right-click on the localhost node, select Rename from the shortcut menu, and then rename the node from “localhost” to “CustomerOrdersWebService”.

Figure 19. Adding a Web Reference to your project adds three new files to your project.

Now, take a closer look at the files added to the project. In order to see all of the file detail, click the Show All Files button at the top of the Solution Explorer (Figure 20).

Figure 20. Click the Show All Files button to display all file detail in your project.

Expand the CustomerOrdersWebService node, and you’ll see three files. Reference.map is an XML file that maps URLs to local cached copies of the Service1.disco and Service1.wsdl files. Service1.disco is a Web Service discovery file. For more information on .disco files, see the “Web Services Discovery” section later in this chapter. Service1.wsdl is a local copy of the Customer Orders Web Service WSDL file.

If you expand the Reference.map node, you’ll see a file named Reference.cs (or Reference.vb). Open this file by double-clicking it and you’ll see the definition of a class named CustomerOrders based on the .NET Framework’s SoapHttpClientProtocol class.


In C# (shown partially):

public class CustomerOrders :

   System.Web.Services.Protocols.SoapHttpClientProtocol

{

  ...

}

And in Visual Basic .NET (shown partially):

Public Class CustomerOrders

    Inherits System.Web.Services.Protocols.SoapHttpClientProtocol

  ...

End Class

This is a proxy class you can use to call methods on the Customer Orders Web Service. When you call a Web Service method, you don’t actually call the method on a Web Service’s object directly. Rather, you instantiate a local proxy class (based on the .NET Framework’s SoapHttpClientProtocol class) that passes the call on to the Web Service (Figure 21).

Figure 21. When you add a Web Service reference to your project, VS .NET automatically creates a local proxy class that you can use to indirectly call methods of the Web Service.

Calling the Web Service

Now you’re ready to add code to the form to call the Web Service. To do this, select the Form1.cs [Design] tab (or Form1.vb), and double-click the Call Web Service button. This adds a new btnCallWS_Click event handler method to the form.

Before adding code to this method, go to the top of the form and add a reference to the CustomerOrders proxy class’ namespace.


In C#:

using WinForms_Web_Service_Consumer.CustomerOrdersWebService;

And in Visual Basic .NET:

Imports WinForms_Web_Service_Consumer.CustomerOrdersWebService

Now, go back to the bottom of the code-behind file and add code to the btnCallWS_Click event handler method.

In C#:

private void btnCallWS_Click(object sender, System.EventArgs e)

{

  // Instantiate the Web Service proxy class

  CustomerOrders CustomerOrdersWS = new CustomerOrders();

 

  // Call the Web Service and store the returned DataSet into dsOrders

  DataSet dsOrders =

    CustomerOrdersWS.GetOrdersByCustomerID(this.txtCustomerID.Text);

 

  // Bind the DataSet to the Orders DataGrid

  this.grdOrders.SetDataBinding(dsOrders, dsOrders.Tables[0].TableName);

}

And in Visual Basic .NET:

Private Sub btnCallWS_Click(ByVal sender As System.Object, _

    ByVal e As System.EventArgs) Handles btnCallWS.Click

    ' Instantiate the Web Service proxy class

    Dim CustomerOrdersWS As New CustomerOrders()

 

    ' Call the Web Service and store the returned DataSet into dsOrders

    Dim dsOrders As DataSet = _

        CustomerOrdersWS.GetOrdersByCustomerID(Me.txtCustomerID.Text)

 

    ' Bind the DataSet to the Orders DataGrid

    Me.grdOrders.SetDataBinding(dsOrders, dsOrders.Tables(0).TableName)

End Sub 'btnCallWS_Click

In this method, the first line of code instantiates the CustomerOrders Web Service proxy object. The next line calls the Web Service, passing the value stored in the Customer ID text box, and storing the return value in the dsOrders DataSet. The last line of code binds the DataSet to the DataGrid.

Running the Customer Orders Web Service consumer

Now it’s time to run the Customer Orders Web Service consumer project. To do this, press F5, and Visual Studio .NET automatically saves all changes, compiles the project, and runs it. To test the Web Service, once the form displays, enter the text “QUICK” in the text box, and then click the Call Web Service button (Figure 22).

Figure 22. The Web Service Consumer form calls the Customer Orders Web
Service to retrieve the orders for the specified customer, and then displays them
in the DataGrid.

If this is the first time your Web server has started up, it will take several seconds before any records are displayed in the DataGrid. However, subsequent calls should respond far more quickly (you can try other customer IDs such as “QUEEN”, “OCEAN”, and “CHOPS”).

Before continuing to the next section, close the Web Service Consumer form to avoid any conflicts.

Web Services Discovery

Do you want to be discovered or not? If your Web Service is of a private nature, you probably don’t. You will only inform your business associates of its existence and not tell the rest of the world. However, you may want to create a Web Service intended for public consumption. How can others learn about your Web Service and the details of how to call its methods? This is accomplished by a process called discovery.

Discovery with UDDI

Universal Description, Discovery, and Integration (UDDI) is a registry that allows you to locate Web Services. If you have a Web Service you want to make public, you register information about your Web Service in the UDDI directory, and others can learn about your Web Service by searching the UDDI registry.

As you saw earlier in this chapter, when you add a Web Reference to your project, Visual Studio .NET provides an interface you can use to search the UDDI directory. Let’s go back to this form and use it to search the UDDI directory.

 Right-click the Add References node in the Solution Explorer and select Add Web Reference from the shortcut menu. This displays the Add Web Reference dialog (Figure 23).

Figure 23. The Add Web Reference dialog allows you to search the UDDI directory for Web Services exposed on the Internet.

In the left pane there are two hyperlinks. The UDDI Directory link allows you to search for “real, live” Web Services, and the Test Microsoft UDDI Directory link allows you to search for “test” Web Services. Click the UDDI Directory link and the message “Downloading Web Service Files” appears in the right pane. After several seconds, the UDDI Search Tool is displayed in the left pane (Figure 24).

Figure 24. The UDDI search tool allows you to search for Web Services by name or by category.

The UDDI search tool allows you to search for Web Services by Service name, Provider Name, or category. For example, type the word “weather” into the Service Name text box and click the Search button. As of the writing of this book, several weather Web Services registered with UDDI are displayed in the left pane of the Add Web Reference dialog
(Figure 25).

Figure 25. There are multiple weather services registered with UDDI.

Pick the “Weather Retriever” Web Service from the list (if you don’t see this specific Web Service, just choose another one). Expand the node of the “Weather Retriever” Web Service and you will see a more detailed description of the Web Service (Figure 26). The Service Description details that this Web Service retrieves Weather information based on a specific zip code. Also, notice the link displayed under “Interface definitions” references an .asmx file. It tells you that this is a .NET Web Service (although it doesn’t have to be a .NET Web Service to work properly in this example!)

Figure 26. Clicking the Interface definitions link enables the Add Reference button, allowing you to add a Web Service reference to your project.

Adding a Web Service reference from UDDI

If you click the Interface definitions link, the message “Downloading Web Service files…” appears in the right pane. After several seconds, the Web Services WSDL file appears in the left pane, and the Add Reference dialog is enabled. Click the Add Reference button to add a reference to the Weather Fetcher Web Service to your project. When you do this, Visual Studio .NET adds three files to your project. Notice the URL for the Web Service is shown in reverse order (Figure 27).

Figure 27. The URLs for Web References added to your project by Visual Studio.NET are shown in reverse order.

When you added the local Customer Orders Web Service to the project, you renamed the “localhost” node to something more descriptive because it is used as the namespace of the Web Service proxy class. However, with this public Web Service, leave the name “as is” because it provides a unique namespace.

Next, you’ll add some user interface controls to your project’s Form1 that allow you to call the Weather Retriever Web Service and display its results. Drag and drop the controls listed in Table 5 from the Visual Studio.NET Toolbox onto the form and set the corresponding properties listed in the table.

Table 5. Weather Web Service user interface controls

Control

Property

Value

GroupBox

 

 

 

Name

grpWeather

 

Location

40, 249

 

Size

540, 165

 

Text

Weather

Label

 

 

 

Name

lblZipCode

 

AutoSize

True

 

Location

80, 30

 

Text

Zip Code:

TextBox

 

 

 

Name

txtZipCode

 

Location

145, 28

 

Size

135, 20

 

Text

(empty string)

Button

 

 

 

Name

btnCallWS2

 

Location

305, 28

 

Size

100, 23

 

Text

Call Web Service

TextBox

 

 

 

Name

txtWeather

 

Location

25, 70

 

MultiLine

True

 

Size

490, 75

Calling the Web Service

Now you are ready to add code to the form that calls the Web Service and displays the
result. Double-click the btnCallWS2 button to automatically add a new event handler
method named btnCallWS2_Click to the form’s code-behind file. Before adding code to
this method, go to the top of the code-behind file and add a reference to the Web Service proxy object’s namespace.

In C#:

using WinForms_Web_Service_Consumer.com.vbws.www;

And in Visual Basic .NET:

Imports WinForms_Web_Service_Consumer_Visual_Basic.com.vbws.www

Now add the following code to the btnCallWS2_Click method at the bottom of the
code-behind file.

In C#:

private void btnCallWS2_Click(object sender, System.EventArgs e)

{

  // Instantiate the WeatherRetriever Web Service proxy

  WeatherRetriever WeatherRetrieverWS = new WeatherRetriever();

 

  // Call the Web Service's GetWeather method

  CurrentWeather WeatherReport =

   WeatherRetrieverWS.GetWeather(this.txtZipCode.Text);

 

  // Display the results

  this.txtWeather.Text = WeatherReport.Conditions + "\r\n" +

   "Temperature: " + WeatherReport.CurrentTemp + "\r\n" +

   "Humidity: " + WeatherReport.Humidity + "\r\n" +

   "Barometer: " + WeatherReport.Barometer + "\r\n" +

   "Barometer Direction: " + WeatherReport.BarometerDirection;

}

And in Visual Basic .NET:

Private Sub btnCallWS2_Click(ByVal sender As System.Object, _

    ByVal e As System.EventArgs) Handles btnCallWS2.Click

    ' Instantiate the WeatherRetriever Web Service proxy

    Dim WeatherRetrieverWS As New WeatherRetriever()

 

    ' Call the Web Service's GetWeather method

    Dim WeatherReport As CurrentWeather = _

        WeatherRetrieverWS.GetWeather(Me.txtZipCode.Text)

 

    ' Display the results

    Me.txtWeather.Text = WeatherReport.Conditions & ControlChars.CrLf & _

        "Temperature: " & WeatherReport.CurrentTemp & ControlChars.CrLf & _

        "Humidity: " & WeatherReport.Humidity & ControlChars.CrLf & _

        "Barometer: " & WeatherReport.Barometer & ControlChars.CrLf & _

        "Barometer Direction: " & WeatherReport.BarometerDirection

End Sub

Running the Web Service consumer

Now you’re ready to run the Web Service. To do this, just press F5 to save all changes, compile the project, and run the application. When the form is displayed, enter a zip code in the Zip Code text box (for example, “22903”), and then click the Call Web Service button. After several seconds, you should see the weather report for the specified zip code displayed in the text box at the bottom of the form (Figure 28).

Figure 28. This form demonstrates how to call a public Web Service discovered by means of UDDI.

Conclusion

As you see from this chapter, Microsoft has made it very easy to both publish and consume Web Services in Visual Studio.NET. Although you may not initially find a use for Web Services in your application, as they become more and more mainstream, and as new, reliable Web Services become more prevalent, you may find they give your desktop and Web applications a level of interoperability they’ve never had before.

 

 


.NET for Visual FoxPro Developers