Consuming Data in a Web Service

for RuBoard

After the Web service has been built and exposed on the Web server, a client will typically call it by building a SOAP message and sending it to the server. However, Web services created by VS .NET by default also can be called using an HTTP-GET or POST. In this way, clients that don't support SOAP can still invoke the Web service. For example, a client can issue the following HTTP-GET to call the GetTopSellers method of the Catalog Web service:

 GET /Catalog.asmx/GetTopSellers?daysOut=  value  HTTP/1.1 Host: www.computebooks.com 

The result will be an XML document that includes the schema of the DataSet along with the serialized DiffGram encoded as follows :

 HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: length <?xml version="1.0" encoding="utf-8"?> <DataSet xmlns="www.computebooks.com/catalog">   <schema xmlns="http://www.w3.org/2001/XMLSchema">  schema  </schema>  xml  </DataSet> 

However, clients that support SOAP can build a SOAP message and expect a SOAP message in return, like those shown in Listing 19.3.

Listing 19.3 Calling the Web service. This listing shows the SOAP request and response messages that can be used with the Catalog Web service.
  Request:  POST /Catalog.asmx HTTP/1.1 Host: www.computebooks.com Content-Type: text/xml; charset=utf-8 Content-Length: length SOAPAction: "www.computebooks.com/catalog/GetTopSellers" <?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>      <GetTopSellers xmlns="www.computebooks.com/catalog">        <daysOut>  short  </daysOut>      </GetTopSellers>    </soap:Body> </soap:Envelope>  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>     <GetTopSellersResponse xmlns="www.computebooks.com/catalog">        <GetTopSellersResult>          <xsd:schema>  schema  </xsd:schema>  xml  </GetTopSellersResult>     </GetTopSellersResponse>   </soap:Body> </soap:Envelope> 
graphics/analysis.gif

You'll notice in Listing 19.3 that because document-style encoding is used in the Web service, the response message includes the XSD schema of the DataSet as well as the XML itself in the GetTopSellersResult element.

As a result, any client on any platform that can use HTTP, build the appropriate SOAP request message, and parse the SOAP response is able to call the Web service and use the data returned in the DataSet . From the ADO.NET perspective, the great thing about this architecture is that you have to work with only one type of object, the DataSet , to handle your data both internally in your data services tier and externally when you expose your data through a Web service. This simplifies the programming model and extends the reach of your applications beyond the Windows platform.

Using VS .NET

Although clients can certainly use HTTP-GET or POST or build the SOAP request message themselves , for a client using VS .NET, support is built into IDE to allow both discovery and referencing of Web services to take place. For example, assume that a fictional company called Cold Rooster Consulting wants to incorporate the ComputeBooks Catalog Web service into its Internet site to allow its customers to view the top-selling books. If the site is built with VS .NET in any of the .NET languages, Cold Rooster can do this by clicking on Add Web Reference from the context menu associated with the project in the Solution Explorer window. The resulting dialog contains an address bar that enables the developer to enter the URL of the Catalog Web service. By entering the address of the .asmx file or the .asmx file appended with the query string ?WSDL , the service will be located and the right Available References window populated , as shown in Figure 19.2.

Figure 19.2. Referencing a Web service. This dialog in VS .NET enables the developer to specify the end point of the Web service or search for it using UDDI.

graphics/19fig02.jpg

graphics/newterm.gif

If the developer doesn't know the URL of the Web service or wants to search for other Web services, he or she can click on the Microsoft UDDI link in the window on the left. The developer can then navigate to the UDDI registry to search for various Web services using the HTML interface.

What Is UDDI?

UDDI (Universal Description, Discovery and Integration) is an industry initiative with more than 250 participating companies. Located at www.uddi.org, UDDI aims to integrate business services over the Internet by promoting a common protocol to publish and connect to Web services using directories. A Web service directory or registry allows businesses to publish their Web services in a searchable database. The UDDI specification calls for four types of information to be published in the registry, including business information, service information, binding information, and specifications for services. Both Microsoft and IBM host production UDDI directories that use the same protocols and are replicated, so either can be used to find a Web service.

