In this multi-part blog im going to talk through how to set up a php soap (Simple Object Access Protocol) server that can be added as a web-reference through visual studio. Im mainly doing this because it took me along time to figure out the finer details of wsdl and soap, and i’d like to try and save other people the same hassle.
The example soap service that i will build for demonstration purposes will be a simple schedule service, that can be queried to find out what meeting is next and todays meeting schedule.
Part 1: Introduction to WSDL
Skip this section if you are familiar with xml.
Xml is in the same form as html but instead of describing how to format its contents (tables/headings etc..), xml describes the content so
could contain a name, it does not define how to format the contents (XSL Transformations can be used to this end, although i wont describe them here, w3schools has a tutorial).
A simple xml document could go as follows
<?xml version="1.0" encoding="utf-8"?> <xmldoc xmlns="http://example.com/test"> <element attribute="value"> Im some data!! </element> </xmldoc>
As you can see an xml document needs a root element (xmldoc here) and a namespace, it also needs the tag at the top to describe what version the xml is and its encoding, this doesnt need to change under normal circumstances, although you may want to change the encoding.
The xmlns above says that this document and all the elements in it are described in the namespace ‘http://example.com/test’, a namespace is simply a placeholder to differentiate between different sets of xml schemas such as xhtml and wdsl. the namespaces name can be either a url (as above), the address need not exist but should be relevant to the content in which it is used, or it can be a urn.
References to other namespaces can be provided in the root element of a xml document like this:
<xmldoc xmlns"http://example.com/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:element /> </xmldoc>
Here we have referenced the xmlschema namespace and assigning it the shorttag ‘xsd’ and used the self-closing ‘element’ tag from it by referencing ‘xsd’.
As for schemas, a good tutorial is available from the w3c here.
The schema file ive created for this service can be found at http://www.xnet.tk/test-soap/schema.xsd.
Wsdl stand for Web Service Description Language and describes how a service should function, it is generally used to describe soap services, although it does have the capability to describe REST style services, I have found this to be not well supported nor documented (barring the w3c spec).
A WSDL file has 4 sections to it (5 if you include the xml schema).
- Messages – these describe what information is going between the client and server.
- PortTypes – these describe what operations the service supports and what input and outputs (messages) are expected for each operation.
- Bindings – these describe how the operations communicate (in this case soap operations) and where they communicate with (address).
- And finally the service section – this defines which binding and port type a particular web address provides.
Ive created a wsdl file for this service and can be found at http://www.xnet.tk/test-soap/soap.wsdl
Ive found that for a service to function properly each operation must have an input message and an output message, even if the input message is empty, so in the wsdl file you will find a Request and Response message for each operation, where the request message is empty.
Below is a typical message declaration, it declares the message as containing one part of type Meeting in the xts namespace (which is referenced to ‘http://www.xnet.tk/test-soap’)
<message name='GetNextMeetingResponse'> <part name='Meetings' type='xts:Meeting' /> </message>
The porttype section simply describes what operations use which messages as their inputs and outputs. for example:
<operation name='GetNextMeeting'> <input message='GetNextMeetingRequest' /> <output message='GetNextMeetingResponse' /> </operation>
This says that the operation GetNextMeetings will have the input of message type GetNextMeetingRequest and will output a message of type GetNextMeetingResponse. Simple so far eh?
So now that we’ve described what the operations will input and output, we need to say how that will communicate that. In this case with soap.
<binding name='ServiceBinding' type='ServicePortType'> <soap:binding style='rpc' transport='http://schemas.xmlsoap.org/soap/http'/> <operation name='OperationThatExistsInThePortTypeAbove'> Stuff about the operation (covered in a bit) </operation> </binding>
Here we have defined the ServiceBinding Binding that describes the communication method of the PortType. we can also see the first use of soap, in this case to describe the method of transport and using the rpc (Remote Procedure Call) style.
The operation GetNextMeeting would have an operation description such as
<operation name='GetNextMeeting'> <soap:operation soapAction='http://www.xnet.tk/test-soap#GetNextMeeting'/> <input> <soap:body use='literal' encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' namespace='http://www.xnet.tk/test-soap'/> </input> <output> <soap:body use='literal' encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' namespace='http://www.xnet.tk/test-soap'/> </output> </operation>
This is quite generic and can be used for most operations with few changes, namely changing the namespace if necessary and the part after the # in the soap:operation action to the name of the operation.
This part is quite brief and simply says where each binding can be located:
<service name='MeetingSchedualService'> <port binding='ServiceBinding' name='ServicePort1'> <soap:address location='http://www.xnet.tk/test-soap/soap-server.php'/> </port> </service>
This says the the service MeetingSchedualService has one port that uses binding ServiceBinding and the soap:address says where the soap server can be reached at.
should be up soon is available here.