Professional ASP.NET 1.1 [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Professional ASP.NET 1.1 [Electronic resources] - نسخه متنی

Alex Homeret

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید






Design Decisions

Just as there are design decisions to be made when you build a web service, there are design decisions related to how to use a web service. One of the most obvious is handling exceptions.


SOAP Exceptions


In an ideal scenario, whenever you call a web service, some type of application logic is executed performing the desired task according to the request. However, code often has bugs. SOAP takes this fact into account and defines the response that a web service should use when an error occurs. This error takes the form of a SOAP message, and it is known as a SOAP Exception.

Requests to ASP.NET Web services that generate an exception will return a SOAP exception. Within the

System.Web.Services.Protocols namespace is a class named

SoapException . Clients using .NET can wrap

try...catch blocks around calls to web services and catch SOAP Exceptions as instances of a

SoapException class. Let's look at an example. The following is a simple web service (written using VB.NET) that can generate a runtime 'divide by zero' error:


<%@ WebService Class="ExceptionExample" %>


Imports System.Web.Services


Public Class ExceptionExample

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

Return a / b

End Function

End Class


Using Visual Studio .NET or

wsdl.exe , you can build a proxy class. Let's name it

ExceptionExample , deploy it to a web application's

bin directory, and call the

ExceptionExample Web service. Using VB.NET, you could write:


<Script runat="server">

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

Dim example As New ExceptionExample()


lblDiv1.Text = example.Divide(6,2)

lblDiv2.Text = example.Divide(5,0)

End Sub

</Script>

The result of 6 divided by 2 is: <asp:label id="lblDiv1" runat="server" />

<br>

The result of 5 divided by 0 is: <asp:label id="lblDiv2" runat="server" />


If you execute this code, the statement

example.Divide(6,2) is valid, and should execute. However, the statement

example.Divide(5,0) results in a divide-by-zero error. Figure 20-8 the result:


Figure 20-8:

The code raises an unhandled exception on line 6 in our call to

Divide(5,0) . The exception that is bubbled up and displayed in the ASP.NET error page is of type

SoapException . Let's make a few modifications to the code to handle this exception:


<%@ Import Namespace="System.Web.Services.Protocols" %>


<Script runat="server">

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

Dim example As New ExceptionExample()


Try

lblDiv1.Text = example.Divide(6,2)

Catch err As SoapException

lblDiv1.Text = "Unable to compute..."

End Try


Try

lblDiv2.Text = example.Divide(5,0)

Catch err As SoapException

lblDiv2.Text = "Unable to compute..."

End Try


End Sub

</Script>

The result of 6 divided by 2 is: <asp:label id="lblDiv1" runat="server" />

<br>

The result of 5 divided by 0 is: <asp:label id="lblDiv2" runat="server" />


Unlike an ASP/VBScript combination, ASP.NET supports structured error-handling (so no more

On Error Resume Next ) thanks to the CLR. In our code we've made a few modifications to catch exceptions: we've added a namespace,

System.Web.Services.Protocols , which contains the

SoapException class and have added

try...catch blocks around the code. Now, if an exception of type

SoapException occurs, we can catch the exception and display a meaningful result.

When you run the modified code, you get the following result, as shown in Figure 20-9:


Figure 20-9:

Another design decision is whether to use SOAP headers to send additional data with the web service. In the previous chapter, we examined how to support SOAP headers on the server. Now, let's look at how to use SOAP headers with the proxy.


Using SOAP Headers


The following is a simple ASP.NET Web service (written in VB.NET) that implements a SOAP header:


<%@ WebService Class="UsingSoapHeaders" %>


Imports System.Web.Services

Imports System.Web.Services.Protocols


Public Class MySoapHeader : Inherits SoapHeader

Public Value As String

End Class


Public Class UsingSoapHeaders

Public sHeader As MySoapHeader

<WebMethod(), SoapHeader("sHeader")> _

Public Function GetValueOfSoapHeader() As String

Return sHeader.Value

End Function

End Class


Here,

GetValueOfSoapHeader returns the value of the SOAP header that the caller presents.

Described in WSDL


The information for

SimpleSoapHeader is described in the WSDL for the service, as the application using the web service will require knowledge of the

SoapHeader , in order to call the service:


<s:element name="MySoapHeader" nillable="true" type="s0:MySoapHeader" />
<s:complexType name="MySoapHeader">
<s:sequence>
<s:element minOccurs="1"
maxOccurs="1"
name="Value"
nillable="true"
type="s:string" />
</s:sequence>
</s:complexType>


This WSDL uses an XML Schema to define a SOAP header,

MySoapHeader . The proxy generator (Visual Studio .NET or

wsdl.exe ) will then create a class

MySoapHeader with a single member variable

Value .

SOAP Header Proxy


The following is the VB.NET code generated by Visual Studio .NET for the WSDL preceding the web service:

Namespace Simple
<WebServiceBindingAttribute(Name:="UsingSoapHeadersSoap")
[Namespace]:="http://tempuri.org/")>
Public Class UsingSoapHeaders
Inherits SoapHttpClientProtocol

