.NET調PHP Web Service的典型例子

iDotNetSpace發表於2009-08-10
最近一個專案由"WinForm直接訪問DB2"移植到"WinForm通過PHP Web Service來訪問DB2”。
(優點是php可以架在Linux上,而Linux是免費的)      
這個命題的難點不是訪問DB2,而是.NET呼叫PHP的Web Service。對於我這個長期作.NET,之前一直以為只有.NET才可以做Web Service……的人來說,真是有點強“聰”所難了。
      但是問題還是要解決的,期限就擺在眼前呢。經過一番調查,終於有了眉目,現在分享給大家。
      
      首先要說明的,PHP伺服器需要至少需要兩個檔案——一個WSDL檔案和一個PHP檔案。WSDL檔案是一種機讀的XML檔案,用於描述WebService提供的服務和呼叫方法(對於.NET則可以自動生成呼叫程式碼,十分好用),php檔案就是真正實現的WEB服務了。
      1)PHP伺服器端程式碼
          1-1)TestWebService.php程式碼
.NET調PHP Web Service的典型例子
php
class TestWebService
{
    
public function HelloWorld()
    {
        
return array("HelloWorldResult"=>"Hello");
    }

    
public function GetArray($args)
        {
          
/*
           注意,Web Service的方法在宣告時至多一個引數,
            可是在呼叫該方法時就必須傳value1,value2兩個引數。
            (這一點十分令人費解,我的理解是,在呼叫該方法時,系統把所有引數都放到一個物件裡傳過來的)
          
*/

        
$value1 = $args->value1;  
        
$value2 = $args->value2;//這兩句是獲取真正的引數
 
        
$arry = array($value1,$value2);

        
//返回值也很特別,不是直接返回$arry,而是把它放到一個物件裡再返回。
        return array("GetArrayResult"=>$arry);
    }
}

//建立WebSevice例項
$server = new SoapServer("TestWebService.wsdl");
//指定類名
$server->setClass("TestWebService");

$server->handle();


?>

          1-2)TestWebService.wsdl程式碼
.NET調PHP Web Service的典型例子
xml version="1.0" encoding="utf-8"?>
<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/">
  
<wsdl:types>
    
<s:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/">
      
<s:element name="HelloWorld">
        
<s:complexType />
      
s:element>
      
<s:element name="HelloWorldResponse">
        
<s:complexType>
          
<s:sequence>
            
<s:element minOccurs="0" maxOccurs="1" name="HelloWorldResult" type="s:string" />
          
s:sequence>
        
s:complexType>
      
s:element>
      
<s:element name="GetArray">
        
<s:complexType>
          
<s:sequence>
            
<s:element minOccurs="0" maxOccurs="1" name="value1" type="s:string" />
            
<s:element minOccurs="0" maxOccurs="1" name="value2" type="s:string" />
          
s:sequence>
        
s:complexType>
      
s:element>
      
<s:element name="GetArrayResponse">
        
<s:complexType>
          
<s:sequence>
            
<s:element minOccurs="0" maxOccurs="1" name="GetArrayResult" type="tns:ArrayOfString" />
          
s:sequence>
        
s:complexType>
      
s:element>
      
<s:complexType name="ArrayOfString">
        
<s:sequence>
          
<s:element minOccurs="0" maxOccurs="unbounded" name="string" nillable="true" type="s:string" />
        
s:sequence>
      
s:complexType>
    
s:schema>
  
wsdl:types>
  
<wsdl:message name="HelloWorldSoapIn">
    
<wsdl:part name="parameters" element="tns:HelloWorld" />
  
wsdl:message>
  
<wsdl:message name="HelloWorldSoapOut">
    
<wsdl:part name="parameters" element="tns:HelloWorldResponse" />
  
wsdl:message>
  
<wsdl:message name="GetArraySoapIn">
    
<wsdl:part name="parameters" element="tns:GetArray" />
  
wsdl:message>
  
<wsdl:message name="GetArraySoapOut">
    
<wsdl:part name="parameters" element="tns:GetArrayResponse" />
  
wsdl:message>
  
<wsdl:portType name="TestWebServiceSoap">
    
<wsdl:operation name="HelloWorld">
      
<wsdl:input message="tns:HelloWorldSoapIn" />
      
<wsdl:output message="tns:HelloWorldSoapOut" />
    
wsdl:operation>
    
<wsdl:operation name="GetArray">
      
<wsdl:input message="tns:GetArraySoapIn" />
      
