Using WSDL to Document Web Services

WSDL Document Syntax

WSDL documents can be intimidating at first glance. But the syntax of a WSDL document is not nearly as complex as that of an XML Schema document. A WSDL document is composed of a series of associations layered on top of an XML Schema document that describes a Web service. These associations add to the size and the perceived complexity of a WSDL document. But once you look underneath the covers, WSDL documents are rather straightforward.

The root of a WSDL document is the definitions element. Within this element are five types of child elements:

  • types Contains the schema definitions of the messages that can be sent and received by the service. The most common way of representing the schema is using XML Schema.

  • message Serves as a cross-reference that associates the message with its definition within the schema.

  • portType Defines a set of interfaces that the Web service can expose. An interface is associated with one or more messages.

  • binding Associates the portType definition with a particular protocol.

  • service Defines a collection of related endpoints (ports) exposed by the Web service.

The following diagram illustrates how these five elements are layered on top of the schema definition to describe the Web service:

As you can see, a WSDL document is composed of a series of associations. For example, message parts are used to associate a datatype definition with a portion of the content of a message.

definitions Element

The root element in a WSDL document, the definitions element, serves much the same role as the schema element in an XML Schema document. It contains child elements that define a particular service.

Much like an XML Schema document, a WSDL document can define its own namespace by adding a targetNamespace attribute to the definitions element. The only restriction is that the value of the targetNamespace attribute cannot contain a relative URI.

The WSDL namespace allows you to fully qualify references to entities defined within a WSDL document. For example, a message definition is referenced by a portType definition. Later in the chapter, I reference entities defined within another WSDL namespace to facilitate interface inheritance.

The following WSDL fragment defines the definitions element for the Calculator Web service:

<?xmlversion="1.0"encoding="utf-8"?> <definitionstargetNamespace="http://somedomain/Calculator/wsdl" xmlns:tns="http://somedomain/Calculator/wsdl" xmlns="http://schemas.xmlsoap.org/wsdl/"> <!--Definitionswillgohere.--> </definitions>

The preceding WSDL document contains a definitions element. Within the target namespace, the target namespace is set to http://somedomain/Calculator. Then a reference is made to the target namespace, assigning it a prefix of tns:. This prefix will be used within the document to fully qualify references to entities defined within the document. Finally, the WSDL namespace is set to the default namespace.

The definitions element defines the boundaries of a particular name scope. Elements declared within a WSDL document are used to define entities such as ports and messages. These entities are assigned a name using the name attribute. All name attributes within a name scope must be unique. For example, if a WSDL document contains a port named Foo, it cannot contain another port or message named Foo.

It might not always be practical to define a unique fully qualified URI for a namespace—for example, early in the development cycle or when you want to create a couple of experimental Web services. In these cases, you can use http://tempuri.org, a special URI that is used by convention to define namespaces that do not need to be uniquely identified.

types Element

The types element contains schema information referenced within the WSDL document. The default type system supported by WSDL is XML Schema. If XML Schema is used to define the types contained within the types element, the schema element will appear as an immediate child element.

You can use other type systems by extension. If you use another type system, an extensibility element can appear under the types element. The name of the element should identify the type system used. In this chapter, I limit my discussion to XML Schema because it is the dominant type system used in WSDL documents, including those for Web services developed on the .NET platform.

The Calculator Web service will expose two RPC-style methods, an Add method and a Subtract method. The messages will be encoded in much the same way that I showed you in Chapter 4. The only difference is that the schema will be embedded within a WSDL document, as shown here:

<?xml version="1.0" encoding="utf-8"?> <definitions targetNamespace="http://somedomain/Calculator/wsdl"  xmlns:tns="http://somedomain/Calculator/wsdl"  xmlns:xsd="http://www.w3.org/2001/XMLSchema"  xmlns:s="http://somedomain/Calculator/schema"  xmlns="http://schemas.xmlsoap.org/wsdl/">     <types>     <schema attributeFormDefault="qualified"      elementFormDefault="qualified"      xmlns="http://www.w3.org/2001/XMLSchema"      targetNamespace="http://somedomain/Calculator/schema">       <!-- Definitions for both the Add and Subtract SOAP messages -->       <element name="Add">         <complexType>           <all>             <element name="x" type="int"/>             <element name="y" type="int"/>           </all>         </complexType>       </element>       <element name="AddResult">         <complexType>           <all>             <element name="result" type="int"/>           </all>         </complexType>       </element>       <element name="Subtract">         <complexType>           <all>             <element name="x" type="int"/>             <element name="y" type="int"/>           </all>         </complexType>       </element>       <element name="SubtractResult">         <complexType>           <all>             <element name="result" type="int"/>           </all>         </complexType>       </element>       <!-- Common SOAP fault detail element used by Add and Subtract -->       <element name="CalculateFault">         <complexType>           <all>             <element name="x" type="int"/>             <element name="y" type="int"/>             <element name="Description" type="string"/>           </all>         </complexType>       </element>     </schema>   </types>   <!-- More definitions will go here. --> </definitions>

