1. 程式人生 > >SOAP和WSDL的一些必要知識

SOAP和WSDL的一些必要知識

http://www.cnblogs.com/JeffreySun/archive/2009/12/14/1623766.html

SOAP和WSDL對Web Service、WCF進行深入瞭解的基礎,因此花一些時間去了解一下是很有必要的。

一、SOAP(Simple Object Access Protocol)

如果我們要呼叫遠端物件的方法,就必定要告訴對方,我們要呼叫的是一個什麼方法,以及這個方法的引數的值等等。然後對方把資料返回給我們。

這其中就涉及到兩個問題:1、資料如何在網路上傳輸。2、如何表示資料?用什麼格式去表示函式以及它的引數等等。

1、SOAP的傳輸協議

SOAP的傳輸協議使用的就是HTTP協議。只不過HTTP傳輸的內容是HTML文字,而SOAP協議傳輸的是SOAP的資料。看一下下面的例子:

這是一個HTTP請求(請求google的首頁)的內容:

複製程式碼 GET / HTTP/1.1 Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: en-us
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; CIBA) chromeframe/4.0
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Host: www.google.com
Cookie: PREF=ID=d8f9f1710bfa5f72:U=a5b3bec86b6433ef:NW=1:TM=1260238598:LM=1260241971:GM=1:S=q2agYsw3BsoOQMAs; NID=29=JgIGDDUx70IQTBVAnNEP_E9PLLKBI9STjzaBjgq1eWuDg-_jCgFpka59DrOC0aZKLbj4q77HU1VMKscXTP3OaseyTbv643c2XPe9dS7lsXDHAkAnS46vy-OU8XRqbmxJ; rememberme=true; SID=DQAAAH4AAABW7M4nVkTeOR7eJUmC1AJ4R6hYbmVewuy_uItLUTzZMUTpojdaHUExhPa_EPAkO9Ex1u3r7aPXZ5cj28xHnv2DbfRYf5AyaBcimciuOTITKSIkqn3QSpGDFkRS1Xn7EGzDpCV0V1xFlCu0erf_jfe_D6GOgC2P2S08jNdFS9Vpmw; HSID=AFEFTMA68EgNjkbil; __utmx=173272373.; __utmxx=173272373.

---------如果有Post的資料,這裡還會有Post的資料--------
複製程式碼

這個是一個SOAP請求的內容:

複製程式碼

POST /WebServices/WeatherWebService.asmx HTTP/1.1

User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 2.0.50727.3603)
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://WebXml.com.cn/getSupportCity"
Host: www.webxml.com.cn
Content-Length: 348
Expect: 100-continue
Connection: Keep-Alive

<?xml version="1.0" encoding="utf-8"?><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><getSupportCity xmlns="http://WebXml.com.cn/"><byProvinceName>廣東</byProvinceName></getSupportCity></soap:Body></soap:Envelope> 複製程式碼

可以看到,一個SOAP請求其實就是一個HTTP請求,但為了表明內容是SOAP的資料,需要加入上面請求中紅色字的部分來以示區別。也就是說,如果請求頭中有SOAPAction這一段,那麼請求會被當作SOAP的內容來處理而不會當作HTML來解析。可以用上面指定SOAPAction來表示內容是SOAP的內容,也可以指定 Content-Type: application/soap+xml 來表示內容是SOAP的內容。SOAP請求中最後的那段XML資料,這個就是請求的具體內容,這個就是SOAP規定的請求的資料格式,下面再詳細對格式進行說明。

2、SOAP的資料格式

現在知道了SOAP是通過HTTP協議的POST方法來傳輸資料的,只不過是請求的Header中加了一些標誌來說明自己是一個SOAP請求。那麼資料的具體格式是怎麼規定的呢,我們把上面請求的XML資料展開看一下:

複製程式碼 <?xml version="1.0" encoding="utf-8"?><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><getSupportCity xmlns="http://WebXml.com.cn/"><byProvinceName>廣東</byProvinceName></getSupportCity></soap:Body></soap:Envelope> 複製程式碼

 其中的<soap:Body>裡面的內容就是請求的內容,請求的方法為getSupportCity,該方法有一個名為byProvinceName的引數,引數的值為“廣東”這個字串。再看一下返回的內容:

複製程式碼 HTTP/1.1 200 OK
Date: Mon, 14 Dec 2009 05:55:39 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Cache-Control: private, max-age=0
Content-Type: text/xml; charset=utf-8
Content-Length: 1052

<?xml version="1.0" encoding="utf-8"?><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><getSupportCityResponse xmlns="http://WebXml.com.cn/"><getSupportCityResult><string>廣州 (59287)</string><string>深圳 (59493)</string><string>潮州 (59312)</string><string>韶關 (59082)</string><string>湛江 (59658)</string><string>惠州 (59298)</string><string>清遠 (59280)</string><string>東莞 (59289)</string><string>江門 (59473)</string><string>茂名 (59659)</string><string>肇慶 (59278)</string><string>汕尾 (59501)</string><string>河源 (59293)</string><string>揭陽 (59315)</string><string>梅州 (59117)</string><string>中山 (59485)</string><string>德慶 (59269)</string><string>陽江 (59663)</string><string>雲浮 (59471)</string><string>珠海 (59488)</string><string>汕頭 (59316)</string><string>佛山 (59279)</string></getSupportCityResult></getSupportCityResponse></soap:Body></soap:Envelope> 複製程式碼

返回的HTTP頭中並沒有標誌來表明是一個SOAP的響應,因為的確沒有必要,請求方傳送出的SOAP請求,返回的肯定是SOAP的響應。

一個典型的SOAP請求格式的結構如下:

複製程式碼 <?xml version="1.0"?><soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle
="http://www.w3.org/2001/12/soap-encoding"><soap:Header><m:Trans xmlns:m="http://www.w3schools.com/transaction/"
  soap:mustUnderstand
="1">234
  
</m:Trans></soap:Header><soap:Body><m:GetPrice xmlns:m="http://www.w3schools.com/prices"><m:Item>Apples</m:Item></m:GetPrice></soap:Body></soap:Envelope> 複製程式碼

下面逐個解釋裡面的元素:

a) Envelope

SOAP的請求內容必須以Envelope做為根節點。

xmlns:soap="http://www.w3.org/2001/12/soap-envelope",不能修改,否則會出錯。http://www.w3.org/2001/12/soap-envelope裡面有Envelope的schema的相關定義。有興趣的可以去這個連結的內容。

soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding",這個指定了資料元素的型別。

b) Header

這個是可選的,如果需要新增Header元素,那麼它必須是Envelope的第一個元素。

Header的內容並沒有嚴格的限制,我們可以自己新增一些和應用程式相關的內容,但是客戶端一定要記得處理這些Header元素,可以加上mustUnderstand強制進行處理。

c) Body

這個就是請求的主題內容了,請求什麼函式,引數是什麼型別等等都在這裡面指定。 

用標籤表示一個函式,然後用子元素表示它的引數。

在呼叫中沒有指定引數和返回型別,這裡不需要指定,因為提供服務的一方自己已經規定好了資料型別,在呼叫時指定資料型別沒有任何意義。

二、WSDL(Web Services Description Language)

  WSDL是用來描述WebService的,它用XML的格式描述了WebService有哪些方法、引數型別、訪問路徑等等。我們要使用一個WebService肯定首先要獲取它的WSDL,在VS中新增一個Web 引用時,這些工作由開發環境幫我們做了,開發環境根據WSDL文件給Web Service生成了相應的代理類供我們使用。

下面是一個HelloWorld的WebService的服務端程式碼:

複製程式碼 publicclass Service : System.Web.Services.WebService
{
    
public Service () {

        
//Uncomment the following line if using designed components 
        
//InitializeComponent();     }

    [WebMethod]
    
public DateTime HelloWorld(int i)
    {
        
return DateTime.Now;
    }
}
複製程式碼

    其對應的WebService的WSDL文件如下:

複製程式碼  1 <?xml version="1.0" encoding="utf-8"?> 2 <wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://tempuri.org/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"> 3 <wsdl:types> 4 <s:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/"> 5 <s:element name="HelloWorld"> 6 <s:complexType> 7 <s:sequence> 8 <s:element minOccurs="1" maxOccurs="1" name="i" type="s:int"/> 9 </s:sequence>10 </s:complexType>11 </s:element>12 <s:element name="HelloWorldResponse">13 <s:complexType>14 <s:sequence>15 <s:element minOccurs="1" maxOccurs="1" name="HelloWorldResult" type="s:dateTime"/>16 </s:sequence>17 </s:complexType>18 </s:element>19 </s:schema>20 </wsdl:types>21 <wsdl:message name="HelloWorldSoapIn">22 <wsdl:part name="parameters" element="tns:HelloWorld"/>23 </wsdl:message>24 <wsdl:message name="HelloWorldSoapOut">25 <wsdl:part name="parameters" element="tns:HelloWorldResponse"/>26 </wsdl:message>27 <wsdl:portType name="ServiceSoap">28 <wsdl:operation name="HelloWorld">29 <wsdl:input message="tns:HelloWorldSoapIn"/>30 <wsdl:output message="tns:HelloWorldSoapOut"/>31 </wsdl:operation>32 </wsdl:portType>33 <wsdl:binding name="ServiceSoap" type="tns:ServiceSoap">34 <soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>35 <wsdl:operation name="HelloWorld">36 <soap:operation soapAction="http://tempuri.org/HelloWorld" style="document"/>37 <wsdl:input>38 <soap:body use="literal"/>39 </wsdl:input>40 <wsdl:output>41 <soap:body use="literal"/>42 </wsdl:output>43 </wsdl:operation>44 </wsdl:binding>45 <wsdl:binding name="ServiceSoap12" type="tns:ServiceSoap">46 <soap12:binding transport="http://schemas.xmlsoap.org/soap/http"/>47 <wsdl:operation name="HelloWorld">48 <soap12:operation soapAction="http://tempuri.org/HelloWorld" style="document"/>49 <wsdl:input>50 <soap12:body use="literal"/>51 </wsdl:input>52 <wsdl:output>53 <soap12:body use="literal"/>54 </wsdl:output>55 </wsdl:operation>56 </wsdl:binding>57 <wsdl:service name="Service">58 <wsdl:port name="ServiceSoap" binding="tns:ServiceSoap">59 <soap:address location="http://localhost:2206/WebSite1/Service.asmx"/>60 </wsdl:port>61 <wsdl:port name="ServiceSoap12" binding="tns:ServiceSoap12">62 <soap12:address location="http://localhost:2206/WebSite1/Service.asmx"/>63 </wsdl:port>64 </wsdl:service>65 </wsdl:definitions> 複製程式碼

一個WSDL文件由四部分組成:

1、types

  指定了WebService用到的所有資料型別,上面用到了兩種資料型別,int和datetime


2、message

  指明一個操作所用到的資料型別。

  HelloWorldSoapIn是指HelloWorld的輸入操作用到的資料型別,HelloWorldSoapOut是指HelloWorld的輸出操作用到的資料型別。二者的element元素指出了與types中對應到的具體型別。

3、portType

  指出了這個WebService所有支援的操作,就是說有哪些方法可供呼叫。

  這裡支援一個HelloWorld呼叫,它的輸入和輸出對應到HelloWorldSoapIn和HelloWorldSoapOut這個兩個資料型別。

4、binding

  soap12:binding元素的transport指明傳輸協議,這裡是http協議。

  operation 指明要暴露給外界呼叫的操作。

  use屬性指定輸入輸出的編碼方式,這裡沒有指定編碼。

5、services

  指定服務的一些資訊,主要是指定服務的訪問路徑。