A WSDL (Web Services Description Language) is a url web page that describes a web service. WSDL documents the web service in the form of an xml, here is an example of a WSDL:
Announcement
You can find all my latest posts on medium.http://www.webservicex.net/globalweather.asmx?wsdl
The wsdl contains 4 main element tags:
- portType – this element can be thought of as housing a collection of operations elements (aka functions). Hence each portype element in a wsdl
is a logical grouping for a collection of functions. the portype’s name is given as an attribute. - operation – these elements are child elements of the porttype element. Their “name” attribute is equivalent to a function’s name. Each operation can
contain upto 2 child elements “input” and “output”.- input – this is basically a function’s input parameter
- output – this is basically parameter.
The input and output elements have an attribute called “message” the value of this attribute is actually a pointer to another element called:
- message – this has a “name” attribute that matches the value of the output/input element’s “message” attribute’s value.
The “message” element has a child element called “part”
- part – this explains the data type that the parameter (or output) can be of and also attaches a name (using attributes again) to the parameter/output.
the word “part” is used because each functions “whole message” is a combination of both the input and output.
So far, we know that a porttype (aka function library) house a collection of operations (aka functions). Each functions input(aka parameter)/outputs is defined in the message-element, this include the parameter’s name, and the output variable’s name, since I think the output is given in the form of a variable that stores the output.
However we haven’t look at how you can access a function (e.g. do you use http, soap, etc). This information is stored in an element called binding. A binding element should be available for each port type, since all the operations (functions) in a porttype uses the same network-mechanisn.
Each binding element has 2 attributes:
- name – this helps to refer to a bind in particular
- type – this is the name of the porttype that this binding is associated to.
Eaching binding element contains the following child elements:
- soap:binding – this is actually a one line element (e.g. like html’s
). (Note, this can also be “http:binding”, if http is used instead of SOAP.) It has the following attributes: - style – This defines the soap protocol to use. It is either equal to “rpc” or “document”. In nearly all cases it is “document”, which means that we use the http protocol to deliver the soap “envelope”. I think this is optional
- transport – this is pointer to the document that defines the protocol to be used, this should be equal to “http://schemas.xmlsoap.org/soap/http” . Note, in the case of “http:binding”, we have the “verb” attribute instead of “transport”, and this is equal to either “get” or “post”.
- wsdl:operation: There are several of these. Each one is a reference to each function that are in the given porttype. Here “http://www.w3schools.com/webservices/ws_wsdl_binding.asp” it shows that an operation doesn’t have a name, this is a typo because it should have a name that correspond to the given porttype’s operation’s name attribute’s value. Each operation here, has these elements:
- Each “wsdl:operation” (aside from the name attribute, which matches the operation attribute’s name) have the following child elements:
- Soap:operation – This has 2 attributes:
- soapaction – This I think is the url location to where to send the SOAP message to.
- wsdl:input – This I think is the encoding to use to send the entire SOAP message
- wsdl:output – this I think is the encoding to use to read the SOAP message received from the web service.
Hence without the binding element, it won’t be able to know where to send/recieve soap-messages.
Here’s an Example
If you analyse the following wsdl:
http://www.webservicex.net/globalweather.asmx?wsdl
You will find that it contains 3 porttype elements, and each porttype contains 2 operations. So across all 3 porttypes there are 6 operations (functions). If you look closely you will discover that each porttype contains the functions called:
- 1st porttype (GlobalWeatherSoap) has the following functions
- GetWeather
- GetCitiesByCountry
- 2nd porttype (GlobalWeatherHttpGet) has the following functions
- GetWeather
- GetCitiesByCountry
- 3nd porttype (GlobalWeatherHttpPost) has the following functions
- GetWeather
- GetCitiesByCountry
So why do we have 3 porttypbes with 3 identical pair of functions? That’s because this wsdl can accept 3 types of communications, SOAP, HTTPGet, and httpPost. In most case you will just use the SOAP porttype, but web designers could also use the other 2.
Since each function has an input and output, it means that each function is accompanied by 2 message elements (one for each part), and since we have 6 functions, it means that we have a total of 12 (6*2) message elements to cover off all the functions.
Each porttype’s communication details (e.g. for putty connection, the communication details are, hostname, protocol, e.g. ssh, port number,..etc) are covered in the “binding” elements.
Since there are 3 porttypes, there should be 3 binding elements. However there is 4 (2 of which releates to SOAP). I think this could be for load balancing purposes, but not sure.
Now in powershell, if we do the following:
PS C:\> $url = "http://www.webservicex.net/globalweather.asmx?wsdl" PS C:\> $webservicex = New-WebServiceProxy -Uri $url -namespace WebServiceProxy -Class GlobalWeatherSoap
Note: I think the -class declaration is optional because I think the New-WebServiceProxy will default to the SOAP protocol anyway.
This results in the “$webservicex” object. You can think of this object as our personal messenger that will send and receive data from the webservicex.net’s globalweather service. If you do:
PS C:\> $webservicex | gm TypeName: WebServiceProxy.GlobalWeather Name MemberType Definition ---- ---------- ---------- Disposed Event System.EventHandler Disposed(System.Object, System.EventArgs) GetCitiesByCountryCompleted Event WebServiceProxy.GetCitiesByCountryCompletedEventHandler GetCitiesByC... GetWeatherCompleted Event WebServiceProxy.GetWeatherCompletedEventHandler GetWeatherCompleted(... Abort Method void Abort() BeginGetCitiesByCountry Method System.IAsyncResult BeginGetCitiesByCountry(string CountryName, Syst... BeginGetWeather Method System.IAsyncResult BeginGetWeather(string CityName, string CountryN... CancelAsync Method void CancelAsync(System.Object userState) CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType) Discover Method void Discover() Dispose Method void Dispose(), void IDisposable.Dispose() EndGetCitiesByCountry Method string EndGetCitiesByCountry(System.IAsyncResult asyncResult) EndGetWeather Method string EndGetWeather(System.IAsyncResult asyncResult) Equals Method bool Equals(System.Object obj) GetCitiesByCountry Method string GetCitiesByCountry(string CountryName) GetCitiesByCountryAsync Method void GetCitiesByCountryAsync(string CountryName), void GetCitiesByCo... GetHashCode Method int GetHashCode() GetLifetimeService Method System.Object GetLifetimeService() GetType Method type GetType() GetWeather Method string GetWeather(string CityName, string CountryName) GetWeatherAsync Method void GetWeatherAsync(string CityName, string CountryName), void GetW... InitializeLifetimeService Method System.Object InitializeLifetimeService() ToString Method string ToString() AllowAutoRedirect Property bool AllowAutoRedirect {get;set;} ClientCertificates Property System.Security.Cryptography.X509Certificates.X509CertificateCollect... ConnectionGroupName Property string ConnectionGroupName {get;set;} Container Property System.ComponentModel.IContainer Container {get;} CookieContainer Property System.Net.CookieContainer CookieContainer {get;set;} Credentials Property System.Net.ICredentials Credentials {get;set;} EnableDecompression Property bool EnableDecompression {get;set;} PreAuthenticate Property bool PreAuthenticate {get;set;} Proxy Property System.Net.IWebProxy Proxy {get;set;} RequestEncoding Property System.Text.Encoding RequestEncoding {get;set;} Site Property System.ComponentModel.ISite Site {get;set;} SoapVersion Property System.Web.Services.Protocols.SoapProtocolVersion SoapVersion {get;s... Timeout Property int Timeout {get;set;} UnsafeAuthenticatedConnectionSharing Property bool UnsafeAuthenticatedConnectionSharing {get;set;} Url Property string Url {get;set;} UseDefaultCredentials Property bool UseDefaultCredentials {get;set;} UserAgent Property string UserAgent {get;set;}
You will find that that the “GetWeather” and “GetCitiesByCountry” appear as object methods. Note, anything that have “string” method can be called on.
This means that you can now do this:
PS C:\> [XML]$AustralianCities = $webservicex.GetCitiesByCountry("Australia")
Here we are basically instructing the “$webservicex” object (messenger) to go to the webservicex.net and request for a list of all the cities in Australia, which we have requested by using the GetCitiesByCountry, and passing the parameter “Australia” into it. The web service recieves the request and gives a response, this response is an output that is in SOAP (xml) format. Since the output is in xml, we can’t output it directly into the powershell terminal, instead we have to capture it in the a preformatted variable object.
We can then pull the info out of this variable instead, just like we do for any other object. E.g.:
PS C:\> $australiancities NewDataSet ---------- NewDataSet PS C:\> $australiancities.NewDataSet Table ----- {Table, Table, Table, Table...} PS C:\> $australiancities.NewDataSet.Table Country City ------- ---- Australia Archerfield Aerodrome Australia Amberley Aerodrome Australia Alice Springs Aerodrome Australia Brisbane Airport M. O Australia Coolangatta Airport Aws Australia Cairns Airport Australia Charleville Airport Australia Gladstone Australia Longreach Airport Australia Mount Isa Amo Australia Mackay Mo Australia Oakey Aerodrome Australia Proserpine Airport Australia Rockhampton Airport Australia Broome Airport Australia Townsville Amo Australia Weipa City Australia Gove Airport Australia Tennant Creek Airport Australia Yulara Aws Australia Albury Airport Australia Devonport East Australia Goldstream Aws Australia East Sale Aerodrome Australia Hobart Airport Australia Launceston Airport Australia Laverton Aerodrome Australia Moorabbin Airport Aws Australia Mount Gambier Aerodrome Australia Mildura Airport Australia Melbourne Airport Australia Macquarie Island Australia Wynyard West Australia Adelaide Airport Australia Albany Airport Australia Broken Hill Patton Street Australia Ceduna Airport Australia Derby Australia Darwin Airport Australia Bullsbrook Pearce Amo Australia Edinburgh M. O. Australia Forrest Airport Australia Geraldton Airport Australia Kalgoorlie Boulder Amo Australia Kununurra Kununurra Aws Australia Leigh Creek Airport Australia Learmonth Airport Australia Meekatharra Airport Australia Port Hedland Pardoo Australia Parafield Airport Australia Belmont Perth Airport Australia Katherine Aerodrome Australia Woomera Aerodrome Australia Bankstown Airport Aws Australia Canberra Australia Coffs Harbour Mo Australia Cooma Australia Camden Airport Australia Dubbo Australia Norfolk Island Airport Australia Nowra Ran Air Station Australia Richmond Aus-Afb Australia Sydney Airport Australia Tamworth Airport Australia Wagga Airport Australia Williamtown Aerodrome
When we send a request to a web service, we can send it in many forms, e.g. using html’s “post” or “get”. However the most powerful and popular approach is to send the request in the form of xml? The structure of this xml (i.e. schema), is that of a schema called “SOAP”
You can find the structure of SOAP here:
http://www.w3schools.com/webservices/ws_soap_syntax.asp
Here is a diagram of the structure:
http://en.wikipedia.org/wiki/SOAP
In the case of the above powershell example, the object we created called $webservicex will automatically generate the SOAP request xml behind the scenes and send it to the webservicex.net web service. e.g. when we run:
PS C:\> [xml][/xml]$AustralianCities = $webservicex.GetCitiesByCountry("Australia")
then the GetCitiesByCountry method for the $webservicex will generate the following xml (which I got from soapui):
[code language=”xml”]
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://www.webserviceX.NET">
<soapenv:Header/>
<soapenv:Body>
<web:GetCitiesByCountry>
<!–Optional:–>
<web:CountryName>Australia</web:CountryName>
</web:GetCitiesByCountry>
</soapenv:Body>
</soapenv:Envelope>
[/code]
And the method then sends this xml (SOAP) request to the webservice. After a few moments, the web service returns the following soap (xml) response:
[code language=”xml”]
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetCitiesByCountryResponse xmlns="http://www.webserviceX.NET">
<GetCitiesByCountryResult><![CDATA[<NewDataSet>
<Table>
<Country>Australia</Country>
<City>Archerfield Aerodrome</City>
</Table>
<Table>
<Country>Australia</Country>
<City>Amberley Aerodrome</City>
</Table>
<Table>
<Country>Australia</Country>
<City>Alice Springs Aerodrome</City>
</Table>
<Table>
<Country>Australia</Country>
<City>Brisbane Airport M. O</City>
</Table>
.
.
.
.
<Table>
<Country>Australia</Country>
<City>Tamworth Airport</City>
</Table>
<Table>
<Country>Australia</Country>
<City>Wagga Airport</City>
</Table>
<Table>
<Country>Australia</Country>
<City>Williamtown Aerodrome</City>
</Table>
</NewDataSet>]]></GetCitiesByCountryResult>
</GetCitiesByCountryResponse>
</soap:Body>
</soap:Envelope>
[/code]
To summarise, A SOAP message is an ordinary XML document. The main elements of an a soap’s xml request can be found here:
http://en.wikipedia.org/wiki/SOAP#SOAP_Building_Blocks
http://www.w3schools.com/webservices/default.asp