The Add Web References dialog includes an automatic link to the Microsoft UDDI directory. In addition, developers can download the UDDI SDK from the same site. Features of the SDK include .NET classes that enable you to programmatically search the registry and host a lightweight registry of your own for internal use. Windows .NET Server, which is scheduled to ship in 2002, will contain a UDDI server that can be used behind the firewall to create a directory just for your organization.

graphics/newterm.gif

The promise of a global directory coupled with WSDL means that development tools and custom code can be written to automatically find and use Web services without human interaction. For example, UDDI could be used to automatically locate an equivalent public Web service by searching for Web services that use the same definition (referred to as a tModel in UDDI) if the preferred Web Service isn't responding. In addition, developers can use UDDI to query for the new end point of a Web service if the call to a Web service fails because the provider of the service has changed the URL.

In either case, the developer can then click on the Add Reference button to add a Web reference to the project.

Note

Web references and the ability to call Web services can be added to any type of VS .NET project, including Windows Services, Windows Forms, console applications, and even other Web Service projects.


The result is a Web References folder in the Solution Explorer that contains a reference to the Web service. By default, the reference is named according to the Web Server contacted, although it can be changed by right-clicking on the reference and selecting Rename. You might want to rename it if the Web service may be accessed dynamically from other servers.

When the Web reference is added, VS .NET downloads the WSDL contract into the Web References folder and reverse- engineers it to build a client proxy class that can be used to invoke the Web service from within the application.

The proxy class will have the same name as the Web service ”in this case, ComputeBooksCatalog ”and exist in a namespace of the same name as the Web reference. The client proxy class enables the developer to work with the Web service as if it were any other managed class. In addition, and of particular interest to ADO.NET developers, if the Web service returns any strongly typed DataSet objects, the XSD schema for those DataSets are downloaded, and typed DataSet s (as we discussed on Day 6, "Building Strongly Typed DataSet Classes") are generated for each. This is possible because the WSDL contract contains an import element with a location attribute that references a URL, allowing VS .NET to retrieve the schema of the DataSet using the following query string:

http://server/webService.asmx?schema=DataSetName

In this way, developers can programmatically work with the XML returned as if it were a typed DataSet rather than having to parse it using XML or having to use the generic DataSet object. In the case of the Catalog Web service, the GetTopSellers method simply returns a generic DataSet object, so no additional schema can be downloaded because the Web service doesn't know ahead of time what the schema of the DataSet will look like.

Note

Obviously, developers using Web services sometimes will need to update the reference if the publisher of the service changes it. By right-clicking on the Web reference and selecting Update Web Reference, the WSDL again will be downloaded and the client proxy class will be regenerated.


The code for the client proxy class doesn't appear in the Solution Explorer (except for in the Class view, which in this case shows the ComputeBooksCatalog class). However, you can view the class (and modify it if you're careful) by clicking on Show All Files in the Solution Explorer or looking in the project folder.

Although beyond the scope of this book, the client proxy class exposes methods for each Web method exposed by the Web service (such as GetTopSellers ). In addition, it is derived from the SoapHttpClientProtocol class in the System.Web.Services.Protocols namespace, which contains methods and properties that enable finer-grained control of communication with the Web service such as Url , Timeout , and Proxy .

Note

In addition to the synchronous versions of the methods exposed by the Web service, the client proxy class also exposes begin and end methods for each method (for example, BeginGetTopSellers and EndGetTopSellers ). These methods can be used to call the Web service asynchronously using asynchronous delegates. In this way, you can call the Web service on a separate thread to enable the user to continue working. For more information on asynchronous delegates, see the online documentation.


Because VS .NET does so much work for the developer, actually calling the Web service is trivial. All the developer needs to do is to create an instance of the proxy class and then call the method, as would be done with any other component.

graphics/newterm.gif

