
C# ПІДРУЧНИКИ / c# / Hungry Minds - ASP.NET Bible VB.NET & C#
.pdfUsername and Password. These member variables can be set by applications that wish to pass this data within the SOAP header.
Once you have defined your SOAP header class, you can add it to your Web service implementation and reference it within the method declaration by adding an attribute to that declaration. Although we haven't covered the details of coding Web services and Web service methods, let's take a quick look at the basic syntax involved in this process.
The following code snippet shows the use of our AuthenticationSoapHeader class.
VB.NET:
Public Class MyWebService
Public AuthSoapHeader As AuthenticationSoapHeader
<WebMethod, SoapHeader("AuthSoapHeader")> Public
Function MyWebMethod() As Integer
C#:
public class MyWebService : WebService {
public AuthenticationSoapHeader AuthSoapHeader;
[ WebMethod, SoapHeader("AuthSoapHeader")]
public int MyWebMethod() {
}
}
In this example, we have declared a class named MyWebService that is the implementation class for our Web service. Within this class, we declare a public member variable named AuthSoapHeader, which is an instance of our custom SOAP header class. This class instance is used to set the values contained in the SOAP header.
The next line in our sample decorates the MyWebMethod method declaration with two attributes. The WebMethod attribute indicates that this will be a Web-callable method. The simple addition of this attribute causes ASP.NET to add all the additional features required to make our method callable via the Web. We will examine the WebMethod attribute in much greater detail in subsequent chapters, when we build an ASP.NET Web Service.
Otherwise, our code continues to look and function like a normal class. The SoapHeader attribute is used to specify that a SOAP header should be added to the MyWebMethod method. The parameter of this attribute is used to identify the specific header information to be added to this header and is the name of the member variable we previously declared for our SOAP header instance.
The result of this work is that a SOAP header will be added to the SOAP message that contains two SOAP header elements, the Username and Password. These elements will have values that are specified by the consumer of the Web service.
As we discussed earlier in our coverage of SOAP headers, two attributes named MustUnderstand and DidUnderstand are used with a SOAP header to indicate whether it is mandatory or optional for a recipient to process the header entry. The .NET SoapHeader class implements these SOAP attributes as two Boolean properties of the base class. Therefore, you can set these properties to the desired Boolean value, which will automatically generate the appropriate SOAP attribute when the SOAP message is generated by ASP.NET.
.NET SoapHeader attribute
As we saw in our last example, the SoapHeader attribute is used to enable support for SOAP headers on specific Web service methods that are declared with the WebMethod attribute. Specifically, the SoapHeader attribute is supplied with the name of a member variable that is an instance of our custom SoapHeader class. Technically, this syntax is

setting a property of the SoapHeader attribute, namely the MemberName property. The SoapHeader attribute supports three properties:
§MemberName
§Direction
§Required
The MemberName property of the SoapHeader attribute identifies the name of the class variable that determines the type of the SOAP header. In our example, the type of the SOAP header is obtained from the AuthSoapHeader member variable within the MyWebService class.
The Direction property of the SoapHeader attribute is used to specify in which direction the header is expected to be supplied. By default, SOAP headers are attached to method requests only and are said to be inbound to the Web service. Using this property, we can change this default behavior.
The Direction property accepts an enumeration named SoapHeaderDirection, which supports the three values described in Table 24-4.
Table 24-4: SOAP header direction enumeration
Name |
|
Definition |
|
|
|
SoapHeaderDirection.In |
|
Declares |
|
|
that the |
|
|
SOAP |
|
|
header is |
|
|
expected |
|
|
to be |
|
|
supplied |
|
|
to request |
|
|
messages |
|
|
generated |
|
|
by the |
|
|
Web |
|
|
service |
|
|
consumer. |
|
|
|
SoapHeaderDirection.Out |
|
Declares |
|
|
that the |
|
|
SOAP |
|
|
header is |
|
|
expected |
|
|
to be |
|
|
supplied |
|
|
by |
|
|
response |
|
|
messages |
|
|
generated |
|
|
by the |
|
|
Web |
|
|
service. |
|
|
|
SoapHeaderDirection.InOut |
|
Declares |
|
|
that the |
|
|
SOAP |
|
|
header is |
|
|
expected |
|
|
to be |
|
|
supplied |
|
|
by both |
|
|
the |
|
|
request |
|
|
and |