<wsdl:output message="tns:GetArraySoapOut" />
    
wsdl:operation>
  
wsdl:portType>
  
<wsdl:binding name="TestWebServiceSoap" type="tns:TestWebServiceSoap">
    
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
    
<wsdl:operation name="HelloWorld">
      
<soap:operation soapAction="http://tempuri.org/HelloWorld" style="document" />
      
<wsdl:input>
        
<soap:body use="literal" />
      
wsdl:input>
      
<wsdl:output>
        
<soap:body use="literal" />
      
wsdl:output>
    
wsdl:operation>
    
<wsdl:operation name="GetArray">
      
<soap:operation soapAction="http://tempuri.org/GetArray" style="document" />
      
<wsdl:input>
        
<soap:body use="literal" />
      
wsdl:input>
      
<wsdl:output>
        
<soap:body use="literal" />
      
wsdl:output>
    
wsdl:operation>
  
wsdl:binding>
  
<wsdl:binding name="TestWebServiceSoap12" type="tns:TestWebServiceSoap">
    
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
    
<wsdl:operation name="HelloWorld">
      
<soap12:operation soapAction="http://tempuri.org/HelloWorld" style="document" />
      
<wsdl:input>
        
<soap12:body use="literal" />
      
wsdl:input>
      
<wsdl:output>
        
<soap12:body use="literal" />
      
wsdl:output>
    
wsdl:operation>
    
<wsdl:operation name="GetArray">
      
<soap12:operation soapAction="http://tempuri.org/GetArray" style="document" />
      
<wsdl:input>
        
<soap12:body use="literal" />
      
wsdl:input>
      
<wsdl:output>
        
<soap12:body use="literal" />
      
wsdl:output>
    
wsdl:operation>
  
wsdl:binding>
  
<wsdl:service name="TestWebService">
    
<wsdl:port name="TestWebServiceSoap" binding="tns:TestWebServiceSoap">
      
<soap:address location="http://localhost/phpmyadmin/ws/TestWebService.php" />
    
wsdl:port>
    
<wsdl:port name="TestWebServiceSoap12" binding="tns:TestWebServiceSoap12">
      
<soap12:address location="http://localhost/phpmyadmin/ws/TestWebService.php" />
    
wsdl:port>
  
wsdl:service>
wsdl:definitions>
      WSDL的程式碼比較長,當方法很多時,手敲程式碼是不太可能的。有一個巧的辦法,就是也用.NET實現一個不含真正方法體的Web Serivce,然後通過http://***/TestWebService.asmx?wsdl的方法生成wsdl程式碼檔案。
         關於WSDL檔案,我要說明特別說明兩點:
        (1)soap:address結點是宣告WebService的地址,在部署時要改成相應地址;
        (2)一維陣列的宣告型別為ArrayOfType,字串陣列為ArrayOfString。如果Type不是簡單型別,則Type需要另外宣告。

      2).NET客戶端程式碼
           先要新增Web引用,地址為WSDL檔案的Http地址。
           呼叫程式碼(C#)
        //初始化WebService
        localhost.TestWebService srv = new localhost.TestWebService();
        
//調第一個方法
         string str = srv.HelloWorld();
        
//調第二個方法
         string[] arry= srv.GetArray("string1","string2");


總結: (一)PHP是一種弱型別語言,檢查錯誤比較困難。array型別也與一般理解的陣列不同,它也有類似Hashtable的用法。
          (二)PHP Web Service方法的傳入引數、返回值都至多有一個,因為真正呼叫時的引數和返回值,都是包裝到一個物件中傳送的。
          (三)PHP Web Service也支援自定義型別和自定義型別陣列等複雜型別,但不支援多組陣列。
          (四)若返回值需要是多張二維表時,我淺薄的以為,可以傳化一組字串陣列傳送,格式為
                        [表1行數],[表1列數],[表1列名1],[表1列名2],……[表1列名N],[表1中按行列存放的值]
                        [表2行數],[表2列數],[表2列名1],[表2列名2],……[表2列名N],[表2中按行列存放的值]
                        ……
                        [表M行數],[表M列數],[表M列名1],[表M列名2],……[表M列名N],[表2中按行列存放的值]
                   按順序將上面[]中的內容串成字串陣列,效率還不錯,我測試10000行240列的資料,我有現成編解程式碼,有興趣的可以向我索取.

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-611748/,如需轉載,請註明出處,否則將追究法律責任。

相關文章