Consuming XML Web Services

Every time we come upon XML in this book, I mention that you don't have to know about XML to get anything done with XML. That still holds true. Although an XML Web service returns XML, the controls, classes, and tools in Visual Studio .NET natively read and write XML, so you don't need to understand the XML part—you only need to understand how to get the data from the XML part.

There are probably 50 ways to consume a Web service from any number of client applications. You can use Visual Basic 3, Visual Basic 4, Visual Basic 5, Visual Basic 6, Delphi, FLASH, C++, PowerBuilder—you name it. Because the implementation simply returns text in XML format, anything that can read text can consume a Web service. That's the whole point of a Web service: It can be created and consumed by anything.

The rest of the day focuses on four ways to consume a Web service, which I think are 99.9% of what you'll ever run into. You learn how to consume a Web service from

  • An ASP.NET application

  • A Windows Forms application

  • A console application

  • An HTML page from client-side VBScript/JavaScript

Consuming a Web Service from an ASP.NET Application

The idea behind a Web service is to be able to access application components from any type of application anywhere. To see how this works, you're going to create a new ASP.NET Web application and call the three methods of the firstService application you just finished creating.

To start, open a new instance of Visual Studio .NET and create a new ASP.NET Web application named firstServiceWebConsumer in either Visual Basic .NET or C#, whichever language you prefer (see Figure 13.7). Click the OK button to create your new project.

Figure 13.7. Creating the Web service Web consumer.


After the project is created, you must reference the Web service you created earlier. This is accomplished in a similar manner to adding a reference to an assembly.

If you right-click the References node on the Solution Explorer, you have two options: Add Reference and Add Web Reference, as Figure 13.8 demonstrates. Select Add Web Reference from the contextual menu.

Figure 13.8. The Add Reference option in the Solution Explorer.


The Add Web Reference dialog pops up as shown in Figure 13.9.

Figure 13.9. The Add Web Reference dialog box.


The Add Web Reference dialog has several features. You can search the UDDI directory that was discussed earlier today. You can also search the Test Microsoft UDDI Directory. Microsoft has several Web services, such as the Knowledge Base search service, that you can test and implement in your own applications.

Because you don't want to do either of the available options, you must type the URL of the Web service you want to consume. In the Address box, type

http://localhost/fistService_vb/Service1.asmx

or

http://localhost/fistService_cs/Service1.asmx

depending on what you named your project earlier.

After you type in the address and press Enter, you should see something similar to Figure 13.10, which is the Service Help Page for the Web service named Service1.asmx.

Figure 13.10. Service Help page for Service1.asmx.


From here, you have the same capabilities that you did when you ran the Web service from the project earlier. You can view the service descriptions, invoke the Web services, and inspect additional information that you might need about implementing the Web service. To add this reference to your project, click the Add Reference button. Your Solution Explorer should now look like Figure 13.11.

Figure 13.11. Solution after adding a Web reference for Service1.asmx.


Tip

When you add the Web reference, the Web server name where the Web service is located shows up in the Solution Explorer under Web References. You can right-click on the name of the Web server (in this case, localhost) and change it to something more familiar or recognizable.


Now that you've added the Web reference, you can reference the methods in the Web service as you would any other method in a class. Remember that the WSDL file can be considered a type library for a Web service. In .NET, the term proxy is to refer to the metadata of an object, but not necessarily the object itself. When you add a reference to a Web service created in .NET, a WSDL proxy is added to your solution. The WSDL file contains all the type information that your application needs to invoke the Web service.

For this exercise, the Web service and consumer are on the same machine. This might or might not be true in real life. Either way, you should always use the actual DNS name or IP address of the Web service when you add it through the Add Web Reference dialog. That way, if you move the consumer to another machine, the Web Reference is still valid.

To access the methods in the newly added Web reference, follow these steps to prepare the default WebForm1.aspx page. The outcome should look something like Figure 13.12.

1.
Drag a Label control onto the form and set the Text property to Customer ID.

2.
Drag a TextBox control to the right of the Label control and change its Name property to CustomerID.

3.
Drag a CommandButton control to the form, change its Name property to GetCustomer and change the Text property to Get Customer.

4.
Drag a CommandButton control to the form, change its Name property to GetCustomers, and change the Text property to Get Customers.

5.
Drag a DataGrid control to the form. You can right-click the DataGrid and select AutoFormat from the contextual menu to select a nice color scheme.

Figure 13.12. Webform1 after adding new controls.


Now that you've added the controls and the form is all set, double-click the Get Customer button to get to the code-behind for the GetCustomer click event.

In Listing 13.2, you take the CustomerID information from the CustomerID TextBox and pass it to the GetCustomer method of the Web service.

Listing 13.2. Code-Behind for the GetCustomer Click Event
Private Sub GetCustomer_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles GetCustomer.Click

    Dim ws As New localhost.Service1()

    DataGrid1.DataSource = ws.GetCustomerByID(CustomerID.Text.Trim)

    DataGrid1.DataBind()

End Sub