Within the types element are schema definitions for the Add and Subtract methods, which use the reference to the schema's namespace that appears within the definitions element earlier in the document.

WSDL is not limited to describing XML-based serialization formats. You can use it to describe services that use other formats, including binary. For example, you can use WSDL to describe a service exposed via DCOM. In this case, you can still use XML Schema to describe the data being sent across the wire. The WSDL specification provides the following recommendations for doing so:

  • Describe the data using elements, not attributes. For example, each parameter should be encoded within its own element, much like in SOAP Encoding.

  • Describe only data that is related to the message and is not particular to the wire encoding. For example, the parameters passed to a remote COM object should be described in the schema. However, the DCOM object identifier (OID) is wire-protocol-specific data that identifies the object and should not be described in the schema.

  • Array types should be derived from the Array complex type defined in the SOAP Encoding schema. By convention, the name of the type should be the type of items within the array, prefixed by ArrayOf.

  • Parameters that can contain data of any type should be defined by an element of type xsd:anyType.

message Element

The message element provides a common abstraction for messages passed between the client and the server. Because you can use multiple schema-definition formats within a WSDL document, it is necessary to have a common way of identifying the messages. The message element provides this common level of abstraction that will be referenced in other parts of the WSDL document.

Multiple message elements can and often do appear in a WSDL document, one for each message being communicated between the client and the server. Each message contains one or more part elements that describe pieces of content within the message. An example of a part is the body of a SOAP message or a parameter contained within the query string, a parameter encoded in the body of a SOAP message, or the entire body of a SOAP message.

Each part element contains attributes that associate type and element definitions found in the types element. Because parts are abstract definitions of content, the binding information must be examined in order to determine the meaning of the parts.

Two attributes that can appear within the part element are the element and type attributes. The element attribute refers to an element definition in a schema. The type attribute refers to a type definition in a schema.

Because the Calculator Web service contains two methods, each with a request and response message, and a fault message was defined, the WSDL document will contain five message elements:

<?xml version="1.0" encoding="utf-8"?> <definitions targetNamespace="http://somedomain/Calculator/wsdl"  xmlns:tns="http://somedomain/Calculator/wsdl"  xmlns:s="http://somedomain/Calculator/schema"  xmlns:xsd="http://www.w3.org/2001/XMLSchema"  xmlns="http://schemas.xmlsoap.org/wsdl/">   <!-- Type definitions removed for clarity -->   <message name="AddMsgIn">     <part name="parameters" element="s:Add"/>   </message>   <message name="AddMsgOut">     <part name="parameters" element="s:SubtractResult"/>   </message>   <message name="SubtractMsgIn">     <part name="parameters" element="s:Add"/>   </message>   <message name="SubtractMsgOut">     <part name="parameters" element="s:SubtractResult"/>   </message>   <message name="CalculateFaultMsg">     <part name="fault" element="s:CalculateFault"/>   </message>   <!-- More definitions will go here. --> </definitions>

I created a message element for the request and response message of the Add and Subtract methods. I could have instead specified a part element for each parameter. For example, the AddMsgIn message could have been written as follows:

  <message name="AddMsgIn">     <part name="x" type="xsd:int"/>     <part name="y" type="xsd:int"/>   </message>

Parameters x and y are contained within their own part of the message. The protocol binding will have a lot of influence over how messages are represented. When I discuss binding later in the chapter, I will represent each parameter contained within an HTTP query string as its own message part.

Because each part can serve as an abstract definition of a piece of data, a message can be composed of multiple pieces of data from multiple sources. Although it is not recommended, you could describe a message in which some of the parameters were encoded within a SOAP body and some of the parameters were encoded within the query string.

portType Element

The portType element contains a set of abstract operations representing the types of correspondences that can occur between the client and the server. For RPC-style Web services, a portType can be thought of as an interface definition in which each method can be defined as an operation.

A port type is composed of a set of operation elements that define a particular action. The operation elements are composed of the messages defined within the WSDL document. WSDL defines four types of operations, known as operation types:

  • Request-response RPC-style communication in which the client makes a request and the server issues a corresponding response.

  • One-way Document-style communication in which the client sends a message but does not receive a response from the server indicating the result of the processed message.

  • Solicit-response The opposite of the request-response operation. The server sends a request, and the client sends back a response.

  • Notification The opposite of the one-way operation. The server sends a document-style communication to the client.

