Professional ASP.NET 1.1 [Electronic resources]

Alex Homeret

نسخه متنی -صفحه : 244/ 153
نمايش فراداده

Using the Proxy Class

If you build and use the proxy class in Visual Studio .NET, you can see (through statement completion) that the class contains additional methods and properties beyond the methods used in the web service. For example, the

Fibonacci class supported a

GetSeqNumber method. However, if you examine the proxy for

Fibonacci in Visual Studio .NET, you'll see several other methods and properties that

Fibonacci supports. This is because the

Fibonacci proxy class inherits these methods and properties from a base class.

Note

A proxy inherits from

SoapHttpClientProtocol , which inherits from

HttpWebClientProtocol , which in turn inherits from

WebClientProtocol .

Let's examine some of the common methods and properties we might use.

Controlling Timeout

We still need to write applications so that they behave correctly when the web service is not performing correctly. For example, the network connection between the provider and the consumer of the service could become saturated so that responses start to take too long. Requests are issued, and the consumer of the service simply waits until the request times out. The default timeout for a request from our proxy is ninety seconds.

The following VB.NET code illustrates a simple

Add Web service that performs slowly due to a call to

Thread.Sleep(20000) that forces the thread to wait 20 seconds before continuing:

<%@ WebService Class="Timeout" %>

Imports System.Threading

Imports System.Web.Services

Public Class Timeout

<WebMethod()> Public Function Add(a As Integer, b As Integer) As Integer

Thread.Sleep(20000)

Return a + b

End Function

End Class

This code introduces false latency into the application. However, if this latency were real, the client using the web service would probably not want to wait 20 seconds for a response.

One of the inherited properties in the proxy class is

Timeout . If you use a proxy named

Timeout for the

Add Web service, you could write the following VB.NET code to time the request out if the web service did not respond within five seconds:

<Script runat="server">

Public Sub Page_Load(sender As Object, e As EventArgs)

Dim example As New Timeout()

example.Timeout = 5000

Try

lblResult.Text = example.Add(4,5)

Catch err As Exception

lblResult.Text = err.Message

End Try

End Sub

</Script>

The result of 4 + 5 is: <asp:label id="lblResult" runat="server" />

This code demonstrates the use of a

Try...Catch block surrounding a web service call. We'll talk more about handling web service exceptions later in the chapter. A timeout is an exception, and if it's not handled, an error will be generated.

Using the

Timeout property of the proxy ensures that the application won't wait for a slow web service. Another inherited property of the proxy,

Url , allows you to set the end-point URL that the proxy sends requests to.

Setting the URL

When you build a proxy from a WSDL document generated by ASP.NET, the default end-point of the service is already provided. Here's a snippet of the WSDL for the Fibonacci Web service:

<service name="Fibonacci">
<port name="FibonacciSoap" binding="s0:FibonacciSoap">

<soap:address location="http:// ... /Fibonacci_cs.asmx" /> </port> </service>

The

location attribute defined in

<soap:address/> names the end-point to which SOAP calls are sent. The proxy that is generated uses this setting. As an example, consider the constructor of the VB.NET code:

Public Sub New()
MyBase.New

Me.Url = "http://localhost/WebServices/Fibonacci_cs.asmx" End Sub

The equivalent C# code:

public Fibonacci() {

this.Url = "http://localhost/WebServices/Fibonacci_cs.asmx"; }

Both constructors set the

Url property to the value of

location in the WSDL. Although the value is 'pre-configured' for you in the proxy, you can either remove this setting or reset the value of the property at runtime using the

Url property of the proxy.

As you can reset the

Url that the proxy uses, you can dynamically choose the web service you want to use, or use a common proxy for multiple web services. For example, if you built an e-commerce site and wanted to use web services for credit card validation, you could use the

Timeout and the

Url properties together. If a given call to a service timed out (for example, a call to a Credit Card Web service), you could write code that changes the

Url to a web service provided by another vendor and call that backup service. Of course, this assumes that either the proxy supports all these services, or all the services implement a common web service API.

Proxy Web Server Access

By default the web service proxy will use the settings configured for Internet Explorer to access the Internet. However, you can set your own proxy using the

Proxy property.

To use the

Proxy property, you need to set its value to a class that implements

IWebProxy , such as the

WebProxy class found in the

System.Net namespace. For example, if the local network requires you to use a proxy server named

AcmeCoProxy through port 80, you could write the following VB.NET code:

<%@ Import Namespace="System.Net" %> <Script runat="server"> Private Sub Page_Load(sender As Object, e As EventArgs)

Dim fibonacci As New Fibonacci()

Dim webProxy As New WebProxy("AcmeCoProxy", 80)

Fibonacci.Proxy = webProxy

lblResult.Text = fibonacci.GetSeqNumber(6) End Sub The value of the 6th element in the Fibonacci series is: <asp:label id="lblResult" runat="server"/>

Calls made through the

Fibonacci proxy object are now routed to the

AcmeCoProxy server on port 80. The Web proxy server then issues the request and returns the result to the caller. If the Web proxy server requires credentials, these can be set as part of the

System.Net.WebProxy class.

Maintaining State

ASP.NET Web services use HTTP as the transport protocol for messages. Additional transport protocols can be used to route SOAP, including SMTP and UDP, but HTTP will be the most commonly used protocol. Accordingly, the proxy provides with access to common HTTP protocol features, such as cookies.