Public MySoapHeaderValue As MySoapHeader
Public Sub New()
MyBase.New
Me.Url = "http://localhost/.../SoapHeaders_vb.asmx"
End Sub
<SoapHeaderAttribute("MySoapHeaderValue")> _
<SoapDocumentMethodAttribute("http://tempuri.org/GetValueOfSoapHeader",
Use:=SoapBindingUse.Literal,
ParameterStyle:= SoapParameterStyle.Wrapped)>
Public Function GetValueOfSoapHeader() As String
Dim results() As Object = Me.Invoke("GetValueOfSoapHeader", _
New Object(0) {})
Return CType(results(0),String)
End Function
End Class

<XmlRootAttribute([Namespace]:="http://tempuri.org/", IsNullable:=true)>

Public Class MySoapHeader

Inherits SoapHeader


Public Value As String

End Class
End Namespace


The proxy class contains a

MySoapHeader subclass, which has a member variable,

Value . The proxy class also contains a member variable,

MySoapHeaderValue , which is used to set the SOAP header.

Using the SOAP Header


Let's look at how to use this proxy, along with its SOAP header to send additional data with the web service request. The following is a simple ASP.NET page (written in VB.NET) that uses the proxy:


<%@ Import Namespace="Simple" %>


<script runat="server">

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

' Create a new instance of the UsingSoapHeaders

' proxy class used to call the remote .asmx file

Dim soapHeaderExample As New UsingSoapHeaders()


' Create a new instance of the mySoapHeader class

Dim myHeader As New MySoapHeader()


' Set the value of myHeader

myHeader.Value = "Sample Header Text"


' Set the MySoapHeader public member of the

' UsingSoapHeaders class to myHeader

soapHeaderExample.MySoapHeaderValue = myHeader


' Get the result of the call

Dim result As String

result = soapHeaderExample.GetValueOfSoapHeader()

span1.InnerHtml = result

End Sub

</script>

<font size=6>The value of the SOAP header is: <font color="red">

<span id="span1" runat="server"/></font></font>


In the

Page_Load event handler, we create a new instance of the web service proxy,

soapHeaderExample . We also create an instance of

MySoapHeader that represents the SOAP header (

myHeader ). The

Value field of

myHeader is set to

Sample Header Text .

Next, we set

myHeader to the

soapHeaderExample member variable

MySoapHeaderValue . Finally, we call the

GetValueOfSoapHeader Web service. The

MySoapHeader class instance

myHeader is serialized as a SOAP header for the message and is sent along with the request. When the call completes, the value that was sent as a SOAP header is displayed.

Using SOAP headers is easy. The WSDL of the service describes what the SOAP header is, and the proxy generation tool turns the XML description found in the WSDL into a .NET class that you can program with. SOAP headers are very powerful since they allow you to pass out-of-band data (data that is part of the request, but doesn't belong as part of the method marked as a web service). For example, to send a user ID with each request, you obviously wouldn't want to design each of the methods in the web service to accept that user ID as a parameter. It would be much easier to simply make use of a SOAP header.

This example is relatively simple, but it's enough to allow us to demonstrate how we could build some meaningful applications that use SOAP headers. Later, you'll see a real-world example of how to use SOAP headers. Specifically, you'll see how you can use SOAP headers to send authentication details with each request. Using SOAP headers for authentication is obviously a custom implementation of authentication and authorization, and so you should start by reviewing the security features that are already available.

/ 244