An operation is composed of a subset of input, output, and fault elements. The type of elements and the ordering of the elements within the operation determine the type of operation. For example, one-way defines an input message, and request-response defines an input and an output message. The solicit-response and the notification operation types are the opposite of request-response and one-way, respectively. The solicit-response operation lists the output message and then the input message, and the notification operation contains an output message instead of an input message.

Table 5-1 lists the type and ordering of messages for each operation type.

Table 5-1  Message Ordering for Operation Types

Operation Type

input

output

fault

Request-response

1

2

3*

One-way

1

Solicit-response

2

1

3*

Notification

1

*  The fault message is optional. Any number of fault messages can appear in an operation.

Operations involving two-way communication can optionally specify one or more fault messages. Like Java method definitions, fault messages allow you to declare the type of exceptions that can be thrown by the server application. However, the list of possible faults should not include errors that are specified by the underlying transport protocol. For example, you would not need to represent the HTTP 500 error in the WSDL document.

The names of the input, output, and fault elements have a default value if one was not specified. For one-way and notification operation types, the default name is the name of the operation element in which they are contained. For request-response operation types, the name of the input and output elements default to the name of the operation with Request or Response appended to the end. For solicit-response, the name of the output element defaults to the name of the operation with Solicit or Response appended to the end.

Because multiple fault elements can be defined within an operation, there is no default name for the fault element. Therefore, each fault element must be uniquely named within its parent operation element.

Here is the portType definition for the Calculator Web service:

<?xml version="1.0" encoding="utf-8"?> <definitions targetNamespace="http://somedomain/Calculator/wsdl"  xmlns:tns="http://somedomain/Calculator/wsdl"  xmlns:xsd="http://www.w3.org/2001/XMLSchema"  xmlns="http://schemas.xmlsoap.org/wsdl/">   <!-- Type and message definitions removed for clarity -->   <portType name="CalculatorPortType">     <operation name="Add">       <input message="tns:AddMsgIn"/>       <output message="tns:AddMsgOut"/>       <fault message="tns:CalculateFaultMsg" name="CalculateFault"/>     </operation>     <operation name="Subtract">       <input message="tns:SubtractMsgIn"/>       <output message="tns:SubtractMsgOut"/>       <fault message="tns:CalculateFaultMsg" name="CalculateFault"/>     </operation>   </portType>   <!-- More definitions will go here. --> </definitions>

The preceding snippet of the Calculator WSDL document defines the portType named CalculatorPortType. It contains two request-response operations, Add and Subtract. Because the operations are of type request-response, they both define an input and an output message. Both operations also contain a fault element named CalculateFault.

RPC-style operations can optionally use the parameterOrder attribute to specify the order of the expected parameters. This attribute is of type nmTokens and contains a list of names of the parameters. Because SOAP specifies a clear way to serialize parameters and the name and ordering of the parameters can be described using XML Schema, this attribute is not often used.

Some services described using WSDL can support overloaded methods—methods that have the same name but accept a different set of parameters. Therefore, within a portType definition, more than one operation element can have the same name but specify different messages. In this case, the different operation elements must be identified by the combination of the operation name plus the name of the input, output, and fault elements. As a result, the default name for the input, output, and fault elements might not ensure that operation elements with the same name can be uniquely identified.

binding Element

The binding element contains binding definitions for binding a protocol such as SOAP to a particular bindingType. The binding definitions specify message formatting and protocol details. For example, the binding information specifies whether you can access an instance of a portType in an RPC-like manner.

The binding definitions also indicate the number of network communications required to perform a particular action. For example, a SOAP RPC call over HTTP might involve one HTTP communication exchange, but that same call over SMTP would involve two discrete SMTP communication exchanges.

Binding is accomplished through the use of extension elements. Each protocol has its own set of extension elements for specifying the details of the protocol and the formatting of the messages. For a particular protocol, extension elements are often used to decorate the individual actions within an operation and the operation itself with protocol binding information. Sometimes, extension elements are used at the portType level itself.

The following simplified WSDL document shows the binding for the Calculator Web service. It also contains placeholders for extensibility elements to show where they can be placed in relation to the containing binding element. (I discuss extensibility elements defined by the WSDL specification later in the chapter.)

<?xml version="1.0" encoding="utf-8"?> <definitions xmlns:ext="http://somedomain/MyBindingExt"  xmlns="http://schemas.xmlsoap.org/wsdl/">   <!-- Type, message, and port type definitions removed for clarity -->   <!-- All attributes also removed for clarity -->   <binding name="CalculatorBinding" type="tns:CalculatorPortType>     <ext:SomeExtElement/>     <operation name="Add">       <ext:SomeExtElement/>       <input>         <ext:SomeExtElement/>       </input>       <output>         <ext:SomeExtElement/>       </output>       <fault>         <ext:SomeExtElement/>       </fault>     </operation>     <operation name="Subtract">       <ext:SomeExtElement/>       <input>         <ext:SomeExtElement/>       </input>       <output>         <ext:SomeExtElement/>       </output>       <fault>         <ext:SomeExtElement/>       </fault>     </operation>   </binding>   <!-- More definitions will go here. --> </definitions>

