Скачиваний:
64
Добавлен:
15.03.2015
Размер:
4.31 Mб
Скачать

302

Day 13

Why Use Web Services?

Already, a number of technologies allow you to create distributed applications, including CORBA, DCOM, RPC, and custom solutions based on TCP sockets. Because these technologies are already in place and are quite mature at this time, why would you or your company make the leap to Web Services?

You might choose Web Services for a number of good reasons if you plan to make a distributed application:

Web Services are built on industry standard protocols, such as TCP, SSL, XML, SOAP, and WSDL. We’ll explain these protocols in detail later today.

Web Services are easy—even trivial—to implement with .NET. If you’ve ever tried to implement a CORBA or DCOM solution, you’ll be pleasantly surprised by how painless Web Service implementation and configuration are with .NET and ASP.NET.

You don’t need a lot of infrastructure in place to develop a Web Service. The only real requirements are a Web server and a connection to the Internet.

Implementing Your First Web Service

Rather than dwell on the theoretical aspects of Web Services, let’s implement a simple Web Service to demonstrate some of the points from the preceding section. Two pieces are required in any Web Service implementation: the service and the client. We will create the service first.

The easiest way to create Web Services in .NET is to build them using ASP.NET. Web Service files in ASP.NET have the special filename extension .asmx. ASP.NET flags any file with this extension as a Web Service and compiles it as a Web Service.

The first sample service that we will create simply returns the current time on the server as a string. Follow these steps to create the service:

1.As explained for the first ASP.NET page on Day 2, “Introducing ASP.NET,” create a directory for the Web Service project on your computer. For this example, use the directory C:\src\timeservice.

2.On your Web server, create a virtual directory named TimeService that points to the project directory in step 1. (Day 2 explained how to create virtual directories.)

3.In the project directory, create a new file called TimeUtilities.asmx using your text editor or download this file from the book’s Web site at www.samspublishing.com. Type the contents of Listing 13.1 if you didn’t download the file.

Listing 13.1 shows a basic Web Service that will return the time of day as a string on the server.

ANALYSIS

Introducing Web Services

303

LISTING 13.1 TimeUtils.asmx: Returning the Current Time on the Server

1:<%@ WebService Language=”C#” Class=”TimeUtilities” %>

2:using System;

3:using System.Web.Services;

4:

5:[WebService(Namespace=”http://tempuri.org/webservices”)]

6:public class TimeUtilities : WebService

7:{

8:[WebMethod]

9:public String GetTime()

10:{

11:String ret = “The current time on the server is: “;

12:String curTime = DateTime.Now.ToString();

13:return ret + curTime;

14:}

15:}

Line 1 uses the WebService page directive. You’ve seen other ASP.NET page directives such as Page, Import, and Control on previous days. The WebService

page directive marks the remaining code in the page as a Web Service. Within the page directive, you must specify the class of the Web Service that you are going to define in the code. Each Web Service must have its own class; the one in this example is called

TimeUtilities.

Lines 2 and 3 specify that we are using the System and System.Web.Services namespaces. They are required in any Web Service that we write.

On Line 5 comes the definition of the class. Notice that before we define the class, we use an attribute for it:

[WebService(Namespace=”http://tempuri.org/webservices”)]

This line is called an attribute definition. If you are an experienced .NET code

NEW TERM

developer, you may already have used these kinds of attributes in your code. If

you haven’t used them, just understand that they supplement the code you write. In this 13 case, we are using the WebService attribute to specify the namespace for our Web Service.

Because Web Services can be exposed to the rest of the world on the Internet, each one needs a unique namespace. This namespace is exactly the same kind of thing you would use in an XML file that you were going to share with another company, as we explained on Day 8, “Using XML with Your Application.” If you are developing a Web Service for an organization, you should use your organization’s public URL instead of tempuri.org.

Next, Line 6 defines the TimeUtilities class. Because the class defines a Web Service, it must derive from the WebService class in the System.Web.WebServices namespace.

304

Day 13

Our next order of business (Lines 9–14) is to define the method that we want our Web Service users to call. Notice that the GetTime method is preceded by the [WebMethod] attribute. All methods that should be available to Web Service users must have this attribute. GetTime simply returns a string with the current time on the server.

Testing the Web Service

To test the Web Service, you need to point a Web browser to the Web Service as if it were a regular Web page. ASP.NET automatically generates some simple documentation for the Web Service and provides Web pages to invoke methods on the service. If you’re using the same computer where the Web Service resides to test the service, point your browser to the following URL. If not, substitute the name of the computer for localhost in the following URL:

http://localhost/TimeService/TimeUtils.asmx

You should see a page that resembles Figure 13.1. From the figure, you can see that ASP.NET has created a page with a list of the methods that the TimeUtils Web Service exposes.

FIGURE 13.1

ASP.NET output for the TimeUtils.

Click the GetTime link to see a page that has some template documentation for the GetTime method, as shown in Figure 13.2.

By clicking the Invoke button on this page, you see a response similar to the following code lines in your browser. The Web server (IIS) returns an XML document that contains the response from the Web Service.

<?xml version=”1.0” encoding=”utf-8” ?>

<string xmlns=”http://tempuri.org/webservices”>

The current time on the server is: 7/7/2001 3:55:41 PM </string>

Introducing Web Services

305

FIGURE 13.2

ASP.NET boilerplate documentation for the

GetTime method.

Describing the Web Service

Web Services need a way to tell client programs what methods they implement, the parameters each method takes, and the return values each method gives back. They do so through a WSDL file. WSDL, which stands for Web Services Description Language, provides clients of a Web Service with all the necessary details they need to connect to and use the Web Service.

WSDL files are XML files. To see what the WSDL file looks like for our TimeUtils application, point your browser to the URL of the TimeUtils.asmx file and append the string ?WSDL to the URL, as in the following line:

http://localhost/TimeService/TimeUtils.asmx?WSDL

Tip

You can also see the WSDL file for the TimeUtils application by browsing to

 

the main Web Service page and then clicking the Service Description link

 

 

13

 

(refer to Figure 13.1).

 

 

 

 

 

The WSDL file returned from our sample Web Service looks like Listing 13.2. The WSDL is quite large, even for our simple Web Service. Luckily, you should never have to create WSDL files yourself; the Web Service will generate the files automatically using the plumbing built into ASP.NET.

306

Day 13

LISTING 13.2 The WSDL File for the TimeUtils Web Service

1:<?xml version=”1.0” encoding=”utf-8” ?>

2:<definitions

3:xmlns:s=”http://www.w3.org/2001/XMLSchema”

4:xmlns:http=”http://schemas.xmlsoap.org/wsdl/http/”

5:xmlns:mime=”http://schemas.xmlsoap.org/wsdl/mime/”

6:xmlns:tm=”http://microsoft.com/wsdl/mime/textMatching/”

7:xmlns:soap=”http://schemas.xmlsoap.org/wsdl/soap/”

8:xmlns:soapenc=”http://schemas.xmlsoap.org/soap/encoding/”

9:xmlns:s0=”http://tempuri.org/webservices”

10:targetNamespace=”http://tempuri.org/webservices”

11:xmlns=”http://schemas.xmlsoap.org/wsdl/”>

12:<types>

13:<s:schema attributeFormDefault=”qualified”

14:elementFormDefault=”qualified”

15:targetNamespace=”http://tempuri.org/webservices”>

16:<s:element name=”GetTime”>

17:<s:complexType />

18:</s:element>

19:<s:element name=”GetTimeResponse”>

20:<s:complexType>

21:<s:sequence>

22:<s:element

23:minOccurs=”1”

24:maxOccurs=”1”

25:name=”GetTimeResult”

26:nillable=”true”

27:type=”s:string” />

28:</s:sequence>

29:</s:complexType>

30:</s:element>

31:<s:element name=”string” nillable=”true” type=”s:string” />

32:</s:schema>

33:</types>

34:<message name=”GetTimeSoapIn”>

35:<part name=”parameters” element=”s0:GetTime” />

36:</message>

37:<message name=”GetTimeSoapOut”>

38:<part name=”parameters” element=”s0:GetTimeResponse” />

39:</message>

40:<message name=”GetTimeHttpGetIn” />

41:<message name=”GetTimeHttpGetOut”>

42:<part name=”Body” element=”s0:string” />

43:</message>

44:<message name=”GetTimeHttpPostIn” />

45:<message name=”GetTimeHttpPostOut”>

46:<part name=”Body” element=”s0:string” />

47:</message>

48:<portType name=”TimeUtilitiesSoap”>

Introducing Web Services

307

LISTING 13.2 Continued

49:<operation name=”GetTime”>

50:<input message=”s0:GetTimeSoapIn” />

51:<output message=”s0:GetTimeSoapOut” />

52:</operation>

53:</portType>

54:<portType name=”TimeUtilitiesHttpGet”>

55:<operation name=”GetTime”>

56:<input message=”s0:GetTimeHttpGetIn” />

57:<output message=”s0:GetTimeHttpGetOut” />

58:</operation>

59:</portType>

60:<portType name=”TimeUtilitiesHttpPost”>

61:<operation name=”GetTime”>

62:<input message=”s0:GetTimeHttpPostIn” />

63:<output message=”s0:GetTimeHttpPostOut” />

64:</operation>

65:</portType>

66:<binding name=”TimeUtilitiesSoap” type=”s0:TimeUtilitiesSoap”>

67:<soap:binding transport=”http://schemas.xmlsoap.org/soap/http”

68:

style=”document” />

69:<operation name=”GetTime”>

70:<soap:operation soapAction=”http://tempuri.org/webservices/GetTime”

71:

style=”document” />

72:<input>

73:<soap:body use=”literal” />

74:</input>

75:<output>

76:<soap:body use=”literal” />

77:</output>

78:</operation>

79:</binding>

80:<binding name=”TimeUtilitiesHttpGet” type=”s0:TimeUtilitiesHttpGet”>

81:<http:binding verb=”GET” />

82:<operation name=”GetTime”>

83:<http:operation location=”/GetTime” />

84:<input>

85:

<http:urlEncoded />

13

 

86:</input>

87:<output>

88:<mime:mimeXml part=”Body” />

89:</output>

90:</operation>

91:</binding>

92:<binding name=”TimeUtilitiesHttpPost” type=”s0:TimeUtilitiesHttpPost”>

93:<http:binding verb=”POST” />

94:<operation name=”GetTime”>

95:<http:operation location=”/GetTime” />

96:<input>

97:<mime:content type=”application/x-www-form-urlencoded” />

308

Day 13

LISTING 13.2 Continued

98:</input>

99:<output>

100:<mime:mimeXml part=”Body” />

101:</output>

102:</operation>

103:</binding>

104:<service name=”TimeUtilities”>

105:<port name=”TimeUtilitiesSoap” binding=”s0:TimeUtilitiesSoap”>

106:<soap:address

107:location=”http://localhost/timeservice/timeutils.asmx” />

108:</port>

109:<port name=”TimeUtilitiesHttpGet” binding=”s0:TimeUtilitiesHttpGet”>

110:<http:address

111:location=”http://localhost/timeservice/timeutils.asmx” />

112:</port>

113:<port name=”TimeUtilitiesHttpPost”

114:binding=”s0:TimeUtilitiesHttpPost”>

115:<http:address

116:location=”http://localhost/timeservice/timeutils.asmx” />

117:</port>

118:</service>

119:</definitions>

Analyzing the WSDL File

To get a general sense of what the WSDL file describes, let’s take a detailed look at ANALYSIS Listing 13.2. The top-level XML nodes for the TimeUtils WSDL file are as follows:

<definitions>

<types>

<message name=”GetTimeSoapIn”> <message name=”GetTimeSoapOut”> <message name=”GetTimeHttpGetIn”> <message name=”GetTimeHttpGetOut”> <message name=”GetTimeHttpPostIn”> <message name=”GetTimeHttpPostOut”>

<portType name=”TimeUtilitiesSoap”> <portType name=”TimeUtilitiesHttpGet”> <portType name=”TimeUtilitiesHttpPost”>

<binding name=”TimeUtilitiesSoap”> <binding name=”TimeUtilitiesHttpGet”> <binding name=”TimeUtilitiesHttpPost”>

<service name=”TimeUtilities”>

</definitions>

Introducing Web Services

309

You can see that the WSDL file contains several kinds of nodes: types, message, portType, binding, and service. The types node describes the names, parameters, and return values of each method in the Web Service. The message, portType, binding, and service definitions describe how a client should communicate with the Web Service.

Let’s analyze each WSDL definition node in reverse order.

The service Node

The service node defines the name of our Web Service—in this case, TimeUtilities— and then defines ports:

104:<service name=”TimeUtilities”>

105:<port name=”TimeUtilitiesSoap” binding=”s0:TimeUtilitiesSoap”>

106:<soap:address

107:location=”http://localhost/timeservice/timeutils.asmx” />

108:</port>

109:<port name=”TimeUtilitiesHttpGet” binding=”s0:TimeUtilitiesHttpGet”>

110:<http:address

111:location=”http://localhost/timeservice/timeutils.asmx” />

112:</port>

113:<port name=”TimeUtilitiesHttpPost”

114:binding=”s0:TimeUtilitiesHttpPost”>

115:<http:address

116:location=”http://localhost/timeservice/timeutils.asmx” />

117:</port>

118:</service>

Each port corresponds to a certain protocol that the Web Service will support. Our Web Service supports the SOAP, HTTP Post, and HTTP Get protocols.

Note

Not every Web Service supports HTTP, because some complex parameters

can’t be passed in and out of Web Services using HTTP. We’ll explain the

 

 

rules surrounding when HTTP is supported later today. SOAP supports any

 

kind of data type.

13

The portType Node

Each port supports an “operation.” Each operation corresponds to a method that the Web Service supports. You can see that the following SOAP portType supports the GetTime operation for our Web Service. Each operation consists of “messages”: an input message for when the method is called and an output message for when the method returns a value.