深蓝海域KMPRO

Applying .Net to Web Services

2002-09-13 13:12

Applying .Net to Web Services

By Brian Jepson

As long as it has been possible to connect two computers, programmers have built software that communicates over the network. Most of this communication is facilitated by protocols, which standardize and formalize the way information is exchanged among various applications. Protocols that hide the low-level network plumbing make lazy developers like me very happy, because they require less work and offer more reward. For example, the Simple Mail Transfer Protocol (SMTP) requires that each communication session begin with a client transmitting a HELO string to a server. The server knows that this is the initiation of a session and will respond with a similar string. Because the strings and the order in which they're transmitted are standardized, application developers creating email clients are freed from making their own rules to communicate with servers, and from writing extra code for servers that might have their own arbitrary rules.

Remote Procedure Calls (RPCs) take the concept of the protocol to the next level. With these, you can invoke a method in a bit of code residing anywhere on the network as if it were code running on your own system. Why use up some of your workstation's CPU if a more powerful server is available across the network? Further, if you are performing calculations on a large data set, why bring the data set to your workstation when you can let the server with the data do the work, and send only the result to your workstation? If you extend this notion to object-oriented programming, you might start to think of your remote objects as parts of a service—as if there's a machine across the network that's willing to provide objects that perform work on behalf of your application.

So, what can you do with these remote services? Consider online booksellers like Bookpool.com or Fatbrain.com. Such booksellers rely on distributors to supply them with books. If the distributor exposes inventory and price information as remote objects, the bookseller can develop customized applications that talk to those objects. For instance, the list of new titles could come down the wire as an object, such as an array or vector of books called NewTitlesCollection. Once that object appears in the bookseller's computer, the program could order the new titles using the NewTitlesCollection .GiveMeTenOfEach method. The fact that the local instance of that object has to go back over the network to perform this function is totally hidden from the programmers and users. This is a good thing because it lets you write distributed applications without having to worry about the underlying plumbing. In such a situation, the bookseller is a consumer of various objects that come together to form a service.

As soon as the Web's potential began to sink in, people started looking at ways to deliver these sorts of services over HTTP. Protocols such as XML-RPC and Simple Object Access Protocol (SOAP) emerged, and programmers began writing applications that chattered back and forth over the same infrastructure your Web browser uses to load Web pages.

Enter .Net

Microsoft's manifestation of the Web-services concept is the .Net Framework. The framework represents a shift in Microsoft's focus from creating desktop applications to creating network services. Currently, .Net is somewhat amorphous—it's a catchall phrase for developing software the Microsoft way. By using .Net technologies and practices, developers can build solutions that aggregate services from all over the Internet. This promises to save time and money in development, promote the growth of new technology partnerships, and extend what's currently possible for Internet applications.

Figure 1 shows a user-oriented realization of the .Net vision. There are two applications in the figure: a customized word processor and a customized notepad application. Table 1 describes each of these potential services. The word processor runs on an application service provider's (ASP's) Web server and aggregates services from three different providers to do its work. The notepad application runs on your handheld device. It's much simpler than the word processor, and uses only two services. (Note that although I use Microsoft and Adobe as examples, the services shown in the diagram are purely hypothetical.)

