Writing Web Services

I l @ ve RuBoard

Now that we have a better understanding of the protocols and standards involved in creating a Web Service, we're finally ready to write one of our own. The good news is that although there are a large number of fairly complex protocols at work under the hood, the quality of Microsoft's tools and compilers hides almost of all of this complexity from us. As you'll see, a few simple keywords and command-line parameters are all that you'll really need to make fully functional Web Services a part of your next application. In addition, Visual Studio .NET provides a number of visual tools that make creating and consuming Web Services even easier.

The ASP.NET Pipeline and Handler Architecture

The first thing you'll notice when writing Web Services with ASP.NET is that their filenames end with the .asmx file extension. This unique extension allows IIS to identify the file as a Web Service and invoke the appropriate .NET runtime Web request handler to process it. The .NET runtime employs a modular pipeline architecture to process different types of Web requests . This pipelined architecture allows multiple request handlers to process a single Web request sequentially, and the modular design allows administrators to configure the order in which handlers are executed and developers to replace existing handlers or create new ones. Common request handlers include those required to execute .aspx, .asmx, and .asp file types, log application events, authenticate users, and perform session management functions.

Writing Our First Service

Let's start our project by creating a subdirectory called testService in our Web server's root directory. Next, open Notepad and save the empty file to the testService directory you just created with the filename testService.asmx .

Processor Directives

Processor directives are located at the beginning of global.asax, .aspx, and .asmx files and are used to configure certain compiler settings and to indicate to ASP.NET the nature of the content it is about to process. For our simple Web Service, we just need to specify the language and class name associated with the service. To accomplish this, we type the following into our newly created testService.asmx file:

  <%@ WebService Language="c#" Class="testService" %> 

The code for our first Web Service is fairly straightforward, so we'll just enter it directly into Notepad as shown in Listing 11.1.

Listing 11.1 A simple Web service using the [WebMethod] attribute ( 11ASP01.cs.asmx ).
 using System; using System.Web.Services; public class testService {     [WebMethod]     public string HelloWorld(string name) {         return "Why, hello " + name + "!";     } } 

The [WebMethod] Attribute

Everything you just typed in should look pretty familiar by now. Note our use of the System.Web.Services namespace. By referencing this namespace, we gain access to the [WebMethod] service attribute. This attribute is used to tag the HelloWorld(string name) method as being accessible via our Web service. Think of the [WebMethod] attribute as a sort of superpublic access modifier extending access to the method across the Internet. You can't get any more public than that!

Thanks to the dynamic nature of the ASP.NET runtime, our service will be automatically compiled the first time we attempt to access the service. All that's left is for us to test the service! Save the changes you've made to the testService.asmx file if you haven't done so already and then fire up your favorite Web browser and point it to http://www.localhost/testService/testService.asmx . At this point you should be presented with a generic Web Service interface similar to that shown in Figure 11.1.

Figure 11.1. Generic Web Service interface provided by ASP.NET.

This interface is generated automatically by the ASP.NET runtime by examining the metadata associated with the compiled Web Service class as represented in its WSDL service contract. The WSDL service contract was likewise generated automatically by ASP.NET by examining the actual compiled class file associated with the service through a process known as reflection.

Each method marked with the [WebMethod] attribute (and therefore accessible via the Web Service) is listed in the Web Method Reference material along with information about what input parameters it requires and what values, if any, it returns. Moreover, a form-based interface that can be used to invoke the method for testing purposes is also provided.

Before we invoke our service's HelloWorld method to test the service, let's take a look at the WSDL file that ASP.NET has provided for us. Click the link entitled WSDL Contract and you should see the WSDL contract document as shown in Figure 11.2.

Figure 11.2. WSDL contract associated with the HelloWorld Web Service.

The first thing you'll notice is that the WSDL file returned to your browser is a well- formed XML document. The next thing to note is that this document describes three possible protocol bindings for the Web Service method HelloWorld . These bindings correspond to the SOAP, HTTP POST, and HTTP GET protocols respectively.

When we submit our name as a string value to the HelloWorld method, we will be using the HTTP POST protocol as defined in the service contract. According to the service contract, we can then expect to receive a string encoded using XML as a return value. The importance and value of the WSDL document cannot be understated because it allows a client application written in any language on any platform to understand the service's interface and execute against it.