The .NET Framework exposes this functionality through the following base classes that you can derive from to create custom SOAP extensions:
§System.Web.Services.Protocols.SoapExtension
§System.Web.Services.Protocols.SoapExtensionAttribute
The SoapExtension class is the base class for all SOAP extensions. This class defines a method named ProcessMessage that is called several times at various stages of message processing. These stages are listed in Table 24-5.
Table 24-5: SOAP extension message processing stages
Name |
|
Definition |
|
|
|
BeforeSerialize |
|
During |
|
|
SoapClientMessa |
|
|
ge processing, |
|
|
this stage occurs |
|
|
after a client calls |
|
|
a Web Service |
|
|
method, but prior |
|
|
to the call being |
|
|
serialized. |
|
|
During |
|
|
SoapServerMess |
|
|
age processing, |
|
|
this stage occurs |
|
|
after the Web |
|
|
Service method |
|
|
returns results, |
|
|
but prior to those |
|
|
results being |
|
|
serialized. |
|
|
|
AfterSerialize |
|
During |
|
|
SoapClientMessa |
|
|
ge processing, |
|
|
this stage occurs |
|
|
after a client call |
|
|
to a Web Service |
|
|
method is |
|
|
serialized, but |
|
|
prior to the |
|
|
network request |
|
|
for the call is |
|
|
made. |
|
|
During |
|
|
SoapServerMess |
|
|
age processing, |
|
|
this stage occurs |
|
|
after the results |
|
|
for a Web |
|
|
Service method |
|
|
are serialized, but |
|
|
prior to the |
|
|
network response |
|
|
sending the |
|
|
results to the |
|
|
client. |
|
|
|
BeforeDeserialize |
|
During |
|
|
SoapClientMessa |
|
|
ge processing, |