.Net services and applications can run on any platform that the framework supports. You can write your programs using any language that is supported by .Net (such as C#, C++, VB.Net, JScript, Python, COBOL, Eiffel, and others), and the programs will be compiled on a platform-independent format called Intermediate Language (IL). IL is conceptually similar to Java's bytecode, but it's never executed inside a virtual machine. Instead, IL is compiled to native code either at install-time, or each time the program is run. The latter is done with a just-in-time compiler, which compiles the IL into machine code on demand.

As I write this, the languages, server software, and compilation infrastructure for the .Net framework work only on Windows platforms. However, Microsoft has submitted a substantial portion of the .Net Framework to the European Computer Manufacturer's Association (ECMA). If accepted, third parties could implement and offer the .Net Framework on any platform by closely following the specification.

The portion of .Net that was submitted to ECMA includes the C# (C-Sharp) language and the common language infrastructure (CLI). The CLI includes IL, the base class library, and the execution engine that provides runtime support with class loading and just-in-time compilation. Figure 2 shows the relationship of the ECMA submission to the overall .Net architecture.

Of course, the larger question is whether or not it's a good idea for the components of your word processor to run on many different servers. Some aggregations of services may be more practical than others. For example, an order-fulfillment system is a good candidate for using distributed services. Because bits of critical data are already held by a variety of entities, a distributed architecture makes perfect sense. Whether ASPs and Web-service providers can bring high availability to distributed end-user applications remains to be seen.

A Web Service in C#

To create a Web service using .Net, you need to set up (or find) a Web server that has the .Net Framework installed. The .Net Framework includes the CLI, the C#, C++, VB.Net, and JScript languages, and the .Net Framework APIs—everything from basic runtime libraries to user-interface libraries. Internet Information Server (IIS) must be installed to develop Web services under .Net. If you were to build your own .Net server from scratch, you'd do well with a Pentium II and Windows 2000—which includes IIS. On top of that, you'd need to install the .Net Framework Beta (see "Online Resources"). At the time of this writing, Brinkster is offering free .Net testing accounts, and Eraserver.net is offering accounts for $9.95 a month. I'm sure there are others out there, so look for them if you need different features. I signed up for the Brinkster account and deployed my sample Web services there.

Of course, once you've established where you're going to put the file containing the code for your Web service, you need to actually write the code. Source code for .Net Web services is stored in files with the .asmx extension. You can write this code in C# or any of the other supported languages. Treat the .asmx file as you would an ASP document: Simply place it in a Web-accessible folder that has script execute permissions.

A Web service is a class that inherits from System.Web.Services .WebService. Any methods you want to expose must have the WebMethod attribute. Listing 1 shows a Web service written in C# that follows these rules. If you install this file on a server, you can visit the Web service in your browser to get a useful description (see Figure 3). You can even click on the Invoke button to call one of your methods. Note that this isn't true inter-application communication, but rather, a convenient interface that .Net supports in case you want to have some human interaction with the Web service.

SOAP

As I mentioned earlier, developers find that it saves time to let programs communicate via standard Web protocols like HTTP. When XML appeared on the scene, it was a natural choice to represent the data that's transferred between applications. XML was used as the foundation for communication that uses SOAP, which was created jointly by DevelopMentor, UserLand Software, and Microsoft. SOAP has been implemented by a variety of adopters, including IBM, the Apache XML Project, and open-source developers such as Paul Kulchenko, the author of SOAP::Lite (see "SOAP::Lite"). SOAP is so simple to understand that a human could read a conversation between two software applications.

Note that you can also use CORBA, DCOM, and RMI to communicate between applications. However, the plumbing that supports them is complicated, and requires a significant level of expertise to master.

At this writing, the SOAP implementation that comes with .Net isn't compatible with some other SOAP implementations. However, as the flurry of activity in implementing SOAP settles down, it's likely that this sort of problem will become less common. Fortunately, there's an attribute you can attach to your class that fixes this problem. To use SOAP, add two lines to the .asmx file in Listing 1. The first imports the namespace that contains the SOAPServiceStyle class (the System.Xml.Serialization namespace). The second line adds a custom attribute. Listing 2 shows Hello.asmx modified with these two lines (5 and 7).

Listing 3 shows a SOAP request sent via HTTP to the Hello.asmx Web service I showed you earlier. The request would come from a client or other application that wanted to use the Web service. Lines 1 to 4 constitute a standard HTTP header: The first three lines contain the service name, the content length, and the data type; the last line is a SOAP-specific HTTP header that specifies the method you want to invoke.

Lines 6 through 13 make up the body of the SOAP request. Line 6 describes the document as an XML document—you'll see something like this at the top of most XML documents. Lines 7 to 9 and line 13 constitute the enclosing Envelope element, including information such as the encoding style and the XML namespace (xmlns) that corresponds to a SOAP envelope. Think of this envelope as the package that contains the SOAP parcel.

The Body element, delimited by lines 10 and 12, makes up the parcel. This element contains a method call (IssueGreeting) on line 11, which specifies the method you want to call. If there were any arguments to the method, these would be enclosed in the IssueGreeting element.

Note that all of the elements are prefixed with a namespace, such as SOAP-ENV or namesp1. This is done so you don't have to worry about collisions between XML elements with the same name. Namespaces make sure that an element called namesp1:Envelope isn't confused with SOAP-ENV:Envelope.

Listing 4 shows the Web service's response to the SOAP request. This response would be transmitted via HTTP back to the requesting client application. Lines 1 through 6 are the HTTP response headers, indicating that the SOAP client should expect some XML output. They also specify other information about the response, such as its length. The markup on line 8 identifies this as an XML document (note that it's missing the optional encoding attribute that appears in Listing 3).

As with Listing 3, the response has an Envelope element. Lines 14 and 18 delimit the message body, which contains an element called IssueGreetingResult. It's in this element that we find the nugget we're interested in—the one called result—which contains the string Hello, World!

As a side note, if you compare the Envelope elements in Listings 3 and 4, it appears as if each element is prefixed by a different namespace. However, each namespace actually contains the same information. If you look at the attribute that corresponds to each namespace (line 9 in Listing 3, line 10 in Listing 4), you'll find that they both resolve to the same schema. You can think of SOAP-ENV and soap as local namespaces that refer to the same global schema.

There are more attributes contained in the Envelope element, but it's safe to think of these as related to the underlying plumbing. When you examine a SOAP client, you'll want to set this XML aside and concentrate on invoking methods on Web services. If you are interested in learning more details about the SOAP protocol itself, read Understanding SOAP (Kennard Scribner and Mark C. Stiver, Sams Publishing, 2000) or visit one of the locations in "Online Resources."

Future Developments

.Net promises cross-language support, but many observers hope it will provide cross-platform support as well. The framework faces an uncertain future if this doesn't appear. Microsoft has positioned .Net to compete with Sun's Java 2 Enterprise Edition platform. Supporting multiple-operating systems is essential if Microsoft plans to compete on all fronts. For more information on the rivalry between the creators of Java 2 Enterprise Edition and .Net, read "The Big Picture," by Al Williams, also in this issue.

Of course, cross-platform support means different things to different people at different times. Some argue that SOAP offers the cross platform support that's lacking from .Net. This is true in theory, because anything that can speak HTTP and parse XML should be able to participate in a SOAP dialog with .Net. Even so, this doesn't let Microsoft off the hook. We still need a CLI—that is, everything in the ECMA submission—for Linux, the Mac OS, Solaris, and others. I hope that Microsoft isn't waiting for someone else to implement this. It would be a character-building exercise for Microsoft to set up the Redmond equivalent of publicsource.apple.com and get developers plugged in to an open-source .Net port.

相关推荐