The Anatomy of WSDL


WSDL defines a Web service in two parts. The abstract definition contains a description of the Web service that is independent of the platform and language, with no mention of how messages are transported between the client and the server. The abstract definition specifies the interface to the service but not how to access that interface. The concrete definition adds the details describing how to access the Web service.

In theory, this separation into abstract and concrete definitions allows you to reuse the abstract definition to create several concrete definitions and therefore several different implementations of a given service. Or, to put it more succinctly, you can access the same Web service across different protocols.

However, as you’ll see as we move through the chapter, the abstract definition of a Web service is not truly abstract; it contains some implementation- specific details. You’ll also see when we look at UDDI in the next chapter that we don’t split the WSDL along these lines and that we consider the definition of the Web service to be the entire WSDL description of the service except its address.

It would be easy to simply rehash the WSDL specification as the bulk of this chapter. But instead we’re going to introduce WSDL in relation to a simple Web service similar to the one in Chapter 2. In that chapter, we looked at several examples that showed how to do complex things with the SOAP messages passed between the client and the server. The end result would be an application that’s too complex for our purposes, so here we’ll work with a simple Web service that implements only enough functionality for our purposes.

You can find the complete Web service for this chapter, RecordFinder, at http://localhost/wscr/03/RecordFinder.asmx; it contains all of the code that is introduced in this chapter but uses only the SOAP transport protocol. The complete Web service is rather complex and, because it uses only SOAP, doesn’t provide an ideal starting point to discuss WSDL. Instead, as a starting point we’ll take one of the methods, GetAlbumsForArtist, from the complete Web service and create a new service, SimpleRecordFinder, that exposes only this method. To show the use of various protocols with WSDL, this service has all three transport protocols enabled and can be found at http://localhost/wscr/03/ simple/SimpleRecordFinder.asmx.

Note

As you saw in Chapter 2, you can encode a SOAP message in five ways. Not surprisingly, the WSDL that’s generated depends on the way in which the SOAP message is encoded. In this chapter, we’ll introduce WSDL using the SimpleRecordFinder service, which has the default options for Web services in .NET that give us a message format that is document-oriented, nonencoded (literal), with wrapped parameters. You’ll see when we change the message formatting options in the “SOAP Message Formats” section that you can change the WSDL quite substantially.

As with all Web services created in .NET, you can look at the WSDL by appending ?wsdl to the URL. Rather than present the complete WSDL in one block, we’ll look at each part of the WSDL in turn. The WSDL for the SimpleRecordFinder service, and indeed all Web services, has several elements, as shown in Figure 3-1.


Figure 3-1: Major elements of WSDL and their relationships

The abstract definition of the Web service defines the service as a portType, and each portType has a series of operation elements. Within an operation you might have input, output, and fault messages that are defined to either the XSD schema or to type definitions in the WSDL file. When related to a .NET Web service, the portType is the class and an operation corresponds to an exposed method of that class.

The concrete definition of the service builds on the abstract definition and adds protocol-specific details to the portType to provide a binding. The binding also has operation elements, which correspond directly to the operation elements in the portType but are protocol-specific. The bindings are combined into a protocol-specific port, and the ports are combined to create the service.

We’ll cover the elements of the WSDL document in detail later in the chapter, but a brief introduction to the elements here will give you a good grounding and avoid a lot of needless “read-ahead” to the sections that follow:

  • Types The data type definitions used by the messages to be exchanged. These can be any typing scheme that the creator of the Web service wants to use, but WSDL assumes that the XSD definitions are used.

  • Message The definitions of the data that is to be transmitted. Each message is associated with one of the types defined or an XSD type. Messages can have multiple parts that allow different types to be combined into a single message.

  • PortType The abstract definition of the Web service. Each portType has a set of operations. An operation is the abstract definition of a method exposed by the service. Depending on the type of the operation, it might have input, output, and fault elements that map back to the defined messages.

  • Binding The concrete definition of the portType. Within the binding, you specify what protocol the binding uses. Each binding has a set of operations. In this case, an operation is the concrete definition of a method exposed by the service. Each binding operation maps back to a portType operation. Depending on the protocol being used, the operation might define the encoding used, the ordering of the messages within the operation, and so forth.

  • Service The concrete definition of the Web service, which is used to group together a set of ports. A port specifies the address of the Web service and ties that address to a specific binding.