For example, a SOAP extension that is applied to a Web service client could gain access to the SOAP request message at the AfterSerialize stage. To gain access to the SOAP response message, the extension would wait for the BeforeDeserialize stage to occur.
In addition to implementing the SoapExtension class, you must also derive a class from the SoapExtensionAttribute base class. You use this class to create and apply a custom SOAP extension attribute to a method. When the custom extension attribute is added to a Web service method or a proxy class method, the associated extension is invoked at the appropriate time.
So, in summary, to implement a SOAP extension, you must derive classes from the
.NET SoapExtension and SoapExtensionAttribute base classes, and then implement the code in these derived classes to intercept SOAP messages at the message processing stages you are interested in handling.
For specific examples of SOAP extensions, you can refer to the Microsoft .NET online documentation or the Visual Studio online documentation. The MSDN library also contains information about SOAP extensions in the .NET Framework.
Handling SOAP exceptions
As we have previously discussed, SOAP defines a mechanism for Web services to return a SOAP exception message in the face of a failed method call.
Handling SOAP exceptions within .NET applications (including ASP.NET applications) is a simple, straightforward process. The .NET Framework implements a class named SoapException (contained within the System.Web.Services.protocols namespace). The ASP.NET runtime converts SOAP exceptions into instances of the .NET SoapException class. This means that you can use try . . . catch blocks within your calls to Web service methods to catch SOAP exceptions. The following example illustrates how this is done:
VB.NET:
Imports System.Web.Services
Public Class MyWebService
<WebMethod()> Public Function Divide(x as Integer,
y as Integer) as Integer
Return x / y
End Function
End Class
C#:
using System.Web.Services;
public class MyWebService : WebService {
public int Divide(int x, int y) {
return x / y;
}
}
We can catch divide-by-zero exceptions that can occur when calling the Divide Web method by using code similar to the following fragment:
VB.NET:
Dim div As New MyWebService
Dim z as Integer
Try
Z = div.Divide(1, 0)
Catch err As SoapException
strError = "Web method caused an exception"
End Try
C#:
public MyWebService div = new MyWebService;
int z;
try {
z = div.Divide(1,0);
}
catch (Exception e)
{
strError = "Web method caused an exception";
}
The structured exception handling offered by the CLR makes error handling efficient and effective. All we need to do is use try . . . catch blocks to trap errors that may occur in our calls to Web service methods.
Generally speaking, you should always wrap Web service method calls in try . . .
catch blocks. Because Web method calls are at least cross-process (and typically, cross-machine or even cross-network), the possibility always exists that something within the underlying network may go wrong. Unlike local procedure calls that are within a single process, many other factors could cause a remote Web method invocation to fail. So, it's better to be safe than sorry when it comes to recognizing and handling these types of errors.
Microsoft SOAP Toolkit
As you might expect, it is entirely possible to create and consume Web services without the infrastructure and services provided by the .NET Framework and Visual Studio .NET (although it is much easier to do so with their support).
Because Web services are based on XML, HTTP, and SOAP, all we need to create or consume Web services are implementations of these technologies. This is precisely what Microsoft has done with the Microsoft SOAP toolkit.
The Microsoft SOAP toolkit supplies the technologies and tools needed to build and deploy Web services using Visual Studio 6.0 as the development environment along with the familiar COM programming model. In addition to building Web services that can run on Windows NT 4.0 SP6 and Windows 2000, you can build Web service consumers that will run on Windows 98, Windows ME, Windows NT 4.0 SP6, or Windows 2000 SP1.
The toolkit is a free and fully supported SDK that you can download from the MSDN Web site. For those of you who cannot deploy .NET or wish to address legacy platforms with Web services, the Microsoft SOAP Toolkit will prove to be a valuable resource for you.
Although we won't go into great detail about the toolkit here (after all, the subject of this book is ASP.NET), we will briefly discuss the features of the toolkit in case you ever have a need to use it. If that happens, you will want to refer to the documentation that comes with the toolkit for more-detailed information on system requirements, installation instructions, code samples, and the like.
If you are using the ISAPI listener, Web service message processing is automatic. When an incoming SOAP request is detected, the ISAPI listener is invoked to handle the message. The ISAPI listener loads the WSDL and WSML files, executes the request, and returns the results in a response message. In this scenario, you only need provide the WSDL and WSML files.
If you are using the ASP listener, you must create an ASP page that uses the SOAPServer COM component to process incoming Web request messages.
Note Both the ISAPI and ASP listeners use the SOAPServer component. So, regardless of listener choice, the SOAP messages are handled identically (once the SOAPServer component receives the request).
The SOAPServer component enables Web service request messages to call methods on COM components. The component exposes several properties and methods that permit an ASP page to pass a Web service request to the component for execution (via the request stream) and supply the results to the caller (via the response stream). Using this component, the ASP page does not have to understand how to process SOAP messages.
To use the SOAPServer component, you specify the WSDL and WSML documents as input arguments to the initialization method. This allows the component to create the mappings between Web service requests and COM method calls.
After you have initialized the SOAPServer object, you can call its invoke method, passing the ASP input stream and output stream as arguments to the method. When you call the invoke method on the SOAPServer object, the following steps occur:
1.The SOAPServer object deserializes the SOAP request message supplied to it via the invoke method.
2.The request is then examined to locate the COM component and method to be called from the WSDL and WSML documents that were loaded when the SOAPServer object was initialized.
3.An instance of the identified COM object is created and the appropriate method is called using the arguments obtained from the request message.
4.The result is obtained from the method call and serialized into a SOAP response message.
5.The SOAP response message is returned to the caller via an output argument of the invoke method.
Creating a Web service consumer
The SOAPClient COM component enables Web service consumers to call Web services. This component leverages the features of the SOAP Toolkit to provide properties and methods that a Web service consumer can use to call Web service methods without having to deal with SOAP messages directly. In this way, the SOAPClient component acts as a proxy object for the Web service.
To use the SOAPClient component, you must have access to the WSDL document that describes the Web service. When you call the initialization method on the component, you pass in the location of the WSDL document. This causes all the operations defined in the WSDL document to be dynamically bound to the SOAPClient component. Once this has been completed, you can invoke the methods defined in the WSDL document via the SOAPClient object.
When you invoke a Web service method bound to the SOAPClient object, the following steps occur:
1.The SOAPClient object serializes the method call into a SOAP request message and delivers it to the server.
2.The server deserializes the SOAP request message and processes the request.
3.The server serializes the result into a SOAP response message and delivers it to the client.
4.The SOAPClient object deserializes the SOAP response message and returns the result to the caller.
5.The SOAPClient object also exposes SOAP fault properties so that you can examine error information in case a method call fails for some reason.
To summarize, the SOAPClient object makes it easy to consume Web services in a COM-like manner. The consumer need only supply the WSDL document that describes the Web service to the SOAPClient object in order to call the operations exposed by the Web service. The SOAPClient object takes care of translating COM method calls into SOAP requests and then translating the SOAP response into a COM method return value. If an error occurs in the method call, the SOAPClient object exposes properties that allow a consumer to gain access to the SOAP fault information that is returned.
WSDL/WSML generator tool
The WSDL/WSML generator tool is used to automatically generate WSDL and WSML documents from COM type libraries. The graphical version of the tool (named Wsdlgen.exe) walks you through the process of generating these documents. It will request the type of listener you wish to use, the location of the COM type library, which methods you wish to expose from the available interfaces in the type library, the folder in which to write the WSDL and WSML documents, and a few other details. After answering these questions, the tool will generate the files for you.
If you wish to script the generation of these files, a command-line version of the tool is also supplied, named Wsdlstb.exe. You can use the /? switch on the command line to get help information on valid command parameters and switches.
The bottom line here is that the WSDL/WSML generator tool can be a great timesaver when preparing your COM components for accessibility as Web services.
SOAP trace utility
One final useful utility to point out that ships with the Microsoft SOAP Toolkit is the SOAP trace utility. Using this graphical utility, you can view SOAP request and response messages transported over HTTP between a Web service and Web service consumer.
The trace utility can be configured to run either on the client or the server. To run the trace utility on the server, you must make a small modification to the WSDL document that specifies the URL to the SOAP endpoint. Once this has been done, you can start the trace utility to begin a tracing session. To run the trace utility on the client, you must copy the WSDL document to the client machine, make a similar modification to the WSDL document, and start the trace utility. After starting the utility, you need to specify the name of the host where the actual Web service is running. After doing so, you will be able to begin a tracing session.
Summary
SOAP is a major element of the Web services infrastructure and a critical factor in the ability of Web services to reach across platforms, operating systems, object models, and programming languages. This greatly increases the interoperability of distributed computing components built on this model.
SOAP extinguishes the language and object model wars by permitting component interoperability at a message level, enabling the user to implement their Web service code in any manner that they wish, using tools and technologies that are familiar and native to the platform on which they work.