However, in ASP.NET, one of the particularly effective strategies you can use to encapsulate the call to a Web service involves using a Web User Control.

Simply put, a Web User Control is an ASP.NET page with an .ascx extension that can be embedded in regular ASP.NET pages or other Web User controls. This architecture provides a great deal of flexibility because it enables developers to create controls that abstract specific functionality to be included on multiple pages. Using controls also enables developers to collaborate on a single Web site more easily by allowing individual user controls to be separately developed and then associated on a single page. Web User Controls can also be designed graphically in the VS .NET IDE in the same way as ASP.NET pages.

A Web User Control is added to an ASP.NET site by right-clicking on the project in the Solution Explorer and choosing Add Web User Control. In the code-behind file for the control, the class that is created is derived from the UserControl class in the System.Web.UI namespace. This class is ultimately derived from the System.Web.UI.Control class from which the Page class is also derived. As a result, the way that you code a Web User Control is basically the same as the way you code a regular ASP.NET page. For example, you can place code in the Load event of the control to initialize any child controls contained on the control. Listing 19.4 shows the code for the TopBooks Web User Control (minus the designer generated code) that Cold Rooster Consulting might use to encapsulate the call to the ComputeBooks Catalog Web service.

Listing 19.4 Using a Web User Control. This is the code for the TopBooks.ascx.cs file that Cold Rooster Consulting uses to display the returned data from the Catalog Web service.
 namespace ColdRooster {        using System;        using System.Data;        using System.Drawing;        using System.Web;        using System.Web.UI.WebControls;        using System.Web.UI.HtmlControls;        using ColdRooster.computebooks;         /// <summary>        /// TopBooks User Control        /// </summary>        public abstract class TopBooks : System.Web.UI.UserControl        {         protected System.Web.UI.HtmlControls.HtmlGenericControl lblMessage;         protected System.Web.UI.WebControls.DataList dlBooks;         private void Page_Load(object sender, System.EventArgs e)         {            // Put user code to initialize the page here            // Call the Catalog web service            ComputeBooksCatalog cat = new ComputeBooksCatalog();            cat.Timeout = 5000; //timeout to 5 seconds            DataSet ds = new DataSet();            try            {              ds = cat.GetTopSellers(30);               // bind to the DataList              dlBooks.DataSource = ds.Tables[0];              dlBooks.DataBind();            }            catch (Exception ex)       {              // cannot get the books, not a critical error              this.Visible = false;              logError(ex);            }       }          private void logError(Exception e)          {             // write this to a log for later inspection          }        } } 
graphics/analysis.gif

The interesting aspect of Listing 19.4 is, of course, the call to the Catalog Web service itself in the Page_Load method. You'll notice that because a Web reference exists after the namespace is imported near the beginning of the page, the method simply needs to instantiate a new ComputeBooksCatalog object before calling its GetTopSellers method. However, before doing so, it uses the Timeout property of the proxy class to timeout the call to the method if the response time exceeds five seconds. In this way, the page will be assured to load relatively quickly even if the Web service doesn't respond. If it doesn't, the control's Visible property is set to false so that the control doesn't display at all and the exception is logged for later inspection.

After the DataSet object is returned from the GetTopSellers method, it's bound to a DataList control by setting the DataSource property to the first table in the collection and calling the DataBind method.

When the DataBind method is called, the DataTable is bound to the items in the DataList control as shown in Listing 19.5.

Listing 19.5 Data binding in a Web User Control. This listing shows the entire text of the TopBooks.ascx file that binds the results of the Web service to a DataList control.
 <%@ Control Language="c#" AutoEventWireup="false" Codebehind="TopBooks.ascx.cs"   Inherits="ColdRooster.TopBooks"   TargetSchema="http://schemas.microsoft.com/intellisense/ie5"%> <%@ OutputCache Duration="43200" VaryByParam="none" %> <LINK rel="stylesheet" type="text/css"   href="http://www.coldrooster.com/customer.css"> <b class="bookList">Most Populate Computer Books</b> <br> <span id="lblMessage" runat="server" class="bookList">  <asp:DataList id=dlBooks runat="server" CssClass="bookList">    <ItemTemplate >      <a href='<%# DataBinder.Eval(Container.DataItem , "Url") %>'        target=_blank>        <%# DataBinder.Eval(Container.DataItem , "Title") %></a><br>    </ItemTemplate>  </asp:DataList> Brought to you by <a href="http://www.computebooks.com">ComputeBooks</a> </span> 
graphics/analysis.gif

You'll notice in Listing 19.5 that the HTML contained in a Web User Control needn't contain the HTML and BODY tags that you would find in a typical ASP.NET page. This is the case because the control will be embedded at runtime in the context of an existing page. In this case, the control simply contains a SPAN element that primarily includes a DataList ASP.NET Server Control.

As discussed on Day 16, "ADO.NET in the Presentation Services Tier," DataList controls can use data binding to bind to DataSet , DataReader , and DataView objects in ADO.NET. In this case, the DataBinder object is used to bind the Url and Title columns in the DataTable so that a simple list of hyperlinks is generated. Each link enables the user to navigate directly to the ComputeBooks public site in a separate browser window to view information about the book.

graphics/newterm.gif

Perhaps the most interesting aspect of Listing 19.5, however, is the use of ASP.NET page output caching. You'll notice that near the top of the page the OutputCache directive is specified and its Duration and VaryByParam attributes are set. This directive instructs ASP.NET to cache the output of the user control for 12 hours (43,200 seconds) and to do so regardless of any query string attached to the HTTP request. This has the effect of caching the call to the Web service so that it is called only twice per day regardless of the user. Obviously, this decreases the dependency on the Web service and makes the page more responsive .

To use the TopBooks user control, a page simply needs to include a Register directive that tells the page where to find the control and a tag that places the control into the page. For example, the Cold Rooster Consulting home page would include the following Register directive:

 <%@ Register TagPrefix="Cbks" TagName="TopBooks" Src="TopBooks.ascx"%> 

Then, within the body of the page, the following tag could be inserted to place the control:

 <cbks:TopBooks id="TopBooks" runat="server" /> 

The result is that when the page is processed , so, too, will the user control, and its output will be streamed into the page at the appropriate position as shown in Figure 19.3.

Figure 19.3. Web service results. This screen shot shows the Cold Rooster Consulting home page with the TopBooks user control showing the results from the Catalog Web service.

graphics/19fig03.jpg

Note

Although not an industry standard technique, there is an alternative and simpler technique you can use to return DataSet data over the Web. Within an ASP.NET page after populating a DataSet , you can set the content type of the page to "text/xml" and then write the contents of the DataSet as XML directly to the ASP.NET Response object using the WriteXml method. The client can then simply call the ReadXml method of the DataSet object and pass it the URL of the page that returns the DataSet as XML. This provides a lightweight alternative to using SOAP, although because it doesn't rely on industry standards, it's more appropriate for internal use.


Updating Data Through a Web Service

From the ground already covered today, it should be fairly obvious that updating data with a Web service is basically the reverse of the process just shown. To update data, the Web service can expose a method that accepts a DataSet object as a parameter. When invoked, this method can use the standard technique of passing the DataSet or a particular DataTable to the Update method of a data adapter and then checking for errors as we discussed on Day 12, "Using Data Adapters." More typically, the method of the Web service will simply pass the DataSet to a method in the data services tier that will actually perform the update.

Alternatively, of course, a method in a Web service or in the data services tier could simply accept more granular parameters and then populate parameter objects directly before calling the ExecuteNonQuery method of the command object.

for RuBoard


Sams Teach Yourself Ado. Net in 21 Days
Sams Teach Yourself ADO.NET in 21 Days
ISBN: 0672323869
EAN: 2147483647
Year: 2002
Pages: 158
Authors: Dan Fox

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net