The binding element is associated with a particular portType element via the type attribute. In the preceding WSDL document, I associated the binding named CalculatorBinding with the CalculatorPortType port type. Within the binding element, I created two operation elements to correlate to those defined in the portType element.

Each operation element must have corresponding input, output, and fault elements defined in the portType element. In addition, the names of the operation element and its child input, output, and fault elements must exactly match the names of their counterparts defined in the corresponding portType element.

service Element

A service is a group of related ports and is defined by the service element. A port is a particular endpoint for the Web service that is referenced by a single address. Ports defined within a particular service are orthogonal. For example, the output of one port cannot serve as the input of another.

Here is a simplified service definition for the Calculator Web service. The document contains placeholders for extensibility elements to show where they can be placed in relation to the containing service element:

<?xml version="1.0" encoding="utf-8"?> <definitions xmlns:ext="http://somedomain/MyBindingExt"  xmlns="http://schemas.xmlsoap.org/wsdl/">   <!-- Type, message, port type, and binding definitions removed for clarity -->   <!-- All attributes also removed for clarity -->   <service name="CalculatorService">     <ext:SomeExtElement/>     <port name="CalculatorPort" binding="tns:CalculatorBinding">       <ext:SomeExtElement/>     </port>   </service>   <!-- More definitions will go here. --> </definitions>

The service element is used to group a set of related ports. The preceding WSDL document defines a service called CalculatorService. It contains one port called CalculatorPort. CalculatorPort is associated with the binding element CalculatorBinding.

A port contains an extension element that provides the address where it is located. If you need to specify more than one address, you must create one port for each address. If you define multiple ports of the same port type (and possibly different addresses) within the same Web service, they should be considered alternatives.

They should provide the same behavior, but over different transport protocols. The client can iterate through the ports to find a compatible binding with an appropriate portType and protocol.

Extensibility Elements

Extensibility elements are used to represent particular technologies. For example, you can use extensibility elements to specify the schema language used within the types element.

The schema for a particular set of extensibility elements must be defined within a different namespace than WSDL. The definition of the elements themselves can contain a wsdl:required attribute that specifies a Boolean value. If the required attribute is set to true within an element definition, a binding that references the particular set of extensibility elements must include that element.

Most often, extensibility elements are used to specify binding information. The WSDL specification defines sets of extension elements for binding to SOAP, HTTP GET, HTTP POST, and MIME. However, the specification defines the bindings for only two of the four operation types, one-way and request-response. Let's look at the three bindings supported by the .NET platform: SOAP, HTTP GET, and HTTP POST.

SOAP Extensions

The SOAP extensions provide a set of elements for binding a port type to a SOAP message sent over a particular transport protocol. For example, SOAP extension elements are used to indicate where the individual parts are located within the SOAP message. They are also used to indicate the transport protocol used to send the SOAP message.

SOAP extension elements are contained within the http://schemas.xmlsoap.org/wsdl/soap/ namespace. The convention I use in the rest of this chapter is to associate references to the namespace with the soap: moniker.

binding Element Binding

Extensibility elements added to the binding element provide information about how the parameters are encoded within the SOAP message. Extensibility elements are added to the bind, operation, input, output, and fault messages. They provide information about the transport protocol used to send the SOAP message and how the data is encoded within the SOAP envelope.

The soap:binding element's primary purpose is to signal that SOAP binding is applied to a particular binding definition. Therefore, all binding elements containing SOAP specific binding must contain the soap:binding element. The soap:binding element can also be used to specify the style of the message and the transport protocol that will be used to send the SOAP message. The following portion of the Calculator Web service WSDL document demonstrates the use of the soap:binding element:

<?xml version="1.0" encoding="utf-8"?> <definitions targetNamespace="http://somedomain/Calculator/wsdl"  xmlns:tns="http://somedomain/Calculator/wsdl"  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"  xmlns="http://schemas.xmlsoap.org/wsdl/">   <!-- Type, message, and port type definitions removed for clarity -->   <binding name="CalculatorBinding" type="tns:CalculatorPortType">     <soap:binding style="document"      transport="http://schemas.xmlsoap.org/soap/http"/>     <!-- Operation elements removed for clarity -->   </binding>   <!-- More definitions will go here. --> </definitions>