private void GetCustomer_Click(object sender, System.EventArgs e)
{
   localhost.Service1 ws = new localhost.Service1();

   DataGrid1.DataSource = ws.GetCustomerByID(CustomerID.Text.Trim().ToString());

   DataGrid1.DataBind();
}

The code in Listing 13.2 is amazingly simple. All you need to do is create an instance of the Web service reference, and then call the method on the reference like any other class. Because the DataGrid control natively reads a DataSet and data returned from an XML Web service is read as either XML or a DataSet, you can just set the DataSource property of the DataGrid to the return value of the Web service, and the DataGrid understands the return value. After you set the DataSource of the DataGrid, you can call the DataBind method of the DataGrid and the data appears in the grid.

Listing 13.3 has the code you should add to the GetCustomers click event, which returns all the customers in the Customers table.

Listing 13.3. Code-Behind for the GetCustomers Click Event
Private Sub GetCustomers_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles GetCustomers.Click

    Dim ws As New localhost.Service1()

    DataGrid1.DataSource = ws.GetCustomers()

    DataGrid1.DataBind()

End Sub


private void GetCustomers_Click(object sender, System.EventArgs e)
{
   localhost.Service1 ws = new localhost.Service1();

   DataGrid1.DataSource = ws.GetCustomers();

   DataGrid1.DataBind();

}

Now that you've written the code for both Click events, you can press F5 to run the application.

When WebForm1 is in the browser, click the Get Customers button. Your results should look like Figure 13.13.

Figure 13.13. Results of the GetCustomers method.


Next, enter the CustomerID ALFKI into the TextBox control and click Get Customer. You should see something similar to Figure 13.14.

Figure 13.14. Results of the GetCustomer method.


Just like that, you've consumed data from a Web service. You've also seen how to pass a variable to a method in a Web service. It's no different than working with any other object, except that methods can be called on a remote server and data is retrieved with no special settings on your part. It's truly a powerful tool.

If you don't want to simply bind the data to a DataGrid, you can save the data to a file, load it into a stream, or bind it to other controls.

Consuming an XML Web Service from a Windows Forms Application

Consuming a Web service from a Windows Forms application is identical to consuming a Web service from an ASP.NET Web application. You need to add a Web reference to the project, create an instance of the proxy class, and call the methods that you need to consume.

To test this, create a new Windows Forms application and name it firstServiceFormsConsumer_vb or firstServiceFormsConsumer_cs, depending on the language you're coding in.

When the project is loaded, add a ComboBox and a RichTextBox to the default form1. Change the Name property of the ComboBox to cbo, and change the Name property of the RichTextBox to rtb.

Next, add the Web reference to the project exactly as you did for the ASP.NET Web application. Right-click the References node in the Solution Explorer, select Add Web Reference from the contextual menu, and enter the URL to the ASMX file.

When that's done, you can write some code to consume the Web service. You're going to load the return data from the Web service into a DataSet, and then bind the DataSet to the ComboBox. On the SelectedIndexChanged event of the ComboBox, you'll call the GetCustomerByID Web service, and pass the Text property of the ComboBox to the method.

Listing 13.4 shows the code you should add to both the Form_Load event and the SelectedIndexChanged event of the ComboBox.

