Chapter 14. Web Services

Normal web pages allow interaction between the client browser and the web server hosting the web page. Many businesses, however, need to provide information not to users, but to other programs.

For example, Amazon.com has a service that allows applications to send in the ISBN of a book and get back information about the publisher, sale price, sales rank, and so forth. This service has no user interface: it is a way for your program to interact with their data. Such a service, providing information with no user interface, using standard web protocols, is called a web service.

Platform Independence

Unlike previous technologies for distributed computing (such as DCOM), web services make it unnecessary for both ends of the connection to be running the same operating system or to be programmed in the same language. For example, the server code might be written in VB.2005 on Windows 2000 while the client is a C++ program running on a Unix machine, or vice versa. In other words, while previous technologies required that the client and server be tightly coupled, web services permit them to be loosely coupled.

All that is necessary is that both server and client support the industry standard protocols HTTP, SOAP, and XML. HTTP is the protocol used by the Web. SOAP (Simple Object Access Protocol) is a lightweight, object-oriented protocol based on XML that, in turn, is a cross-platform standard for formatting and organizing information.

How Web Services Work

Microsoft has used web services to mimic RPC (remote procedure calls). You ask for an “object” from a web service, and what you get back provides the public interface to an object running on the web service’s server. You can interact with that object, calling methods and examining or setting properties. In this model, web services allow an object on the server to expose program logic to clients over the Internet. Clients call exposed methods on the web service using standard Internet protocols.

