
C# ПІДРУЧНИКИ / c# / Hungry Minds - ASP.NET Bible VB.NET & C#
.pdfrequest messages they are capable of processing and the response messages (if any) that they return. These capabilities are described in a standard way using the Web Service Description Language (WSDL), which is an XML grammar specifically designed for this purpose.
Before you can submit requests to a Web service, you must know how to format requests for a particular service in the form of a message that encodes the operation requested (such as converting a temperature from one unit to another) as well as any data required to carry out the operation (such as the input temperature, the source units, and the target units). In addition, you must know whether or not to expect a response message from the Web service and what format this response will take (such as the converted temperature value).
The Web service discovery process permits a consumer to search for and locate the WSDL document for a Web service. As implied, a consumer must have possession of the WSDL document before any requests can be properly formatted and delivered to the Web service.
The DISCO specification defines an XML-based grammar and algorithm for discovering the existence of Web services and locating their WSDL document. Using DISCO, you can define search trees that are processed according to the DISCO algorithm to locate Web service descriptions. Of course, if you already know the location of the WSDL document for a specific Web service, this discovery process is not needed.
Discovery documents are XML files that have a file extension of .vsdisco. The discovery document is a container for two types of elements: pointers to WSDL documents and pointers to other discovery documents. These pointers take the form of a URL and can be absolute or relative. The <contractRef> element is used to link to Web Service WSDL documents, whereas the <discoveryRef> element is used to link to other discovery documents.
If you are using Microsoft Visual Studio .NET to create your Web services or Web service consumer applications, the Web Reference feature of Visual Studio has the ability to locate Web services automatically using the discovery process. To do this, you simply enter the URL of a discovery document in the address bar of the dialog box. This will initiate the discovery process starting at the requested URL.
Alternatively, if you are not using Visual Studio .NET, you can use the .NET Framework's disco tool to search for Web service description files. The disco tool is a command-line utility that accepts one parameter: the URL to initiate the search process. In addition, command-line switches can be used to further control the discovery process.
The disco tool copies the WSDL documents of any Web services that it finds and also creates several other files (including a discovery document that refers to the Web service descriptions that it found as well as a discomap file) on the hard drive from which you ran the disco tool. These files can be used as input to the .NET Framework's wsdl tool to create Web service client proxy classes.
Note You must know at least the URL to a Web server in order to initiate the discovery process. If you do not have such a URL, you may wish to use the UDDI search mechanisms to locate Web servers that implement one or more Web services.
The implementation of the discovery process is also embodied in the .NET Framework's System.Web.Services.Discovery namespace. This namespace contains the classes that implement the .NET Web Service discovery process and can be leveraged programmatically by your applications or, if desired, replaced by your own implementation.
We will cover Web service discovery using these tools in greater detail in Chapter 28, "Consuming Web Services."
Web Service description
A Web service description is an XML document that defines the capabilities of a Web service. Using the WSDL XML grammar, you can clearly and unambiguously define the Web-addressable entry points in terms of the request messages that a Web service will accept as well as the response messages a Web service can return. Also included in this description are the supported protocol bindings and a description of the data types processed by the Web service.
Recall that the .NET Framework supports self-describing assemblies. This is accomplished by storing metadata with the assembly that describes the interfaces, data types, and other information about the classes in the assembly. Using the self-describing nature of .NET assemblies, the .NET Framework can generate WSDL documents to describe Web service capabilities from the .NET assemblies that contain ASP.NET Web service code. Much of this support is built into the System.Web.Services.Description namespace in the .NET Framework.
From the Web service perspective, ASP.NET supports the dynamic generation of WSDL documents from the Web Service assembly when it is requested. This eliminates issues related to keeping a separate WSDL document in sync with the Web Service assembly that implements the service.
In a nutshell, this process works as follows:
1.The client requests the WSDL document using a URL of the form http://server/ webservicepath/entrypoint.asmx?WSDL.
2.The Web server maps the request for the ASMX file to the ASP.NET runtime.
3.The ASP.NET runtime uses an instance of the WebServiceHandlerFactory class (found in the System.Web.Services.Protocols namespace) to process the URL.
4.The WebServiceHandlerFactory class obtains the query string and uses classes from the System.Reflection namespace to obtain the Web Service assembly metadata.
5.The metadata is then used with classes from the System.Web.Services. Description namespace to generate and return the WSDL document to the client.
This process makes it simple for a Web service to describe its capabilities to a requesting or potential consumer. The .NET platform automatically generates the WSDL for you, relieving you of this hassle.
The standard method of interacting with a Web service is through the use of a proxy class. From the consumer perspective, Visual Studio and ASP.NET provide tools that make it easy to generate a Web service proxy class, given a Web service description. The proxy class serves as a mirror image of the actual Web service (from an interface standpoint) but does not contain the actual implementation of the service. It is a local resource (local to the consumer) that accepts method calls and then forwards them to the actual Web service via HTTP and SOAP. Results are gathered from the Web service method and returned to the consumer. This gives a Web service method call the appearance of interacting entirely with a local class.
Visual Studio .NET automatically generates proxy classes from WSDL documents when you use the Web Reference feature to locate Web services that you wish to call from within your application. After you have located a WSDL document, you can use the Add Reference button on the dialog box to generate the proxy class.
If you are not using Visual Studio .NET to develop your consumer application, the .NET Framework supplies a tool named wsdl that you can use to generate .NET Web service proxy classes from a supplied WSDL document. The wsdl tool is a command-line utility that accepts a URL that points to the WSDL document that is used to generate the proxy class. A number of switches are available that you can use to control this process, such as specifying the target language for the generated proxy class.
We will examine the use of these tools in greater detail in Chapter 28, "Consuming Web Services."
Web Service Wire Formats
The final piece of the ASP.NET Web Services infrastructure consists of the Web service wire formats. Wire formats define the method by which Web service request and response messages are encoded and transported between the Web service and any consumer. To maximize the reach of Web services on the Internet, standard Internet protocols are used.
ASP.NET Web Services support three wire formats: HTTP-GET, HTTP -POST, and HTTP-SOAP. Traditional Web applications have used HTTP -GET and HTTP -POST to deliver Web forms–based data to the Web server for processing. These same protocols are used to deliver Web service operation requests along with any necessary arguments to the Web service for processing. The HTTP-SOAP wire format is a new format that has been developed exclusively for enabling Web services to communicate very rich data types.
Caution
Each of these wire formats finds its implementation in the System.Web.Services. Protocols namespace of the .NET Framework Class Library. Let's take a look at how these wire formats are implemented for ASP.NET Web Services.
HTTP-GET
The HTTP-GET protocol encodes Web service operation requests and arguments in the URL to the Web service. The operation is coded as part of the URL string and any arguments are coded as query string parameters appended to the base URL. For example:
http://localhost/ctemp/ctemp.asmx/ctemp?Temperature=
32&FromUnits=F&ToUnits=C
This URL specifies the Web-addressable entry point for the CTemp Web service (Ctemp.asxm), including the method to be called (also named ctemp). The arguments to the ctemp method are passed as query string arguments to the method request.
Similar to the way in which WSDL documents are generated and returned to requests for such information via a URL to the Web service entry point file (the ASMX file), the HTTPGET method of calling Web service methods is handled by the WebServiceHandlerFactory class. This class takes the URL and query string parameters as input and translates this into a method call on the appropriate Web service class implementation.
.NET Proxy classes use the HttpGetClientProtocol class in the System.Web.Services. Protocols namespace to invoke Web services that support the HTTP -GET protocol.
HTTP-POST
The HTTP-POST protocol encodes Web service operation requests and arguments within the payload area of the HTTP-POST request as name/value pairs.
This technique of invoking a Web service method is identical in operation to the HTTPGET method (from an ASP.NET perspective), except in the way in which the Web service call arguments are passed to the server.
Once again, the .NET Framework's WebServiceHandlerFactory class is responsible for extracting the method name and arguments from the request and calling the appropriate Web service method found in the Web service class implementation.
.NET Proxy classes use the HttpPostClientProtocol class in the System.Web.Services. Protocols namespace to invoke Web services that support the HTTP -POST protocol.
HTTP-SOAP
HTTP-SOAP is the default ASP.NET Web Service wire format. It is based on the SOAP specification (currently submitted to the W3C as a note) and supports the widest range of simple and complex data types (including document-oriented operations).
Web service request and response messages are encoded into SOAP messages that are included in the payload area of an HTTP-POST message. SOAP messages are encoded in XML using the SOAP vocabulary defined in the specification.
Because SOAP is really XML, it is possible to describe nearly any type of data. This makes SOAP an excellent choice for passing rich data types between Web services and their consumers. For example, it is possible to pass very complex types such as entire XML documents, such as an invoice or purchase order.
.NET Proxy classes use the HttpSimpleClientServiceProtocol class in the System. Web.Services.Protocols namespace to invoke Web services that support the HTTP - SOAP protocol.
Although these are the default wire formats, ASP.NET provides the capability to replace or add to these basic formats. For example, you can implement additional wire formats that allow Web services to communicate using FTP or SMTP.
We will cover each of these previously described Web service wire formats in greater detail in Chapter 25, "Building a Web Service."
Leveraging ASP.NET Features in Web Services
So far, we've outlined the broad support provided by the .NET platform and ASP.NET for building and consuming Web services. In the next few sections, we will look at more specific details of how to leverage some of these features within your ASP.NET Web Service applications.
Supporting transactions
ASP.NET Web Services are capable of supporting transactions, just like the automatic transaction support provided for classic COM+ components. When working with databases and other resource managers that support transactions, you will often want to use transactions to simplify and maintain the integrity of updates.
The major difference between the classic COM+ and new ASP.NET transaction support features is that ASP.NET transactions cannot be started by another application and then flow into the Web service method. In other words, Web services only support transactions that are started by the Web service method itself.
To enable transaction support for a Web service method, you must add the TransactionOption property to the WebMethod attribute that is used to identify Webcallable methods in your Web service classes. For example:
VB.NET:
<WebMethod(TransactionOption:=TransactionOption.Required)>
Public Function CTemp...