Listing 13.4. Code for Windows Forms Events to Consume Service1.asmx
Private Sub Form1_Load(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles MyBase.Load

    Dim ws As New localhost.Service1()

    Dim ds As DataSet

    ds = ws.GetCustomers

    cbo.DisplayMember = "CustomerID"

    cbo.DataSource = ds.Tables(0)

End Sub

Private Sub cbo_SelectedIndexChanged(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles cbo.SelectedIndexChanged

    Dim ws As New localhost.Service1()

    Dim ds As DataSet

    ds = ws.GetCustomerByID(cbo.Text)

    rtb.Text = ds.GetXml

End Sub


private void Form1_Load(object sender, System.EventArgs e)
   {
      localhost.Service1  ws =  new localhost.Service1();

      DataSet ds;

      ds = ws.GetCustomers();

      cbo.DisplayMember = "CustomerID";

      cbo.DataSource = ds.Tables[0];
   }

private void comboBox1_SelectedIndexChanged
      (object sender, System.EventArgs e)
   {
      localhost.Service1  ws =  new localhost.Service1();

      DataSet ds;

      ds = ws.GetCustomerByID(cbo.Text);

      rtb.Text = ds.GetXml();
   }

If you run the application by pressing the F5 key, the Form_Load event calls the Web service and grabs all the customers. The databinding used in the form load is the same code you used two days ago when you wrote the DataAccess application. Because the return type from the Web service is a DataSet, you can just set the DataSet equal to the data coming back from the Web service. After the ComboBox is bound, the SelectedIndexChanged event fires and the GetCustomerID method of the Web service proxy is invoked each time you select another item. The GetXml method that you learned about yesterday loads the XML string into the RichTextBox control.

Your output should look something like Figure 13.15.

Figure 13.15. Consuming the Web service from Windows Forms.


Each time you select another CustomerID from the ComboBox, the XML changes.

Because both methods from the Web service are returning a DataSet, you have the full power of the DataSet class at your fingertips. You can save the XML to a file, load the XML into an XMLDocument object, or use an XMLTextReader to read through the nodes. Everything you learned yesterday about working with XML can be applied to the results from an XML Web service.

If the return type is a string, integer, or even a serialized class, you can handle it accordingly. If a client is non-.NET, the data is just XML, so it can be treated like an XML file.

Consuming a Web Service from VBScript

There are a few ways to invoke a Web service from VBScript or JavaScript. A DHTML behavior is available for download from the Web Workshop on MSDN, or you can simply use XMLHTTP to call the Web service asynchronously.

To test it, add a new HTML form to the ASP.NET Application you were working with earlier.

On the HTML form, add an HTML TextBox, an HTML Button, and two HTML Labels. The HTML Labels are actually HTML DIV elements, so you can interact with them from the client.

Set the ID and NAME property of one of the Labels to customerID and set the other to companyName.

Your HTML form should look something like Figure 13.16.

Figure 13.16. Creating the HTML form to consume a Web service.


Next, double-click on the Button1 that was added, and you're taken to the client-side HTML Button1_OnClick subprocedure. Add the code in Listing 13.5 to the onclick event for Button1.

Listing 13.5. Client VBScript Code for Calling a Web Service
Sub Button1_onclick

  Dim strResults, objXML, strURL, objNodes

  set objXML = CreateObject("Microsoft.XMLDOM")

  objXML.async = false

  strSQL = "http://localhost/firstService_vb/Service1.asmx/
            GetCustomerByID?ID=" & Text1.value

  objXML.load(strSQL)

  objNodes =  objXML.xml

  set objNodes = objXML.selectNodes("//NewDataSet")

  For Each objNode In objNodes
    customerID.innerText  = objNode.selectSingleNode("CustomerID").text
    companyName.innerText  = objNode.selectSingleNode("CompanyName").text
  Next

  set objNodes = Nothing
  set objXML = Nothing

End Sub

In the VBScript, you create an XMLDOM object and call its Load method. The Load method takes the URL of the Service1.asmx file, and uses HTTP-GET to pass the ID parameter in the query string to the Web service. Because the caller isn't a .NET client, it's script, the DOM (document object model) can simply consume the XML data as an XML document and use SelectNodes to get the Nodes collection it's looking for. In the GetCustomerByID method, you didn't specify a name for the DataSet, so the parent node is named the default: NewDataSet.

The XML being parsed is

<?xml version="1.0" encoding="utf-8" ?>
<DataSet xmlns="http://tempuri.org/">
<xs:schema id="NewDataSet" xmlns=""
     xmlns:xs="http://www.w3.org/2001/XMLSchema"
     xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="Customers">
<xs:complexType>
<xs:sequence>
  <xs:element name="CustomerID" type="xs:string" minOccurs="0" />
  <xs:element name="CompanyName" type="xs:string" minOccurs="0" />
  <xs:element name="ContactName" type="xs:string" minOccurs="0" />
  <xs:element name="ContactTitle" type="xs:string" minOccurs="0" />
  <xs:element name="Address" type="xs:string" minOccurs="0" />
  <xs:element name="City" type="xs:string" minOccurs="0" />
  <xs:element name="Region" type="xs:string" minOccurs="0" />
  <xs:element name="PostalCode" type="xs:string" minOccurs="0" />
  <xs:element name="Country" type="xs:string" minOccurs="0" />
  <xs:element name="Phone" type="xs:string" minOccurs="0" />
  <xs:element name="Fax" type="xs:string" minOccurs="0" />
  </xs:sequence>
  </xs:complexType>
  </xs:element>
  </xs:choice>
  </xs:complexType>
  </xs:element>
  </xs:schema>
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"
           xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
<NewDataSet xmlns="">
<Customers diffgr:id="Customers1" msdata:rowOrder="0">
  <CustomerID>ALFKI</CustomerID>
  <CompanyName>Alfreds Futterkiste</CompanyName>
  <ContactName>Maria Anders</ContactName>
  <ContactTitle>Sales Representative</ContactTitle>
  <Address>Obere Str. 57</Address>
  <City>Berlin</City>
  <PostalCode>12209</PostalCode>
  <Country>Germany</Country>
  <Phone>030-0074321</Phone>
  <Fax>030-0076545</Fax>
</Customers>
</NewDataSet>
</diffgr:diffgram>
</DataSet>

After the XML is in the DOM, you can specify what nodes you want to display. Using SelectSingleNode retrieves the correct node, and enables the data to be displayed in the DIV, as the following code demonstrates:

customerID.innerText  = objNode.selectSingleNode("CustomerID").text

If you enter different CustomerIDs from the Northwind database and click the button, the data shows up. Also, notice that the browser doesn't refresh. This processing is being done asynchronously, so the client side never needs to refresh the browser.

This capability using Web services and client-side script opens up a ton of possibilities for writing great browser-based applications.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.67.48