The soap:binding element can contain a transport attribute to specify a transport. The transport attribute must contain a URI that uniquely identifies the transport. The only URI defined in the specification is for the HTTP transport: http://schemas.xmlsoap.org/soap/http. Because the soap:binding element is applied to the entire binding definition, it will apply to all operations referenced by the binding definition.

The style of the message is indicated by the style attribute. The value is either rpc or document. If the style is set to rpc, each part within the operation will represent a parameter. The parameters must be encoded in the body of the SOAP message in a struct-like fashion as dictated by the SOAP specification. The name of the operation element must match the name of the element that contains the parameters in the SOAP message. If the style is set to document, the message parts will appear directly within the body of the SOAP message.

As you will see shortly, the message style can also be set at the operation level. Because the style attribute defined at the operation level takes precedence, setting the style attribute within the soap:binding element does not determine the message style; it merely sets the default value. If the style attribute is not set, the default value is document.

The soap:operation element provides binding information for the operation as a whole. You can use it to specify the document style as well as the SOAP Action HTTP header value for HTTP bindings. The following portion of the Calculator Web service WSDL document demonstrates the use of the soap:binding element:

<?xml version="1.0" encoding="utf-8"?> <definitions targetNamespace="http://somedomain/Calculator/wsdl"  xmlns:tns="http://somedomain/Calculator/wsdl"  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"  xmlns="http://schemas.xmlsoap.org/wsdl/">   <!-- Type, message, and port type definitions removed for clarity -->   <binding name="CalculatorBinding" type="tns:CalculatorPortType">     <soap:binding style="document"      transport="http://schemas.xmlsoap.org/soap/http"/>     <operation name="Add">       <soap:operation soapAction=http://somedomain/Calculator/Add"/>       <input>         <soap:body use="literal"/>       </input>       <output>         <soap:body use="literal"/>       </output>       <fault>         <soap:fault name="CalculateFault" use="literal"/>       </fault>     </operation>     <operation name="Subtract">       <soap:operation soapAction=http://somedomain/Calculator/Subtract"/>       <input>         <soap:body use="literal"/>       </input>       <output>         <soap:body use="literal"/>       </output>       <fault>         <soap:fault name="CalculateFault" use="literal"/>       </fault>     </operation>   </binding>   <!-- More definitions will go here. --> </definitions>

As I mentioned earlier, the style attribute can be set to either rpc or document to indicate the style of the message.

The soapAction attribute specifies the value of the SOAPAction header. The soapAction attribute is required if HTTP is the transport protocol. The value can be blank if the HTTP request URL adequately describes the intent of the message. The client should pass the value of the soapAction attribute unchanged when sending a message to the Web service. If the protocol is not HTTP, the soapAction attribute can be omitted.

The soap:body element specifies how parts of the message are encoded inside the SOAP message body. This element is used to specify which parts of a message appear within the SOAP message body. It can also be used to declare the type of encoding used to serialize the parts within the message body.

You can optionally specify the list of parts that can be found within the body of the SOAP message. The parts attribute can contain a list of named tokens, where each token is the name of a part contained within the SOAP body. If the parts attribute is not specified, all parts defined by the message are assumed to be included in the SOAP body. An example of where the parts attribute would be used is if an HTTP message contained a multipart message that included a SOAP message in addition to a MIME attachment. One part of the message not included in the SOAP body would be the attachment itself.

Sometimes a schema alone cannot adequately represent the way in which data can be serialized. For example, SOAP Encoding defines multiple ways that an array can be serialized: the entire array, a partial array, or a sparse array. (See Chapter 3 for more information.)

The use attribute is required and must be either literal or encoded. The literal value means that parts within the SOAP body must comply with the schema. The part within the message definition must reference the schema using either the type or element attribute.

If parts within the body should be serialized using a particular method of encoding, the value of the use attribute should be encoded. Each part of the message encoded within the SOAP body must reference an abstract type using the type attribute. For example, a part containing a SOAP array would reference the SOAP Array type. If the encoding style supports variations in the way data can be encoded (such as the SOAP Array type), the service must support all of these variations.

If parts of a message are based on abstract type definitions rather than a concrete format specified by a schema definition, the encoding style should be referenced. The encoding style is specified by the wsdl:encodingStyle attribute and can contain a white-space-delimited list of URIs (similar to the encodingStyle attribute defined by SOAP).

If an encodingStyle attribute is specified for a message part and the use attribute is set to literal, the encodingStyle will serve as a hint about how the data is encoded. This is handy if you want to accept only one variation of a particular SOAP encoded datatype. For example, a Web service might accept only SOAP arrays that are fully serialized.

service Element Binding