Typically, both ends of the connection communicate using SOAP messages (see the sidebar "SOAP“), which consist of self-describing, text-based XML documents.[*]

Creating a Web Service

There are two broad aspects to web service development: creating the web service and consuming the web service. You’ll start by creating a simple web service that provides a simulated stock information service. Your web service will expose two methods:

    Function GetName(stockSymbol As String) as String
    Function GetPrice (stockSymbol As String) as Float

Tip

If this web service were an actual production program, the data returned would be fetched from a live database. In order not to confuse web service issues with data access issues, the data in this chapter will be stored in a two-dimensional array of strings.

Begin by creating a new web site named StockPriceWebService. Be sure to click on ASP.NET Web Service in the templates window, as shown in Figure 14-1.

Visual Studio 2005 does a lot of the work of setting up your web service, including adding the necessary <WebService> attributes to your class, and creating a template method (HelloWorld) complete with <WebMethod> attributes. For more on attributes, see the note on attributes in Chapter 12.

Creating a web service
Figure 14-1. Creating a web service

You’ll add a two dimensional array of stock symbols with their names and fictional prices, as shown in Example 14-1.

Example 14-1. Two-dimensional array of stock symbols and prices
Dim stocks As String(,) = _
{ _
   {"MSFT", "Microsoft", "25.22"}, _
   {"DELL", "Dell Computers", "42.12"}, _
   {"INTC", "Intel", "25.50"}, _
   {"YHOO", "Yahoo!", "30.81"}, _
   {"GE", "General Electric", "37.51"}, _
   {"IBM", "International Business Machine", "91.98"}, _
   {"GM", "General Motors", "64.72"}, _
   {"F", "Ford Motor Company", "25.05"} _
}

You are now ready to create your two web methods. Web methods are exposed to web clients by tagging them with the <WebMethod> attribute. The first method, GetPrice, takes a symbol as a string and returns the price, as shown in Example 14-2.

Example 14-2. GetPrice WebMethod
<WebMethod()> _
Public Function GetPrice(ByVal StockSymbol As String) As Double
    Dim returnValue As Double = 0
    For counter As Integer = 0 To stocks.GetLength(0) − 1
        If (String.Compare(StockSymbol, stocks(counter, 0), True) = 0) Then
            returnValue = Convert.ToDouble(stocks(counter, 2))
        End If
    Next
    Return returnValue
End Function

Tip

You can imagine a two-dimensional array as an array of arrays. The first value passed into the offset operator for stocks (counter), ticks through each of the internal arrays in turn:

    stocks(counter, 0)

The second value passed in, (offset 0), picks from within the internal array. The first field (offset 0) is the stock symbol, the second symbol (offset 1) is the stock name, and the third field (offset 2) is the price:

    returnValue = Convert.ToDouble(stocks(counter, 2))

The GetName method is extremely similar, except that instead of returning a price, it returns the name of the stock, as shown in Example 14-3.

Example 14-3. GetName WebMethod
<WebMethod()> _
Public Function GetName(ByVal StockSymbol As String) As String
    Dim returnValue As String = "Symbol not found."
    For counter As Integer = 0 To stocks.GetLength(0) − 1
        If (String.Compare(StockSymbol, stocks(counter, 0), True) = 0) Then
            returnValue = stocks(counter, 1)
        End If
    Next
    Return returnValue
End Function

Notice that Visual Studio 2005 created an .asmx page, but it has only one line in it:

    <%@ WebService Language="vb" CodeBehind="~/App_Code/Service.vb" Class="Service"
    %>

This determines that the code for the web service will be in the code behind (Service.vb) file. The Class attribute created by Visual Studio 2005 ties this .asmx page to the class defined in Service.vb.

Tip

Your new class derives from WebService. While this is the most common way to create a web service, it is optional. However, doing so does give you access to a variety of useful ASP.NET objects: Application and Session (for preserving state); User (for authenticating the caller); and Context (for access to HTTP-specific information about the caller’s request, accessed through the HttpContext class).

WebMethod Properties

Each web method is preceded by the WebMethod attribute. You are free to add properties to this attribute. The following sections describe the valid WebMethod properties.

The BufferResponse Property

By default, ASP.NET buffers the entire response to a request before sending it from the server to the client. Under most circumstances, this is the optimal behavior. However, if the response is very lengthy, you might want to disable this buffering by setting the WebMethod attribute’s BufferResponse property to False. If set to False, the response will be returned to the client in 16 KB chunks.

    <WebMethod(BufferResponse:=False)>

The CacheDuration Property

Web services, like web pages, can cache the results returned to clients. If a client makes a request that is identical to a request made recently by another client, then the server will return the response stored in the cache. This can result in a huge performance gain, especially if servicing the request is an expensive operation (such as querying a database or performing a lengthy computation).

Warning

For the cached results to be used, the new request must be identical to the previous request. If the web method has parameters, the parameter values must also be identical. For example, if the GetPrice web method of the StockTicker web service is called with a value of msft passed in as the stock symbol, that result will be cached separately from a request for dell.

The CacheDuration property defines how long the response is cached, in seconds. Once the CacheDuration period has expired, a new page is sent. To set the CacheDuration for 30 seconds, you’d write,

    <WebMethod(CacheDuration:=30)>

The default value for CacheDuration is 0, which disables caching of results.

The Description Property

The WebMethod attribute’s Description property allows you to attach a descriptive string to a web method. This description will appear on the web service help page when you test the web service in a browser.

When a representation of the web service is encoded into the SOAP message that is sent out to potential consumers, the WebMethod Description property is included:

    <WebMethod(Description:="Returns the stock price for the input stock symbol.")>

The EnableSession Property

The WebMethod attribute’s EnableSession property defaults to False.

If set to True and if your web service inherits from WebService, the session-state collection can be accessed with the WebService.Session property. If the web service does not inherit from the WebService class, then the session-state collection can be accessed directly from HttpContext.Current.Session.

To see this at work, you’ll add a method that tells you how many times it has been called in the current session:

    <WebMethod(Description:="Number of hits per session.", EnableSession:=True)> _
    Public Function HitCounter() As Integer
        If Session("HitCounter") Is Nothing Then
            Session("HitCounter") = 1
        Else
            Session("HitCounter") = CInt(Session("HitCounter")) + 1
        End If
        Return CInt(Session("HitCounter"))
    End Function

Warning

Enabling session state adds additional performance overhead to the application.

Session state is implemented via HTTP cookies in ASP.NET web services, so if the transport mechanism is something other than HTTP (say, SMTP), then the session-state functionality will not be available.

The TransactionOption Property

ASP.NET web methods can use transactions, but only if the transaction originates in that web method. In other words, the web method can only participate as the root object in a transaction. This means that a consuming application cannot call a web method as part of a transaction and have that web method participate in the transaction.

The WebMethod attribute’s TransactionOption property specifies whether or not a web method should start a transaction. There are five legal values of the property, all contained in the TransactionOption enumeration. However, because a web method transaction must be the root object, there are only two different behaviors: either a new transaction is started (Required or RequiresNew) or it is not (Disabled, NotSupported, or Supported).

To use transactions in a web service, you must take several additional steps.

Add a reference to System.EnterpriseServices.dll. In Visual Studio .NET, this is done through the Solution explorer or the Project Add Reference menu item. Add the System.EnterpriseServices namespace:

    Imports System.EnterpriseServices

You must also add a TransactionOption property with a value of RequiresNew or Required to the WebMethod attribute:

    <WebMethod(TransactionOption:=TransactionOption.RequiresNew)>

If there are no exceptions thrown by the web method, then the transaction will automatically commit unless the SetAbort() method is explicitly called. If an unhandled exception is thrown, the transaction will automatically abort.

The MessageName Property

As with aux class, it is possible to have more than one method or function defined in your web service class with the same name (method overloading ). They are differentiated by their signature (the number, data type, and order of their parameters).

Unfortunately, method overloading is not supported by the standard industry protocols, so if you do overload a web method, you must provide each overloaded version with its own unique MessageName property. When the overloaded method is referred to in SOAP messages, the MessageName will be used, and not the method name.

To see the MessageName property at work, you’ll add an overloaded method named GetValue. The first overload accepts the stock name as a parameter (presumably it looks up the user’s account in the database, and returns the value of that stock). The second overload passes in not only the stock name, but also the number of shares owned. The overloaded methods are shown in Example 14-4.

Example 14-4. Overloaded versions of the GetValue WebMethod
<WebMethod(Description:="Returns the value of the users holdings " & _
               "in a specified stock symbol.", _
            MessageName:="GetValueStockInPortfolio")> _
Public Function GetValue(ByVal StockSymbol As String) As Double
    '  Code stubbed out
    Return 0
End Function

<WebMethod(Description:="Returns the value of a specified number " & _
               "of shares in a specified stock symbol.", _
            MessageName:="GetValueThisManyShares")> _
Public Function GetValue( _
ByVal StockSymbol As String, _
ByVal NumShares As Integer) As Double
    '  Code stubbed out
    Return 0
End Function

Because you overloaded GetValues in the web service class, what you see displayed is the MessageName property, as shown in Figure 14-2).