The grammar used by WSDL to build a service definition file covers both the abstract and concrete definitions of the service. The core framework defines the overall service, and binding extensions are used to add the protocol-specific details to the service.

The WSDL specification supports three binding extensions (as discussed later in the chapter): HTTP, MIME, and SOAP. However, nothing precludes the addition of further binding extensions.

Document Structure

At the root of a WSDL document is a <definitions> element that contains all the other elements that describe the Web service. For our SimpleRecordFinder service, the <definitions> element is as follows:

<definitions     xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"     xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"     xmlns:s="http://www.w3.org/2001/XMLSchema"     xmlns:s0="http://www.notashop.com/wscr"     xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"     xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"     xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"     targetNamespace="http://www.notashop.com/wscr"     xmlns="http://schemas.xmlsoap.org/wsdl/">      </definitions>

As you can see, several namespaces are defined as part of the <definitions> element. The most important namespace is the one defined by the xmlns attribute. This is the root namespace for the <definitions> element; all child elements that aren’t prefixed are assumed to be in this namespace.

When you use the automatic facilities of Web services in .NET to generate the WSDL, you automatically have six namespaces defined and added to the WSDL, as shown in Table 3-1.

Table 3-1: Namespaces that .NET Defines When Generating WSDL

Prefix

Namespace URI

Definition

http

http://schemas.xmlsoap.org/wsdl/http

HTTP binding extensions

mime

http://schemas.xmlsoap.org/wsdl/mime

MIME binding extensions

s

http://www.w3.org/2001/XMLSchema

XSD schema

soap

http://schemas.xmlsoap.org/wsdl/soap

SOAP binding extensions

soapenc

http://schemasxmlsoap.org.soap/encoding

SOAP encoding namespace

tm

http://microsoft.com/wsdl/mime/textMatching

Text matching namespace

These six namespaces are added to the WSDL document regardless of whether they’re used. If you build a Web service that uses only the SOAP protocol, the HTTP binding extension prefix is still declared and added to the automatically generated WSDL.

Note

As you’ll see shortly, several of the element names in different namespaces clash, so you must be clear which namespace you’re referring to. In the remainder of this chapter, all elements that are referred to outside of code fragments will be prefixed with the namespace to which they belong. The exceptions are the elements that are part of the WSDL specification; these are used without any prefix.

The SimpleRecordFinder service also defines two namespaces that are specific to the service. The s0 prefix and the targetNamespace attribute for the <definitions> element both point at http://www.notashop.com/wscr, which is the namespace we’ve used throughout the book. These in combination allow us to place the elements that we define in the correct namespace and allow us to use the s0 prefix to reference those elements.

The <import> Element

The autogenerated WSDL for a Web service provides a complete description of the Web service, with everything in one file. It tells you everything you need to know, but it doesn’t make for the most readable of documents.

The WSDL specification defines the <import> element for importing other documents into the current file. The format of the element is as follows:

<import namespace="NamespaceURI" location="LocationURL" />

You specify the location of the document you want to import and the namespace you want the document to be imported as. Specifying the namespace for the imported document allows you to use elements defined in a namespace other than the namespace for the overall WSDL document. This might not be overly important when you’re writing the entire WSDL document, but if you need to use type definitions from other developers, for instance, you’ll soon run into naming conflicts.

From the brief description of the WSDL document so far, it should be obvious that you can split the document neatly into two parts. If you create an abstract definition document, and you import it into the concrete definition document, you can potentially reuse the same abstract definition in multiple concrete definitions. You can go even further and split the type definitions that are required into a separate document and import these into the abstract definition document.

Simply using the <import> element (without having to make any additional changes to a WSDL document) makes the reuse and maintenance of documents easier.

The <documentation> Element

Within each WSDL element you can add a <documentation> element to provide human-readable documentation. This documentation can contain both text and valid XML elements because it is not processed as part of the WSDL.

The simple case of a string of text

<documentation>NotAShop.com record store</documentation>

is as valid as:

<documentation>   <author>Mr. Smith</author>   <date>20th March 2002</date>   <version>1.0.24.3112</version> </documentation> 

The Core Framework

In the <definitions> element you define the entire Web service using a series of elements that match ones shown earlier in Figure 3-1. As you can see by pointing your browser to http://localhost/wscr/03/simple/SimpleRecordFinder.asmx?wsdl, the WSDL for the SimpleRecordFinder service is quite a long document. However, the overall structure is relatively simple. If you take a WSDL document and strip out any details specific to a particular service, you’re left with a WSDL shell:

<?xml version="1.0" encoding="utf-8" ?>  <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"   xmlns:s="http://www.w3.org/2001/XMLSchema">   <types>     <s:schema>            </s:schema>     <-- extensibility element -->   </types>   <message>     <part />          <part />   </message>      <message>     <part />          <part />   </message>   <portType>     <operation>       <input />       <output />       <fault />     </operation>          <operation />   </portType>      <portType />   <binding>     <!—- binding extension element -->     <operation>       <!—- binding extension element -->       <input>         <!—- binding extension element -->       </input>       <output>         <!—- binding extension element -->       </output>       <fault>         <!—- binding extension element -->       </fault>     </operation>          <operation />   </binding>        <binding />   <service>     <port>       <!—- binding extension element -->     </port>          <port />   </service> </definitions>

Although the WSDL document is written with the abstract details at the top of the document and the concrete details at the end, you can more easily understand what’s going on if you consider the elements in the other direction.

In a WSDL document, only one <service> element is defined; it contains a <port> element for each protocol supported by the Web service. A <port> is mapped to a <binding>, so it follows that there is also a <binding> element for each protocol. Within each <binding> element is an <operation> element that corresponds to the <operation> element defined in the <portType>. All of the elements that make up the concrete definition of the service have extensibility elements within them that specify the physical implementation of the service— you can see these in a WSDL document by looking for the elements prefixed with http, mime, and soap.

The abstract definition of the Web service is described by the <portType> element. Within this element is a series of <operation> elements that correspond to the exposed methods of the Web service. Each <operation> element can contain <input>, <output>, and <header> elements that specify messages that are used in accessing the Web service. The messages themselves are defined in <message> elements, and these point at elements and types defined in the <types> section of the WSDL document.

Note

In an ideal world, we’d have one <portType> element describing the Web service and multiple <binding> elements that build on it to provide concrete implementations of the service. This was the original vision of the authors of the WSDL specification. As you can see by looking at the WSDL for SimpleRecordFinder, this is not the case in the real world; we have a complete set of definitions for each of the protocols that the service supports.

The <service> Element

The <service> element is the concrete definition of the service. It contains a <port> element for each binding that the service supports. If you look at the WSDL for the SimpleRecordFinder service, you can see that it follows that basic structure and that we have a <port> element for each protocol that the service supports:

<service name="SimpleRecordFinder">   <port name="SimpleRecordFinderSoap"    binding="s0:SimpleRecordFinderSoap">        </port>   <port name="SimpleRecordFinderHttpGet"    binding="s0:SimpleRecordFinderHttpGet">        </port>   <port name="SimpleRecordFinderHttpPost"    binding="s0:SimpleRecordFinderHttpPost">        </port> </service>

The naming rules for the <service> and <port> elements require that they be unique within the WSDL file. In .NET, the names are generated based on the class name of the Web service and the protocol used. As you can see for the SimpleRecordFinder service, the <service> is named SimpleRecordFinder and the <port> elements are suffixed with the protocol used by that particular port.

If you look at the <port> elements, you’ll see that they each have a binding attribute that points at a given <binding> element in the WSDL file.

The <binding> Element

The <binding> element is the element in the WSDL file that ties together the concrete definition and the abstract definition. As you’ve seen from the details for the <port> elements, we have a <binding> element for each of the protocols that the Web service supports. Looking at the WSDL for the SimpleRecordFinder service, you can see that this is indeed the case:

<binding name="SimpleRecordFinderSoap" type="s0:SimpleRecordFinderSoap">      <operation name="GetAlbumsForArtist">          <input>            </input>     <output>            </output>   </operation> </binding> <binding name="SimpleRecordFinderHttpGet"  type="s0:SimpleRecordFinderHttpGet">      <operation name="GetAlbumsForArtist">          <input>            </input>     <output>            </output>   </operation> </binding> <binding name="SimpleRecordFinderHttpPost"  type="s0:SimpleRecordFinderHttpPost">      <operation name="GetAlbumsForArtist">          <input>            </input>     <output>            </output>   </operation> </binding>

You can see that the <binding> elements have the same naming scheme as the <port> elements we looked at previously. The elements must have unique names, and in the autogenerated WSDL they’re named after the class name and the protocol they use. Within the <binding> element is one <operation> element for each method exposed by the Web service; not surprisingly, these have the same names as the methods. An <operation> element might contain one <input> and one <output> element or any combination, and there’s an element here if there’s an element within the corresponding <portType> element.