The only SOAP extension element specified within the service element is soap:address. It is contained within the port definition and is used to specify the URI of an endpoint or port where the Web service can be reached.

<?xml version="1.0" encoding="utf-8"?> <definitions targetNamespace="http://somedomain/Calculator/wsdl"  xmlns:tns="http://somedomain/Calculator/wsdl"  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"  xmlns="http://schemas.xmlsoap.org/wsdl/">   <!-- Type, message, port type, and binding definitions removed for clarity -->   <service name="CalculatorService">     <port name="CalculatorPort" binding="tns:CalculatorBinding">       <soap:address location="http://somedomain/Calculator"/>     </port>   </service> </definitions>

The service definition states that the Calculator Web service can be reached at http://somedomain/Calculator. If the address cannot be specified by a URI, the soap:address element can be replaced with a custom address element that does properly specify the location.

HTTP GET/POST Extensions

Sometimes it is desirable to invoke a Web service by passing the parameters as name/value pairs using the same mechanism as a standard HTML form post. Parameters can be passed via the query string or a form POST. This sometimes makes it easier for a client to invoke a Web service without having to create a well-formed SOAP message.

The HTTP GET/POST extensions provide a set of elements for binding port types to the SOAP protocol. For example, SOAP extension elements are used to indicate where the individual parts are located within the SOAP message. They are also used to indicate the transport protocol used to send the SOAP message.

In this section, I create two additional bindings for the Calculator Web service, one for HTTP GET and one for HTTP POST. I have a lot of freedom in how I specify the binding, so I will create bindings that closely parallel how Web services developed on the .NET platform behave. In particular, Web services developed using the .NET platform accept standard name/value pairs that are URL encoded and either appended on the query string or POSTed within the body of the HTTP request message. If results are returned, they are passed as a simple XML document in the body of the HTTP response message.

Before I specify the binding information, I need to create an additional element declaration to hold the value of the return parameters. Because individual parameters must be represented as individual parts of a message, I also need to create a couple of new message definitions for the Add and Subtract methods, where each parameter is contained within its own message part. Here are the additions:

<?xml version="1.0" encoding="utf-8"?> <definitions targetNamespace="http://somedomain/Calculator/wsdl"  xmlns:tns="http://somedomain/Calculator/wsdl"  xmlns:s="http://somedomain/Calculator/schema"  xmlns:xsd="http://www.w3.org/2001/XMLSchema"  xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"  xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"  xmlns="http://schemas.xmlsoap.org/wsdl/">   <!-- Note: Previously defined type definitions omitted for clarity -->   <types>     <schema attributeFormDefault="qualified" elementFormDefault="qualified"      xmlns="http://www.w3.org/2001/XMLSchema"      targetNamespace="http://somedomain/Calculator/schema">       <!-- Common result element for HTTP GET/POST binding -->       <element name="Result" type="int"/>     </schema>   </types>   <!-- Messages for HTTP GET/POST-based Web service -->   <!-- Note: Previously defined messages omitted for clarity -->   <message name="AddHttpMsgIn">     <part name="x" type="xsd:string"/>     <part name="y" type="xsd:string"/>   </message>   <message name="AddHttpMsgOut">     <part name="result" element="s:Result"/>   </message>   <message name="SubtractHttpMsgIn">     <part name="x" element="xsd:string"/>     <part name="y" element="xsd:string"/>   </message>   <message name="SubtractHttpMsgOut">     <part name="result" element="s:Result"/>   </message>   <!-- More definitions will go here. --> </definitions>

The preceding WSDL document defines a new element of type int called Result that will be used to contain the result of the Add and Subtract methods returned to the client. This element is referenced by two new outbound messages, one for each method. The document also defines new inbound messages for the Add and Subtract methods. The outbound messages define individual parts for each parameter. Since the name/value pairs containing the parameters are not strongly typed, the type of each part is defined as string.

HTTP GET/POST extension elements are contained within the http://schemas.xmlsoap.org/wsdl/http/ namespace. The convention I follow throughout the remainder of this chapter is to associate references to the namespace using the http: moniker. In a few scenarios, HTTP GET/POST bindings leverage the MIME extension elements. They are defined within the http://schemas.xmlsoap.org/wsdl/mime/ namespace and referenced using the mime: moniker.

binding Element Binding

Extensibility elements added to the binding element provide information about how the parameters are encoded within the HTTP message. Extensibility elements are added to the bind, operation, input, output, and fault messages.

The http:binding element specifies whether the parameters are passed within the URL or within the body of the HTTP request: The “verb” of the http:binding attribute is set to either GET or POST. The following WSDL document demonstrates the use of the http:binding element within the definition of the Calculator Web service:

<?xml version="1.0" encoding="utf-8"?> <definitions targetNamespace="http://somedomain/Calculator/wsdl"  xmlns:tns="http://somedomain/Calculator/wsdl"  xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"  xmlns="http://schemas.xmlsoap.org/wsdl/">   <!-- Type, message, and port type definitions removed for clarity -->   <binding name="CalculatorHttpGetBinding" type="tns:CalculatorPortType"/>     <http:binding verb="GET"/>     <!-- Operation elements removed for clarity -->   </binding>   <!-- More definitions will go here. --> </definitions>

The http:operation element specifies the relative address for each operation. Each input and output message is decorated with an extension element that indicates the method used to encode the parameters passed to the Web service. The three upcoming scenarios for encoding the parameters show the URL encoding of parameters on the query string, nonstandard encoding within the URL, and URL encoding of the parameters in the body of the post.

Parameters can be passed to a Web service via a URL encoded within the query string. URL encoding specifies appending a ? to the end of the URL and then appending a name/value pair separated with an =. If multiple name/value pairs are appended to the URL, they are separated from each other by an &. For example, the Add method can be called as follows:

http://somedomain/Calculator/Add?x=2&y=3

In this case, the input element within the binding for a particular operation would be decorated with an http:urlEncoded element. Here is the resulting HTTP GET binding definition for the Calculator Web service:

<?xml version="1.0" encoding="utf-8"?> <definitions targetNamespace="http://somedomain/Calculator/wsdl"  xmlns:tns="http://somedomain/Calculator/wsdl"  xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"  xmlns="http://schemas.xmlsoap.org/wsdl/">   <!-- Type, message, and port type definitions removed for clarity -->   <binding name="CalculatorHttpGetBinding" type="tns:CalculatorPortType"/>     <http:binding verb="GET"/>     <operation name="Add">       <http:operation location="/Add"/>       <input>         <http:urlEncoded/>       </input>       <output>         <mime:mimeXml part="Body"/>       </output>       <fault>         <mime:mimeXml part="Fault"/>       </fault>     </operation>     <operation name="Subtract">       <http:operation location="/Subtract"/>       <input>         <http:urlEncoded/>       </input>       <output>         <mime:mimeXml part="Body"/>       </output>       <fault>         <mime:mimeXml part="Fault"/>       </fault>     </operation>   </binding>   <!-- More definitions will go here. --> </definitions>

Parameters can also be encoded within the URL in a nonstandard way. In this case, the location attribute of the http:operation element will contain information about how the parameters are encoded. For example, the parameters for the Add method could be encoded within the URL as follows:

http://somedomain/Calculator/Add/2plus3

The parameters 2 and 3 were encoded within the path info of the URL where the parameters were delimited by plus. The resulting http:operation element would appear as follows within the binding definitions:

<http:operation location="Add/(x)plus(y)"/>

The individual message parts enclosed in parentheses are shown in their respective position within the relative URL. In this case, the input element within the binding for a particular operation would be decorated with an http:urlReplacement element.

The third and final way of encoding the parameters that I will discuss is embedding the URL encoded parameters within the body of the HTTP request message (HTTP POST). For example, the parameters would be encoded within the body of the HTTP request as follows:

Add="x=2&y=3"

In this case, the input element can be described using the MIME type application/x-www-form-urlencoded. Therefore, the operation element would be decorated with a mime:content element. Here is the resulting HTTP POST binding definition for the Calculator Web service:

<?xml version="1.0" encoding="utf-8"?> <definitions targetNamespace="http://somedomain/Calculator/wsdl"  xmlns:tns="http://somedomain/Calculator/wsdl"  xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"  xmlns="http://schemas.xmlsoap.org/wsdl/">   <!-- Type, message, and port type definitions removed for clarity -->   <binding name="CalculatorHttpPostBinding" type="tns:CalculatorPortType"/>     <http:binding verb="POST"/>     <operation name="Add">       <http:operation location="/Add"/>       <input>         <mime:content type="application/x-www-form-urlencoded"/>       </input>       <output>         <mime:mimeXml part="Body"/>       </output>       <fault>         <soap:fault name="CalculateFault" use="literal"/>       </fault>     </operation>     <operation name="Subtract">       <http:operation location="/Subtract"/>       <input>         <mime:content type="application/x-www-form-urlencoded"/>       </input>       <output>         <mime:mimeXml part="Body"/>       </output>       <fault>         <soap:fault name="CalculateFault" use="literal"/>       </fault>     </operation>   </binding>   <!-- More definitions will go here. --> </definitions>

The type attribute contains a valid MIME type used to indicate the type of content contained within the body of the HTTP message. The content of the HTTP message can also be labeled as being a member of a family of MIME types by using a wildcard. Here are a couple of examples:

<!-- The content belongs to the MIME family of text types. --> <mime:content type="text/*"/> <!-- Either declaration specifies all MIME types. --> <mime:content type="text/*"/> <mime:content/>

The mime:content element can also contain a part attribute, which is used to specify which part is contained within the body of the HTTP message.

If the message has a MIME type of multipart/related, the message can contain a collection of MIME-formatted parts. For example, a multipart message can contain a SOAP message (text/xml) along with a JPEG image (image/jpeg).

A multipart message can be represented within the binding definition using the mime:multipartRelated element. The mime:multipartRelated element contains a collection of mime:part elements. Each mime:part element represents a particular MIME-formatted part where its type is declared using the mime:content element.

The following example demonstrates how a multipart message containing a SOAP message and a JPEG image is represented within a WSDL document:

<mime:multipartRelated>   <mime:part>     <soap:body use="literal" part="xyCoordinates"/>   </mime:part>   <mime:part>     <mime:content type="image/jpeg" part="graph"/>   </mime:part> </mime:multipartRelated>

Notice that you can use the soap:body element to indicate that a particular MIME part contains a SOAP message. The message part is assumed to have a MIME type of text/xml and be contained within a valid SOAP envelope.

If the MIME message part contains XML but is not SOAP compliant, you can use the mime:mimeXml element. The associated part element defines the root XML element instead of the body of a SOAP message. This element is used extensively in ASP.NET because the HTTP GET/POST version of a Web service returns the results using non-SOAP-compliant XML.

service Element Binding

The only HTTP extension element specified within the service element is http:address. Like its SOAP counterpart, it is contained within the port definition and is used to specify the URI where the Web service can be reached. Here is the service definition for the Calculator Web service:

<?xml version="1.0" encoding="utf-8"?> <definitions targetNamespace="http://somedomain/Calculator/wsdl"  xmlns:tns="http://somedomain/Calculator/wsdl"  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"  xmlns="http://schemas.xmlsoap.org/wsdl/">   <!-- Type, message, port type, and binding definitions removed for clarity -->   <service name="CalculatorService">     <port name="CalculatorHttpGetPort" binding="tns:CalculatorHttpGetBinding">       <http:address location="http://somedomain/Calculator"/>     </port>     <port name="CalculatorHttpPostPort" binding="tns:CalculatorHttpPostBinding">       <http::address location="http://somedomain/Calculator"/>     </port>   </service> </definitions>

The preceding WSDL document defines two ports, one for HTTP GET and the other for HTTP POST. Both ports can be reached at http://somedomain/Calculator.

import Element

Like XML Schema documents, WSDL documents can import other documents. You can thus achieve the same level of modularity that you can with XML Schema documents. Because a WSDL document can get rather large rather quickly, breaking it up into a number of smaller documents can help make the document easier to understand and possibly easier to maintain.

A common way to divide a single service definition into multiple WSDL documents is to place protocol binding information in a separate document. This allows you to write the interface definitions once and then import them into a WSDL document that defines the specific protocols supported by a particular instance of the Web service.

Unlike its XML Schema counterpart, the import element must contain both a namespace and a location attribute. Imagine that I took the WSDL document for the Calculator Web service and separated it into three parts. I placed the schema definitions into Calculator.xsd, the interface definitions into i_Calculator.wsdl, and the protocol into Calculator.wsdl. Calculator.wsdl serves as the WSDL document for the Web service by importing the other two documents. Here is Calculator.wsdl:

<definitions xmlns="http://schemas.xmlsoap.org/wsdl/">   <!-- First import the schema definitions. -->   <import namespace="http://somedomain/myschema/"    location="http://somedomain/Calculator.xsd">   <!-- Next import the port types and message definitions. -->   <import namespace="http://somedomain/Calculator/"    location="http://somedomain/i_Calculator.wsdl">   <!-- Finally provide the protocol-specific binding definitions. --> </definitions>

Documentation

You can include documentation within a WSDL document by using the definitions element's name attribute or the document element. The name attribute can contain a short description of the WSDL document, and the document element can contain text as well as other elements. For example, I could use the document element to record metadata about the document.

<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"  name="The Calculator Web service provides the results of adding and  subtracting two numbers.">   <document>     <author>Scott Short</author>     <version>1.0</version>   </document>   <types>     <document>The following are defined using XML Schema.</document>     <!-- Type definitions removed for clarity -->   </types>   <!-- Additional definitions removed for clarity --> </definitions>

As you can see, the document element can be used inside any WSDL language element.



Building XML Web Services for the Microsoft  .NET Platform
Building XML Web Services for the Microsoft .NET Platform
ISBN: 0735614067
EAN: 2147483647
Year: 2002
Pages: 94
Authors: Scott Short

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