Just as you would with a browser-based application, you can use HTTP cookies to pass additional data along with SOAP messages. The most common use of cookies in an ASP.NET Web service would be to maintain a

Session on the server that is providing the web service. For example, the following web service (written using VB.NET) uses

Session state to retain values on the server:

<%@ WebService Class="SessionStateExample" %>

Imports System.Web.Services

Public Class SessionStateExample

Inherits WebService

<WebMethod(EnableSession:=true)> _

Public Function SetSession(key As String, item As String)

Session(key) = item

End Function

<WebMethod(EnableSession:=true)> _

Public Function GetSession(key As String) As String

Return Session(key)

End Function

End Class

This ASP.NET Web service has two functions defined as web services:

SetSession : Allows you to pass a key and item (both strings) and uses the key value to create an entry in

Session for the value

GetSession : Allows you to pass the key and retrieve the result of the item stored for that key

The

WebMethod attribute explicitly enables Session (which is not enabled, by default) by setting

EnableSession:="true" for each of the methods. The server will issue a Session cookie to the caller that contains a unique

Session ID. On each subsequent request, the caller (in this case the web service proxy) presents the cookie, and the server is able to load the appropriate

Session data.

There are two caveats for using HTTP cookies with the proxy:

If you create a proxy for a web service, and the web service requires the use of HTTP cookies, you need to explicitly support HTTP cookies within our proxy. This is done by creating an instance of a

CookieContainer class and assigning that instance to the proxy's

CookieContainer property.

If you intend to maintain state through the use of ASP.NET session state within the web service, you need to re-present the HTTP cookie on each subsequent use of the proxy by your application. The

Cookie that the proxy receives is only valid for the life of the proxy. When the proxy instance goes out of scope or is destroyed, the cookie is lost and on subsequent requests you no longer have access to the Session (since you no longer have the Session cookie to send to the server).

The following VB.NET code illustrates both these caveats:

<Script runat="Server">
Public Sub Page_Load(sender As Object, e As EventArgs)

Dim sessionExample As New SessionStateExample()

sessionExample.SetSession("name", "rob")

lblSession1.Text = sessionExample.GetSession("name") End Sub </Script> <Font face="arial"> Value: <asp:label id="lblSession1" runat="server"/> </Font>

In the

Page_Load event handler, we create an instance of

SessionStateExample and create a new Session on the web service by calling

SetSession . We then retrieve the value by calling

GetSession("name") . In this case, no value is returned, because the proxy is not using HTTP cookies and so

lblSession1 would not contain a value.

Supporting Cookies within a Web Service Proxy

To enable cookie support within the web service proxy, you need to create a

CookieContainer . Here is the fixed VB.NET code:

<%@ Import Namespace="System.Net" %> <Script runat="Server"> Public Sub Page_Load(sender As Object, e As EventArgs) Dim sessionExample As New SessionStateExample()

Dim cookieContainer As New CookieContainer()

sessionExample.CookieContainer = cookieContainer sessionExample.SetSession("name", "rob") lblSession1.Text = sessionExample.GetSession("name") End Sub </Script> <Font face="arial"> Value: <asp:label id="lblSession1" runat="server"/> </Font>

Here, we first import the

System.Net namespace, which contains the necessary

CookieContainer class. Then, within the

Page_Load event handler we add two lines of code to create an instance of the

CookieContainer class and set that instance to the

CookieContainer property of the web service proxy. When this code is executed, we get the desired result. The

GetSession call returns the value set by

SetSession .

Although this is a simple example, it effectively illustrates how to maintain state through the use of an HTTP cookie using a web service proxy. Let's go one step further.

Persisting the Web Service Cookie for Multiple Requests

Since the proxy does not persist the Session cookie, to use Session state in your web service across multiple requests, you'd need to do your own cookie persistence. Take the following VB.NET example:

<%@ Import Namespace="System.Net" %>
<script runat="server">
Public Sub Page_Load(sender As Object, e As EventArgs)
Dim sessionExample As New SessionStateExample()
Dim cookieContainer As New CookieContainer()

Dim sessionCookie As Cookie

Dim cookieCollection As New CookieCollection() sessionExample.CookieContainer = cookieContainer

sessionCookie = CType(session("sessionCookie"), Cookie)

If (IsNothing(sessionCookie)) Then

sessionExample.SetSession("name", "rob")

cookieCollection = sessionExample.CookieContainer.GetCookies( _

New Uri("http://localhost"))

Session("sessionCookie") = cookieCollection("ASP.NET_SessionId")

Else

sessionExample.CookieContainer.Add(sessionCookie)

End If lblSession1.Text = sessionExample.GetSession("name") End Sub </script> <Font face="arial"> Value: <asp:label id="lblSession1" runat="server"/> </Font>

This is a more advanced example that demonstrates how you can store the web service's Session cookie in Session state with the web application that is using the web service. The code uses two new local variables,

sessionCookie and

cookieCollection , to store the web service's Session cookie.

The code tries to retrieve a value for

sessionCookie by attempting to access a local Session variable. The code then determines if

sessionCookie references an instance of a

Cookie . If it does not, it walks through the procedure of calling the proxy's

SetSession method and then stores the web service's Session cookie. Alternatively, you could simply add the

sessionCookie to the existing proxy's

CookieContainer and call the

GetSession method. We've encapsulated all of this work in one ASP.NET page, but it could just as easily be applied to an entire web application, which would allow us to use ASP.NET Session state for web services across an application.

Let's look at another feature that ASP.NET Web services make easy – converting any web site into a web service.