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 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 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 2.
Figure 2 ASP.NET boilerplate documentation for the GetTime method.
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>
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 (refer to Figure 1).
The WSDL file returned from our sample Web Service looks like Listing 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.
Listing 2The 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"> 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 /> 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" /> 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 Listing 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>
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 Servicein this case, TimeUtilitiesand 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 in this chapter. SOAP supports any kind of data type.
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.
48: <portType name="TimeUtilitiesSoap"> 49: <operation name="GetTime"> 50: <input message="s0:GetTimeSoapIn" /> 51: <output message="s0:GetTimeSoapOut" /> 52: </operation> 53: </portType>
The message Node
The message definition for the GetTimeSoapIn method is as follows:
34: <message name="GetTimeSoapIn"> 35: <part name="parameters" element="s0:GetTime" /> 36: </message>
The message definition describes how parameters will be passed into and out of the Web Service. The GetTime method doesn't receive any parameters, so the message definition is trivial.
The types and schema Nodes
The types node describes each method, parameter, and return value for a Web Service. These Web Service elements are detailed in a schema node. A simplified version of the schema node for our Web Service follows:
<s:schema> <s:element name="GetTime"> <s:complexType /> </s:element> <s:element name="GetTimeResponse"> <s:complexType> <s:sequence> <s:element name="GetTimeResult" type="s:string" /> </s:sequence> </s:complexType> </s:element> <s:element name="string" nillable="true" type="s:string" /> </s:schema>
Here, the schema node describes the GetTime and GetTimeResponse messages that our Web Service deals with. Our Web Service returns a GetTimeResponse message after the GetTime method is invoked. The definition shows that the response message includes a string.