Note

The WSDL specification defines a <fault> element that can also exist within the <operation> element. As you saw in the previous chapter, SOAP faults are generated by exceptions within the Web service, and these are handled automatically by the .NET runtime at both the client and the server. Nothing is added to the autogenerated WSDL to handle SOAP faults. Full details of the <fault> element are not discussed here; see the WSDL specification for more details.

You can also see that if we take away the details from the extensibility elements, the three <binding> elements are identical. It’s the details we add via the extensibility elements—the encoding used, the location of the operations, and so forth—that make the <binding> elements useful.

Finally, note that each <binding> element has a <type> attribute, which is used to bind a particular <binding> to a <portType>.

The <portType> Element

The <portType> element is the abstract definition of the service. You can use it to build the basic interface of the service. Within the <portType> element are a series of <operation> elements, which correspond to the <operation> elements within the <binding> element.

The basic structure of the <portType> element is quite simple, as you can see in the WSDL for the SimpleRecordFinder service:

<portType name="SimpleRecordFinderSoap">   <operation name="GetAlbumsForArtist">     <input message="s0:GetAlbumsForArtistSoapIn" />     <output message="s0:GetAlbumsForArtistSoapOut" />   </operation> </portType> <portType name="SimpleRecordFinderHttpGet">   <operation name="GetAlbumsForArtist">     <input message="s0:GetAlbumsForArtistHttpGetIn" />     <output message="s0:GetAlbumsForArtistHttpGetOut" />   </operation> </portType> <portType name="SimpleRecordFinderHttpPost">   <operation name="GetAlbumsForArtist">     <input message="s0:GetAlbumsForArtistHttpPostIn" />     <output message="s0:GetAlbumsForArtistHttpPostOut" />   </operation> </portType>

The <portType> element follows the same naming scheme as the <binding> and <port> elements, and the <operation> element has the same name as its counterpart within the <binding> element.

Within each <operation> element is a series of elements that correspond to the messages that are required to communicate with the Web service. The elements allowed within the <operation> element need not always be present, but if they are, there can be only one <input> element and one <output> element. Because there is only one of each element, it is not necessary to name these elements. The <input> and <output> elements each possess a message attribute that references a <message> element defined elsewhere in the WSDL document.

Note

As with the <binding> element, we’d also have a corresponding <fault> element here if one existed in the <binding>. See the WSDL specification for more details.

For the SimpleRecordFinder service, we have a simple request-response scenario, and we have an <input> and an <output> element that correspond to parameters and return values required by the exposed method. Although request-response is the nearly ubiquitous format for accessing a remote method, the WSDL specification supports three other scenarios for accessing a method within a Web service:

  • One-way The client sends a request to the Web service and requires no reply.

  • Solicit-response The Web service sends a message and receives a response from the client.

  • Notification The Web service sends a message and requires no reply.

The operation type is not specified directly within the WSDL file; rather, it is inferred from the presence and ordering of the child elements of the <operation> element. A request-response operation has an <input> element and then an <output> element. The opposite operation, solicit-response, has the <output> element followed by the <input> element. For one-way and notification operations, you simply have the <input> or the <output> element. The notification operation has only the <output> element, and the one-way operation has only the <input> element.

Although the base WSDL structure specifies all four scenarios, only the one-way and request-response operations are defined as bindings by WSDL.

The <message> Element

The <message> element defines a message that will pass between the client and the server. Things start to get a little tricky here. As we discussed briefly, implementation-specific details are embedded in the abstract definition of the service, and these details depend on the protocol in use. This is further complicated by the various options available for encoding SOAP messages.

If you look at the autogenerated <message> elements for the SimpleRecordFinder service, you can see these complications and that we have a set of messages for each protocol:

<message name="GetAlbumsForArtistSoapIn">   <part name="parameters" element="s0:GetAlbumsForArtist" /> </message> <message name="GetAlbumsForArtistSoapOut">   <part name="parameters" element="s0:GetAlbumsForArtistResponse" /> </message> <message name="GetAlbumsForArtistHttpGetIn">   <part name="strArtist" type="s:string" /> </message> <message name="GetAlbumsForArtistHttpGetOut">   <part name="Body" element="s0:ArrayOfString" /> </message> <message name="GetAlbumsForArtistHttpPostIn">   <part name="strArtist" type="s:string" /> </message> <message name="GetAlbumsForArtistHttpPostOut">   <part name="Body" element="s0:ArrayOfString" /> </message>