|
Table 23-2: TransactionOption property values |
|
|
|
|
|
|
|
|
|
Option |
|
Description |
|
|
|
|
|
|
|
|
|
the method. |
|
|
|
|
|
|
The default option is Required. If you are familiar with COM+ transaction support, you know that you were required to use the SetComplete or SetAbort method to signal the completion state of the transaction. This is no longer required for ASP.NET applications. The successful completion of a method call implies a call to SetComplete, whereas if the method call raises an exception, this implies a call to SetAbort.
If a Web Service method is participating in a transaction and an exception occurs, ASP.NET automatically aborts the transaction. Likewise, if no exception occurs, then the transaction is automatically committed.
Note For more information about automatic transaction support within ASP.NET Web Services, refer to the .NET Framework online documentation.
Enabling session state
Session state allows Web service methods to maintain contextual information between calls. To use the built-in session state support provided for ASP.NET Web Services, the Web Service class must inherit from either the WebService base class or use the HttpContext class.
Session state support for Web Services is bound to the HTTP protocol because it relies on the cookies feature of HTTP. You may recall that the design of SOAP is purposefully transport-independent, allowing SOAP messages to be piggybacked on other transport protocols such as FTP or SMTP. However, if you rely on the HTTP transport for session state support, you can no longer bind your SOAP messages to another transport without losing session state support.
Session state support for Web Services is disabled by default because it incurs additional overhead that you may not wish or need to use. To enable session support, you must add the EnableSession property to the WebMethod attribute that is used to identify Web-callable methods in your Web Service classes. For example:
VB.NET:
<WebMethod(EnableSession:="true")> Public Function CTemp...
C#:
[WebMethod(EnableSession="true")] Public string CTemp...
This property accepts a True or False value and specifies whether or not to enable session support for the Web method. Again, the default value of this property is False.
Session state uses temporary cookies to track a session. This means that the cookie is never saved to the hard drive. So, for the session state to remain valid, the same session ID must be used between requests. The session ID is normally supplied by the proxy class and, therefore, only exists as long as the proxy class exists. This means that the lifetime of the proxy class normally determines the lifetime of the session.
If this default behavior is unacceptable, it is possible to change this such that the cookie can be persisted and, thus, survive across proxy class instances.
Note For more information about maintaining session state with ASP.NET Web services, refer to the .NET Framework online documentation.
Web service caching
ASP.NET Web Services support output caching. This permits the result of a previous method request to be saved in a memory cache, to be recalled on subsequent requests without having to re-execute the logic of the method.
Output caching is convenient and useful in situations where the data being returned does not change often. This results in potentially large performance gains for the Web service when many consumers make requests for the same information.
To enable output caching, you must add the CacheDuration property to the WebMethod attribute that is used to identify Web-callable methods in your Web service classes. For example:
VB.NET:
<WebMethod(CacheDuration:=120)> Public Function CTemp...
C#:
[WebMethod(CacheDuration=120)] Public string CTemp...
This property accepts an integer value that specifies the length of time (in seconds) that the output will remain in the cache after the first execution of the method has returned the result the first time. Subsequent requests will immediately return the result to the call from the output cache until the specified time period expires. When this occurs, the method will be executed again, repopulating the cache and restarting the cache expiration countdown.
Output caching works correctly even if the method requires one or more arguments that can vary between requests. In this case, the output is cached for each unique combination of arguments supplied to the method. If the method has been called with identical parameters to a previous request, the response is obtained from the output cache; otherwise, the method is executed normally.
Output caching can be a very valuable tool in dramatically increasing the performance of your application. However, the effectiveness of this technique must be balanced against the memory used and the type of data being cached. If the data changes frequently or is infrequently accessed, the use of output caching will only degrade server performance.
So, carefully examine your situation before deciding to use output caching as a technique to increase server performance.
Buffering server responses
Response buffering allows the Web server to return the response to the consumer all at once, after the response has been completely generated, rather than transmitting it in multiple chunks. By default, ASP.NET Web Services buffer the response before sending it. However, in some cases it may be appropriate to change this default behavior. For example, it may be beneficial for long-running methods to transmit the response as it is generated.
To disable response buffering for Web services, you must add the BufferResponse property to the WebMethod attribute that is used to identify Web-callable methods in your Web service classes. For example:
VB.NET:
<WebMethod(BufferResponse:=true)> Public Function CTemp...
C#:
[WebMethod(BufferResponse=true)] Public string CTemp...
This property accepts a true or false value that specifies whether or not output buffering is enabled. The default for this property is true, which enables output buffering.
If you choose to disable response buffering, you must balance the potential benefits of this versus the additional resources required to transmit the response in multiple requests.
Inside an ASP.NET Web Service
So far, we've spent a great deal of time talking about the motivation behind Web services and some basics about the technologies that enable us to build and consume Web services. However, we have not yet covered exactly how a Web service works.
To wrap up this chapter on Web service infrastructure, let's walk through what happens during the execution lifetime of a Web service. In this way, we can bring together all the elements of Web services that we have discussed up to now and examine how they fit together to enable the Web service execution model.
In our discussion thus far, we've revealed partial details of how an ASP.NET Web Service works. Now that we have a complete picture of the technologies and tools used to build and consume ASP.NET Web Services, let's take a conceptual, but detailed, look at the execution flow and lifetime of a fictional Web service named CTemp.
The CTemp Web service converts temperature values from one numeric unit to another. The service supports a single method that accepts three input arguments: the temperature value, the source units, and the destination units. The Web service method takes these input arguments and converts the specified temperature to the destination units and returns the new temperature value to the caller.
We will begin our walkthrough at the point where the consumer sends a properly formatted SOAP message to the target server requesting the CTemp method of the CTemp Web service.
1.The IIS Web server hosting the CTemp Web service receives the request message (technically, an HTTP -SOAP request).
2.The URL is interpreted by the Web server to determine what ISAPI filter is responsible for handling the request (based on the file type). Because the URL points to the Web service entry point file (the ASMX file), the request is passed along to the ASP.NET ISAPI filter.
3.The ASP.NET ISAPI filter passes the request to an instance of the .NET HTTPRuntime class, which is hosted within an IIS application process. The movement of the request from the ISAPI filter to the HTTPRuntime class completes a transition from unmanaged to managed code.
4.The ASP.NET HTTPRuntime class is responsible for handling all incoming HTTP requests. The runtime resolves the URL to a specific application and then dispatches the request to that application. Web services are handled by the .NET WebServiceHandlerFactory class.
5.The WebServiceHandlerFactory deserializes the SOAP payload from the request, creates an instance of the CTemp Web service implementation class, and executes the CTemp method, passing the input arguments.
6.The ASP.NET runtime takes the result of the CTemp method call and serializes it into a SOAP response message. This message is then added to the payload of an HTTP response and delivered back to the client (in this case, our proxy class).
As you can see, a lot goes on behind the scenes of a Web service method request. Although this overview gives you an idea of what happens to a Web service request while it is being processed, it is by no means a complete picture. Many details within each of these steps have been left out for brevity (and understandability). However, this short tour should make it easier to see how the various pieces of the puzzle fit together.