Let's move on and actually test our Web Service. Use your browser's back button to return to the Web Service interface generated by ASP.NET and type your name (or the name of someone close to you whom you'd like to impress) in the form field. When you click the Invoke button, you will be presented with a screen similar to Figure 11.3 displaying the HTTP response generated by our service.

Figure 11.3. HTTP response generated by the HelloWorld Web Service.

Here we see that the return value has been encoded using XML within a <string> tag. If we had invoked the method programmatically using SOAP (as opposed to using an HTTP method from our Web browser), this tag would have been used by the client proxy to convert the value into a native string data type.

Generating a Client Proxy

The client proxy is what gives us the illusion that we are working with a simple local object when in fact much more is going on under the hood and over the Internet. It's important to emphasize that the client proxy is generated automatically for us by a simple .NET utility based on the WSDL contract provided by the ASP.NET runtime, making our job even easier. Let's generate a client proxy for our new service and use it to access our service programmatically over the Internet.

We'll start by creating a subdirectory called testServiceClient in the root of our c drive. Next, we'll open a command prompt, navigate to the testServiceClient directory, and issue the following command to generate the client proxy for our service:

TIP

If you're sure you've installed the .NET SDK properly but the command line reports that wsdl.exe and csc.exe are not recognized as "internal or external" commands, you might need to add the directories associated with these programs to your path . At the time of this writing, the default install paths for these programs were C:\Program Files\Microsoft.NET\FrameworkSDK\Bin and C:\WINNT\Microsoft.NET\Framework\v1.0.2914 . Because these locations are likely to change by the time you read this tip, you should search your hard drive for wsdl.exe and csc.exe to find the proper paths to include for your system.


  wsdl /language:CS /out:testServiceProxy.cs http://localhost/testService/ testService.  asmx?wsdl 

After issuing this command, you should see something similar to Figure 11.4 as output on your display:

Figure 11.4. Creating a Web Service client proxy from the command line.

And that's it! We now have a client proxy that will allow us to program against our Web Service from within any .NET application from anywhere on the Internet! Before we use the proxy as part of a client application, however, let's take a closer look at the command-line parameters we used. The /language:CS parameter indicates that we want the application to generate our client proxy as C# code. Notice that we supplied a URL to access the service directly rather than the service's WSDL file. Although we could have provided the WSDL file ourselves by specifying the URL of the service, instead we save an extra step and ensure that our proxy will work against the latest version of the service. The /out: parameter indicates the location and filename where we'd like the proxy source code to be generated. Although C# code is generated by default, you can easily use the /language: parameter to specify a different target language, such as Visual Basic.

Now let's take a look at Figure 11.5 showing the client proxy code that Wsdl.exe generated to gain some insight into how we'd write such a proxy ourselves if .NET hadn't been nice enough to do the job for us.

Figure 11.5. HelloWorld Web Service client proxy code.

Immediately after the comment lines at the beginning of the file, we see references to several system libraries. Although System.xml.Serialization has been included by default, our client proxy does not use it. XML serialization is an advanced feature that allows complex data types, such as datasets and other system and user -defined classes, to be converted to XML so that they can be transmitted using SOAP. We'll see an example of this later in the chapter.

Also worth mentioning is System.Web.Services.Protocols . You'll notice that our client proxy class TestService inherits from this library's SoapHttpClientProtocol class. Here we see the beauty of object-oriented design in action. All our proxy class has to do in order to utilize the networking, protocol, serialization, and marshalling services that comprise the Web Services architecture is to simply inherit this functionality from the SoapHttpClientProtocol class.

The no argument constructor for the client proxy sets the URL parameter of the superclass to the address of the Web Service so that communication between the client and server can take place. Next, a public HelloWorld method is defined that invokes our Web Service's HelloWorld method and casts the result to a native string data type from the generic object type returned. Because our proxy will have to wait for a response from the Web Service after we've invoked the HelloWorld method, two utility methods are defined to handle this in an asynchronous fashion.

A Simple Web Service Client

Web Services won't change the world unless there are clients out there who use them ”so let's get to work! Now that we've generated our proxy class, we just need to type our test client code into Notepad, save it, compile the test client and proxy classes together, and then run the program. Launch Notepad, type in the bit of code in Listing 11.2, and then save the file as testServiceClient.cs in the C:\testServiceClient directory.

Listing 11.2 A simple Web Service client ( 11ASP02.cs ).
 using System; class testServiceClass {     static void Main() {     testService myTest = new testService();     string response = myTest.HelloWorld("William");         Console.WriteLine(response);     } } 

Again, this is pretty much boilerplate code. In fact, we don't even need to specify any using statements to reference any special libraries because all of the architectural plumbing associated with remote access to Web Services is handled by the proxy class. All that there is left for us to do is to create an instance of the TestService class and call the HelloWorld method on it.

Before we can run our client application, however, we will need to compile both the TestService proxy and our new testServiceClass using the following command:

  csc /r:System.Web.dll,System.Web.Services.dll,System.XML.dll,System.dll  testServiceClient.cs testServiceProxy.cs 

Here we are using the /r: parameter to indicate to the C# compiler which system libraries will be utilized by our application. In addition, we specify which source files we'd like to compile. The resulting executable is called testServiceClient.exe. If you run this application, you should receive output similar to that in Figure 11.6.

Figure 11.6. Sample output from testServiceClient.

At this point, it is useful to take a look at a simplified version of the SOAP message that is actually being sent to the Web Service when you run the client.

  <?xml version="1.0"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/...>     <soap:Body>         <HellowWorld xmlns="http://tempuri.org">             <name>William</name>         </HelloWorld>     </soap:Body> </soap:Envelope> 

As you can see, the SOAP message itself is made up of two major sections. The SOAP envelope identifies the various XML namespaces associated with SOAP messaging and contains the SOAP body, which carries the actual message being sent between systems. A third element, the SOAP header, is optional and carries data about the message such as that relating to transactions, authentication, and payment.

The body contains, at a minimum, the name of the method that is being invoked and any argument values that are passed to it. Here we see that one argument, name, with the value William is being passed to the HelloWorld method. Notice that it's very easy to read and understand a SOAP message as opposed to those encoded by binary protocols such as DCOM, RMI, and IIOP. Also notice that there is nothing Microsoft-proprietary going on here ”it's all just straight XML and SOAP.

Now let's look at a simplified response message:

  <?xml version="1.0"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/...>     <soap:Body>         <HellowWorldResult xmlns="http://tempuri.org">             <result>Why, hello William!</result>         </HelloWorldResult>     </soap:Body> </soap:Envelope> 

A SOAP response looks remarkably similar to a request. Here we see that Why, hello William! is returned as a result of the invocation of the HelloWorld method.

I l @ ve RuBoard


Asp. Net. By Example
ASP.NET by Example
ISBN: 0789725622
EAN: 2147483647
Year: 2001
Pages: 154

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net