Within each <message> element is a <part> element that corresponds to a piece of data that must be passed. For the SimpleRecordFinder service, we have only one part per message, but it is quite possible to have multiple parts, and these are accommodated by simply having multiple <part> elements within a <message>, the ordering of the <part> elements reflecting the order expected by the method.

A <part> element can reference any of the types defined or imported into the WSDL document. For the XSD typing system, WSDL defines two attributes that can be used on <part> elements, only one of which can be used in a given <part> element:

  • element References an <s:element> defined in the types section

  • type References an <s:simpleType> or an <s:complexType> defined in the types section

Each <message> must have a unique name within the WSDL document. .NET gives it the default name constructed from the method name, the protocol, and the direction of the message. The naming of the <part> elements is slightly more complex; it depends on the protocol and, for SOAP, the message format being used. You can name the <part> elements in three ways, as described in Table 3-2.

Table 3-2: Naming of <part> Elements

Protocol

“In” Message

“Out” Message

HTTP

Parameter name in code

Always Body

Wrapped SOAP

Always parameters

Always parameters

Bare SOAP

Parameter name in code

Result appended to method name

As you can see from the table, for the HTTP protocol the naming rules are quite simple. These also translate to the types and elements used, and if you think about how the message is passed from the client to the server, this makes sense. You can’t encode messages sent via HTTP in the same manner that you can encode messages sent via the SOAP protocol. WSDL for HTTP is simple; it’s SOAP that causes the complexities.

For the default SOAP message format, which we’re using with SimpleRecordFinder, you always bind the <part> elements to a defined <s:element> in the <types> section. For the other SOAP message formats, this is not always the case, as you’ll see in the “SOAP Message Formats” section later in the chapter.

The <types> Element

The <types> element defines the data that the network service uses in the message transfer. Although WSDL allows any type system to be used, it assumes that XSD is being used, and .NET uses this type schema exclusively.

A complete discussion of XSD is beyond the scope of this book, and the intricacies of XSD are best left to other books such as Definitive XML Schema by Priscilla Walmsley (Prentice Hall, 2001). We will, however, talk about how the SOAP message format affects the types that are defined.

For the default SOAP message format that we’re using with SimpleRecordFinder, you always define <s:element> elements that wrap complex types that ultimately refer to either an XSD complex or intrinsic type. For the other SOAP message formats, this is not always the case, as you’ll see in the “SOAP Message Formats” section later in the chapter.

The Binding Extensions

We already discussed why you need binding extensions, and we briefly looked at what they allow you to do. Before we dive into the specifics of the three extensions defined by WSDL, it is worthwhile to discuss what’s missing from the WSDL file as it stands.

You saw earlier that in the <service> and <binding> elements we laid the foundation for the protocol-specific information to be added. We have a service that has a series of ports, and each port has a binding that details the operations that are possible on each port. Did you notice that we’re missing the addressing details? Nowhere in the core framework does it mention the address of a service—it’s up to the binding extensions to define this address.

We also barely discussed how the messages are to be transmitted across the wire. We have an abstract definition of the messages provided by the <message> elements, but how does this get across the wire? Do we send it as XML? What if it’s an image? How do we specify that we want to send an image across the wire? Again, the binding extensions come to the rescue.

As noted earlier, WSDL defines binding extensions for HTTP, MIME, and SOAP. We’ll start with a look at the HTTP binding extensions because these are the least complex and have the fewest options.

The MIME binding extensions are the odd man out of the three binding extensions described in the WSDL specification. Rather than relating to a protocol that allows the Web service to be accessed, the MIME binding extensions provide a means of encoding arbitrary data into a format that can be transported as part of a request to the Web service using the HTTP or SOAP protocol.

SOAP is the most complex binding extension defined in the WSDL specification. As you saw in Chapter 2, SOAP has options for the encoding used, the type of call, whether the messages are wrapped or bare, and so forth. We’ll cover each of these options and see how they affect the WSDL that is generated.

HTTP Binding Extensions

The HTTP binding extensions describe the interface provided by the Web service to users of the HTTP protocol. Although HTTP 1.1 defines eight methods of access across HTTP, only the GET and POST methods have bindings defined by WSDL 1.1.