Testing Your Web Service

Before you create a client for your web service, you can have Visual Studio 2005 create a test page for you. Just run the program in the debugger, as shown in Figure 14-2.

Testing the web services
Figure 14-2. Testing the web services

Click on GetName, for example. You will be prompted to enter a stock symbol, as shown in Figure 14-3.

Testing GetName
Figure 14-3. Testing GetName

Enter a valid stock symbol (one of the symbols in the array) and the stock’s name is returned in an HTML document, as shown in Figure 14-4.

Value returned as XML
Figure 14-4. Value returned as XML

Examining the WSDL

You can examine the WSDL (Web Service Description Language) document for this web service by adding ?WSDL after the URL, as shown in Figure 14-5.

There are three things to notice in Figure 14-5. First, the URL is identical to the URL that brought up the test document, except that the string ?WSDL is appended. Second, both the GetValueStockInPorffolio and GetValueThisManyShares methods are shown (the names used in the MessageName property), but the GetValue method does not appear. The SOAP document (and thus the WSDL document) does not use the class’s method name, but rather uses the unambiguous MessageName property.

Writing the Client

To create a client that uses your new web service, create a new (normal) ASP.NET web site called StockPriceClient, as shown in Figure 14-6.

Your client will need knowledge of your web service. The easiest way to provide that knowledge is to create a web reference. Right-click on your project and choose Add Web Reference, as shown in Figure 14-7.

WSDL document
Figure 14-5. WSDL document
Creating client web site
Figure 14-6. Creating client web site

The Add Web Reference dialog will open. If you have created the web service on the same machine as the client, click on “web services on the local machine,” as shown in Figure 14-8.

Warning

If you have been using file-based web applications, you’ll need to create a virtual directory in IIS to point to the web service, for this web reference to work.

Add Web Reference
Figure 14-7. Add Web Reference
Choosing local web service
Figure 14-8. Choosing local web service

Once you click on Service, the Add Web Reference dialog will locate the service (and bring up the test page). Give your service a reference name (a name by which you can refer to it in your code) and click Add Reference, as shown in Figure 14-9.

Name and Add Reference
Figure 14-9. Name and Add Reference

When you click Add Reference, the web reference is added to your project, and reflected in the Solution explorer, as shown in Figure 14-10.

Client solution with web reference
Figure 14-10. Client solution with web reference

Switch to Design view. Enter the words Stock Ticker and highlight them. Set them to Heading 1 and center them using the toolbar controls.

Move down on the page and enter the text Please enter a stock symbol:, then drag a text box into place. Name the text box txtStockSymbol. Add a button, name it btnSubmit, and set its text to Get Stock Info. Finally, add a label (lblMsg) and set its text to blank (see Figure 14-11).

Running the Stock Ticker Client
Figure 14-11. Running the Stock Ticker Client

Double-click on the button to create an event handler. In the event handler, you’ll get the text from txtStockSymbol and send it to the GetName and GetPrice methods of your service. You’ll then format the response and put it in the output label, as shown in Example 14-5.

Example 14-5. Submit button Click event handler
Protected Sub btnSubmit_Click( _
ByVal sender As Object, _
ByVal e As System.EventArgs) Handles btnSubmit.Click
    Dim proxy As StockPriceService.Service = New StockPriceService.Service()
    Dim symbol As String = Me.txtStockSymbol.Text
    Dim stockName As String = proxy.GetName(symbol)
    Dim stockPrice As Double = proxy.GetPrice(symbol)
    Me.lblMsg.Text = "The price of " & stockName & " is " & stockPrice.ToString()
End Sub

The result is that when you put in a stock symbol and press the Get Stock Info button, the methods of the web service are called, and values are returned to your client application for display, as shown in Figure 14-11.



[*] It is also possible to communicate via HTTP-GET or HTTP-POST requests.

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

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