The schema for the HTTP binding extensions can be found at http://schemas.xmlsoap.org/wsdl/http. As you’ve seen, .NET adds this schema to the WSDL document with a namespace prefix of http.

Data returned from a Web service accessed using HTTP is returned as an XML document, with the names of the types returned used as the XML tags. The same document is returned regardless of whether you access the Web service using the GET method or the POST method.

The differences between the two methods become apparent when you look at how to send data to the Web service—that is, how to pass the parameters to the service. You can pass the parameters to the Web service in three ways—two ways that use HTTP-GET and one that uses HTTP-POST:

  • HTTP-GET with the payload replacing the URL, as in /service.asmx/ 34/45/56.

  • HTTP-GET with the payload as a query string, as in /service.asmx?a=34&b=45&c=56.

  • HTTP-POST with the payload in the body of the request. For example, the body of the request would be a=34&b=45&c=56.

If you look at the WSDL generated for the two versions of the HTTP protocol for the SimpleRecordFinder service, you’ll see that they differ only in the HTTP binding extension used in the <input> element and the verb attribute of the <http:binding> element. Rather than show both versions, we’ll simply show the HTTP-GET version here:

<binding name="SimpleRecordFinderHttpGet"  type="s0:SimpleRecordFinderHttpGet">   <http:binding verb="GET" />   <operation name="GetAlbumsForArtist">     <http:operation location="/GetAlbumsForArtist" />     <input>       <http:urlEncoded />     </input>     <output>       <mime:mimeXml part="Body" />     </output>   </operation> </binding> <service name="SimpleRecordFinder">   <port name="SimpleRecordFinderHttpGet"    binding="s0:SimpleRecordFinderHttpGet">     <http:address      location="http://localhost/wscr/03/simple/SimpleRecordFinder.asmx"     />   </port> </service>

Although not part of the HTTP binding extensions, the MIME extension bindings are shown in the HTTP outline because it is not possible to return data from an HTTP operation without reference to the MIME extensions.

Note

Although we’ll discuss both <http:urlEncoded> and <http:urlReplacement> in the sections that follow, .NET always uses <http:urlEncoded> when accessing a Web service using the HTTP- GET protocol and always uses the <mime:content> element when accessing using the HTTP-POST protocol. .NET has no facilities to change this.

The <http:binding> element

The <http:binding> element indicates that the binding uses the HTTP protocol and specifies which method the protocol uses. The basic format of the element is as follows:

<http:binding verb="Method">

The verb attribute specifies which method of the HTTP protocol the binding is using—GET or POST. Note that the attribute is case sensitive.

The <http:operation> element

The <http:operation> element specifies the location of an operation relative to the address given in the <http:address> element. The basic format of the element is as follows:

<http:operation location="OperationURL">

The location attribute must be a relative URL; it is combined with the location specified in the <http:address> element to generate the complete URL for the operation.

For the GET method of accessing the Web service, you have two options for passing parameters to the Web service. Depending on the option you choose, you might have something slightly different than a simple relative URL. Specifying <http:urlReplacement> for an <input> operation requires the location attribute of the <http:operation> to be modified. We’ll explain this in more detail shortly.

The <http:urlEncoded> element

The <http:urlEncoded> element indicates that the input parameters to the Web service are to be encoded using the standard URL encoding rules. The element has no attributes, and it can simply be added as a child of the <input> element.

The names of the parameters correspond to the names of the message parts, and parameters are separated with the & character. For the GET method, the parameter list is simply appended to the end of the URL after the ? character has been added. This is equivalent to the query string method of passing parameters to pages. For the POST method, the query string is still used but is passed as the content of the message rather than appended to the URL.

The <http:urlReplacement> element

The <http:urlReplacement> element is valid only for the GET method of accessing the Web service. With URL replacement, all the parameters to the Web service are encoded into the URL.

The replacement follows quite a simple algorithm and relies on the location attribute of the <http:operation> element containing the parameters to be replaced.

Within the location attribute of the <http:operation>, you enclose each parameter you want to pass within parentheses; the name within the parentheses is the name of the message part you want to replace. Each message part is then replaced with the value that’s expected when the method call is made. So if we want to access a Web service at /service.asmx/34/45/56 and the parameters to our call are a, b and c, the <http:operation> element becomes

<http:operation location="/service.asmx/(a)/(b)/(c)" />

The <http:address> element

The <http:address> element specifies the base URL for the port. There can be only one address element for each port. It is combined with the <http:operation> element to give the complete URL for the Web service. The basic format of the <http:address> element is as follows:

<http:address location="LocationURL">

The location attribute must be a fully qualified URL; it is automatically updated by .NET to be the current location of the Web service. If you use WSDL files that are not generated automatically, you obviously need to change this to the correct location.

MIME Binding Extensions

The MIME binding extensions allow arbitrary data to be encoded and passed to and from Web services. They allow any type of data that can be MIME-encoded to be used as a parameter to or a return value from a Web service.

The schema for the MIME binding extensions can be found at http://schemas.xmlsoap.org/wsdl/mime; .NET adds this to the WSDL document with a namespace prefix of mime.

Unlike the HTTP and SOAP binding extensions, the MIME binding extensions are added to the WSDL file as children of the <input> or <output> element and cannot be used without one of the other two binding extensions.

.NET does not natively support the MIME extensions—we cannot, for instance, pass images as parameters to and from Web services. If we want to do this we are moving into the realm of the Web Service Enhancements (WSE) that are covered in Chapter 13.

Note

.NET always defines the HTTP bindings to use <mime:content> for the input to a HTTP-POST method and always uses <mime:mimeXml> as the return from both HTTP-GET and HTTP- POST methods. The MIME binding extensions are never used in combination with the SOAP protocol.

The <mime:content> element

The simplest MIME binding extension you can use is the <mime:content> element, whose basic format is as follows:

<mime:content part="MessageName" type="MimeType">

The part attribute specifies which part of the message the binding applies to. If the message has only one part, you don’t need to specify this attribute.

The type attribute specifies the MIME type. If you don’t specify it, all MIME types are assumed to be acceptable. A MIME type has two sections, separated by a slash; you can use the wildcard (*) character to specify that you want to allow an entire family of MIME types.

For example, if you want to allow only the “text/xml” MIME type, you can specify the <mime:content> element as follows:

<mime:content type="text/xml">

If you want to allow the entire text MIME type family, you can specify the element as follows:

<mime:content type="text/*">

The <mime:mimeXML> element

The <mime:mimeXML> element indicates that the data you’re expecting to receive is an XML document—that is, a “text/xml” document that adheres to the schema of the referenced message part. The basic syntax for the <mime:mimeXml> element is as follows:

<mime:mimeXml part="MessageName">

As with the <mime:content> element, the part attribute specifies which part of the message the binding applies to. If the message has only one part, you don’t need to specify this attribute.

The <mime:multipartRelated> element

The <mime:multipartRelated> element is used to combine several MIME elements into one message using the multipart/related MIME type. The basic syntax for the <mime:multipartRelated> element is as follows:

<mime:multipartRelated>   <mime:part>     <mime:content> or <mime:mimeXml> or <mime:multipartRelated>   </mime:part>      <mime:part /> </mime:multipartRelated>

A <mime:multipartRelated> element must have at least one <mime:part> element within it. Within the <mime:part> element, you specify the individual MIME binding extensions that make up the parts of the message. If more than one MIME binding extension is within a <mime:part>, they indicate alternatives; only one of them can be present in the transmitted message.

SOAP Binding Extensions

By now you should be wondering about the role of SOAP in Web services. We’ve discussed how to describe a SOAP-free Web service in WSDL, how to accept HTTP-GET and HTTP-POST requests, and how to return data formatted as some arbitrary MIME type. WSDL is certainly not limited to SOAP. But as the only transport-independent Web service protocol, SOAP is important and is the basis for the majority of the work occurring in the Web services arena. In the previous chapter, we walked through all the options for using the SOAP protocol as the transport mechanism for Web services.

The schema for the SOAP binding extensions is at http://schemas.xmlsoap.org/wsdl/soap; .NET adds this to the WSDL document with a namespace prefix of soap.

You add the SOAP binding extensions to the WSDL in the same way that you add the HTTP binding extensions, as you can see in the WSDL for the SimpleRecordFinder service at the top of the next page.

<binding name="SimpleRecordFinderSoap" type="s0:SimpleRecordFinderSoap">   <soap:binding transport="http://schemas.xmlsoap.org/soap/http"     style="document" />   <operation name="GetAlbumsForArtist">     <soap:operation      soapAction="http://www.notashop.com/wscr/GetAlbumsForArtist"      style="document" />     <input>       <soap:body use="literal" />     </input>     <output>       <soap:body use="literal" />     </output>   </operation> </binding> <service name="SimpleRecordFinder">   <port name="SimpleRecordFinderSoap"    binding="s0:SimpleRecordFinderSoap">     <soap:address      location="http://localhost/wscr/03/simple/SimpleRecordFinder.asmx"     />   </port> </service> 

In addition to the four elements in the WSDL above, there are another two that aren’t used in this Web service. The <soap:fault> element sits inside a <fault> element, and the <soap:header> element sits inside the <input> or <output> element if you’re using SOAP headers.

Note

.NET does not use the <fault> element, so it doesn’t use the <soap:fault> element, either. See the WSDL specification for more details.

The <soap:binding> element

The <soap:binding> element is used in the same way as the <http:binding> element; it indicates that the SOAP protocol is being used. The basic format of the <soap:binding> element is as follows:

<soap:binding transport="TransportSchema" style="rpc|document">

The value for the style attribute specifies whether the operations in the binding are RPC-oriented or document-oriented; if a value isn’t specified, the style attribute defaults to document.

The transport attribute specifies the underlying transport that the binding is using. SOAP currently defines only the HTTP transport; its schema is at http:/ /schemas.xmlsoap.org/soap/http. You can use other transports (such as FTP and SMTP), but the details for these have not been defined yet, and as far as we know, no Web services have been built that use protocols other than HTTP.

The <soap:operation> element

The <soap:operation> element is used in the same way as the <http:operation> element; it provides settings that affect the operation as a whole. Unlike the HTTP version, the SOAP version doesn’t have a location attribute because the details about the method we’re trying to access is contained in the SOAP envelope. The basic format of the <soap:operation> element is as follows:

<soap:operation soapAction="ActionURL" style="rpc|document">

The style attribute indicates whether the operation is RPC-oriented or document-oriented. If the attribute is not specified, the value specified for the <soap:binding> element is used.

The soapAction attribute specifies the value of the SOAPAction header for the operation. For the HTTP transport this value is required, and it has no default value. In .NET, it defaults to the operation name appended to the namespace of the service.

The <soap:body> element

The <soap:body> element defines the Body element of the SOAP envelope. The basic format is as follows:

<soap:body parts="PartsList" use="literal|encoded"     encodingStyle="StlyeURL" namespace="NamespaceURL" />

The parts attribute indicates which parts of the message are contained within the SOAP body, with the message determined from the <portType> element that the <binding> element references. If you don’t specify a parts attribute, all parts of the message are assumed to be contained in the SOAP body.

The use attribute indicates whether the message parts are literal or encoded. If the method expects literal parameters, the encodingStyle and namespace attributes are not present; if the method expects encoded parameters, the encodingStyle attribute lists the encodings used by the message and the namespace attribute is used to point at the namespace of the message.

The <soap:header> element

Although not used by the SimpleRecordFinder service, the <soap:header> element defines the Header element of the SOAP envelope and has a syntax similar to that of the <soap:body> element:

<soap:header message="MessageName" part="PartName" use="literal|encoded"  encodingStyle="StlyeURL" namespace="NamespaceURL" /> </soap:header>

The use, encodingStyle, and namespace attributes are used in the same way as the <soap:body> element.

The message and part attributes reference the <message> element and the part of the enclosed message that defines the header type. You must specify which message you’re referring to because the SOAP headers are specific to the SOAP binding extensions and therefore have no intrinsic referencing within WSDL, as the <soap:body> element does.

Note

The WSDL specification also specifies a <soap:headerfault> element that allows problems with the header to be communicated back to the client. As with the handling of faults in the SOAP body, the handling of errors in the SOAP header is automatic. See the WSDL specification for more details.

The <soap:address> element

The <soap:address> element is used in the same way as the <http:address> element. It indicates the address of the Web service. It is the only element in the SOAP binding extensions that indicates the address of the Web service because the details about the method called are contained in the SOAP envelope.

The basic format of the <soap:address> element is as follows:

<soap:address location="LocationURL">

The location attribute must be a fully qualified URL.




Programming Microsoft. NET XML Web Services
Programming MicrosoftВ® .NET XML Web Services (Pro-Developer)
ISBN: 0735619123
EAN: 2147483647
Year: 2005
Pages: 172

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