簡體   English   中英

使用NuSOAP生成WSDL - 返回具有各種類型的結構(int,string,結構數組)

[英]Generating WSDL with NuSOAP - return struct with various types (int, string, array of structs)

我想通過使用NuSOAP生成WSDL來通過SOAP查詢一些內容。
我知道有很多與該主題有關的問題,但我沒有成功地使代碼適應我的特定問題。

我成功地生成了WSDL代碼,它只返回一個結構數組(關聯數組),但我寧願返回一個包含整數變量,字符串變量和結構數組的對象(struct)

所以, 這是用於返回結構數組的代碼

<?php

    function getStuffs( $user='', $pass='' ) {
        // here we can check user and pass and do whatever (if it isn't alright, we can throw exception or return NULL or sg. similar)
        // .......

        $stuff_array   = array();
        $stuff_array[] = array( 'id'=>122, 'name'=>'One stuff');
        $stuff_array[] = array( 'id'=>213, 'name'=>'Another stuff');
        $stuff_array[] = array( 'id'=>435, 'name'=>'Whatever stuff');
        $stuff_array[] = array( 'id'=>65, 'name'=>'Cool Stuff');
        $stuff_array[] = array( 'id'=>92, 'name'=>'Wow, what a stuff');    

        return $stuff_array;
    }

    require_once 'nusoap/lib/nusoap.php';
    $server = new soap_server;

    // $myNamespace = $_SERVER['SCRIPT_URI'];
    $myNamespace = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'];

    $server->configureWSDL('MyStuffService', 'urn:' . $myNamespace);
    // $server->wsdl->schemaTargetNamespace = 'http://soapinterop.org/xsd/';

    $server->wsdl->addComplexType(
        // name
        'Stuffs',
        // typeClass (complexType|simpleType|attribute)
        'complexType',
        // phpType: currently supported are array and struct (php assoc array)
        'struct',
        // compositor (all|sequence|choice)
        'all',
        // restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
        '',
        // elements = array ( name = array(name=>'',type=>'') )
        array(
            'id' => array(
                'name' => 'id',
                'type' => 'xsd:int'
            ),
            'name' => array(
                'name' => 'name',
                'type' => 'xsd:string'
            )
        )
    );  

    $server->wsdl->addComplexType(
        // name
        'StuffsArray',
        // typeClass (complexType|simpleType|attribute)
        'complexType',
        // phpType: currently supported are array and struct (php assoc array)
        'array',
        // compositor (all|sequence|choice)
        '',
        // restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
        'SOAP-ENC:Array',
        // elements = array ( name = array(name=>'',type=>'') )
        array(),
        // attrs
        array(
            array(
                'ref' => 'SOAP-ENC:arrayType',
                'wsdl:arrayType' => 'tns:Stuffs[]'
            )
        ),
        // arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
        'tns:Stuffs'
    );

    $server->register(
        // string $name the name of the PHP function, class.method or class..method
        'getStuffs',
        // array $in assoc array of input values: key = param name, value = param type
        array(
            'user' => 'xsd:string',
            'pass' => 'xsd:string'
        ),
        // array $out assoc array of output values: key = param name, value = param type
        array(
            'return' => 'tns:StuffsArray'
        ),
        // mixed $namespace the element namespace for the method or false
        'urn:' . $myNamespace,
        // mixed $soapaction the soapaction for the method or false
        'urn:' . $myNamespace . "#getStuffs",
        // mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
        'rpc',
        // mixed $use optional (encoded|literal) or false
        'encoded',
        // string $documentation optional Description to include in WSDL
        'Fetch array of Stuffs ("id", "name").' // documentation
    );

    #$server->wsdl->schemaTargetNamespace = $myNamespace;
    $server->service(isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '');
    exit();

?>

在C#控制台應用程序中,在添加名為“StuffService”的Web引用並將“?wsdl”附加到可以找到此PHP文件的相應URL之后,此代碼有效,我可以完美地查詢stuff_array值,如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WebServiceTest
{
    class Program
    {
        static void Main(string[] args)
        {
            StuffService.MyStuffService myService = new StuffService.MyStuffService();

            StuffService.Stuffs[] stuffs = myService.getStuffs("someone", "1234");

            foreach (var stuff in stuffs)
            {
                Console.WriteLine(stuff.id+".: "+stuff.name);
            }

            Console.WriteLine();
            Console.WriteLine("Press a key...");
            Console.ReadKey();
        }
    }
}

這很酷,但我想開發這個代碼來回饋這樣的對象:

class ResponseObject {
    public $responseCode = 0;
    public $responseMessage = '';
    public $stuffArray = NULL;
}   

$responseObject = NULL;

function getStuffs( $user='', $pass='' ) {
    global $responseObject;

    $responseObject = new ResponseObject();

    // check stuffs in a simple way now
    if($user != 'someone' && $pass != '1234'){
        $responseObject->responseCode = 2;
        $responseObject->responseMessage = 'Authentication failed';
        return $responseObject;
    }

    $responseObject->stuffArray   = array();
    $responseObject->stuffArray[] = array( 'id'=>122, 'name'=>'One stuff');
    $responseObject->stuffArray[] = array( 'id'=>213, 'name'=>'Another stuff');
    $responseObject->stuffArray[] = array( 'id'=>435, 'name'=>'Whatever stuff');
    $responseObject->stuffArray[] = array( 'id'=>65, 'name'=>'Cool Stuff');
    $responseObject->stuffArray[] = array( 'id'=>92, 'name'=>'Wow, what a stuff');          

    $responseObject->responseCode = 1;
    $responseObject->responseMessage = 'Successful!';
    return $responseObject; 
}

適合的NuSOAP代碼是什么?
謝謝!! :)

我希望我能澄清一下我想要實現的目標:返回一個包含int,字符串和結構數組的結構,但不知道如何編寫適當的NuSOAP代碼。 這樣我就可以首先檢查responseCode,並使用相應的錯誤消息處理它或輸出stuffArray等。

經過長時間的實驗,我找到了解決方案!

因此,給出一個包含三個成員的結構 - 一個int responseCode,一個字符串responseMessage和一個在示例中名為stuffArray的結構數組 - 通過帶有NuSOAP(PHP)的SOAP,如下所示,我在代碼中添加了一些注釋以使其更多明確:

<?php

    class ResponseObject {
        public $responseCode = 0;
        public $responseMessage = 'Unknown error!';
        public $stuffArray = NULL;
    }   

    /**
     * @return object
     */ 
    function getStuffs( $user='', $pass='' ) {

        $responseObject = new ResponseObject();

        // check stuffs in a simple way now
        if( !($user == 'someone' and $pass == '1234') ){
            $responseObject->responseCode = 2;
            $responseObject->responseMessage = 'Authentication failed!';
            return $responseObject;
        }

        $responseObject->stuffArray   = array();
        $responseObject->stuffArray[] = array( 'id'=>122, 'name'=>'One stuff');
        $responseObject->stuffArray[] = array( 'id'=>213, 'name'=>'Another stuff');
        $responseObject->stuffArray[] = array( 'id'=>435, 'name'=>'Whatever stuff');
        $responseObject->stuffArray[] = array( 'id'=>65, 'name'=>'Cool Stuff');
        $responseObject->stuffArray[] = array( 'id'=>92, 'name'=>'Wow, what a stuff');          

        $responseObject->responseCode = 1;
        $responseObject->responseMessage = 'Successful!';
        return $responseObject; 
    }

    require_once 'nusoap/lib/nusoap.php';
    $server = new soap_server;

    // $myNamespace = $_SERVER['SCRIPT_URI'];
    $myNamespace = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'];

    $server->configureWSDL(
        // string $serviceName, name of the service
        'MyStuffService',
        // mixed $namespace optional 'tns' service namespace or false
        // 'urn:' . $myNamespace
        $myNamespace
    );

    // $server->wsdl->schemaTargetNamespace = 'http://soapinterop.org/xsd/';
    $server->wsdl->schemaTargetNamespace = $myNamespace;

    $server->wsdl->addComplexType(
        // name
        'Stuffs',
        // typeClass (complexType|simpleType|attribute)
        'complexType',
        // phpType: currently supported are array and struct (php assoc array)
        'struct',
        // compositor (all|sequence|choice)
        'all',
        // restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
        '',
        // elements = array ( name = array(name=>'',type=>'') )
        array(
            'id' => array(
                'name' => 'id',
                'type' => 'xsd:int'
            ),
            'name' => array(
                'name' => 'name',
                'type' => 'xsd:string'
            )
        )
    );  

    $server->wsdl->addComplexType(
        // name
        'StuffsArray',
        // typeClass (complexType|simpleType|attribute)
        'complexType',
        // phpType: currently supported are array and struct (php assoc array)
        'array',
        // compositor (all|sequence|choice)
        '',
        // restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
        'SOAP-ENC:Array',
        // elements = array ( name = array(name=>'',type=>'') )
        array(),
        // attrs
        array(
            array(
                'ref' => 'SOAP-ENC:arrayType',
                'wsdl:arrayType' => 'tns:Stuffs[]'
            )
        ),
        // arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
        'tns:Stuffs'
    );


    $server->wsdl->addComplexType(
        // name
        'ResponseObject',
        // typeClass (complexType|simpleType|attribute)
        'complexType',
        // phpType: currently supported are array and struct (php assoc array)
        'struct',
        // compositor (all|sequence|choice)
        'all',
        // restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
        '',
        // elements = array ( name = array(name=>'',type=>'') )
        array
        (
            'responseCode' => array(   'type' => 'xsd:int'),
            'responseMessage' => array(   'type' => 'xsd:string'),
            'stuffArray'   => array(   'type' => 'tns:StuffsArray'
                                            // DON'T UNCOMMENT THE FOLLOWING COMMENTED LINES, BECAUSE THIS WAY IT DOESN'T WORK!!! - Left it in the code not to forget it....
                                            // ,
                                            // 'minOccurs' => '0',
                                            // 'maxOccurs' => 'unbounded'
                                            )
        )
    );

    $server->register(
        // string $name the name of the PHP function, class.method or class..method
        'getStuffs',
        // array $in assoc array of input values: key = param name, value = param type
        array(
            'user' => 'xsd:string',
            'pass' => 'xsd:string'
        ),
        // array $out assoc array of output values: key = param name, value = param type
        array(
            'return' => 'tns:ResponseObject'
        ),
        // mixed $namespace the element namespace for the method or false
        // 'urn:' . $myNamespace,
        $myNamespace,
        // mixed $soapaction the soapaction for the method or false
        // 'urn:' . $myNamespace . "#getStuffs",
        $myNamespace . "#getStuffs",
        // mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
        'rpc',
        // mixed $use optional (encoded|literal) or false
        'encoded',
        // string $documentation optional Description to include in WSDL
        'Fetch array of Stuffs ("id", "name").' // documentation
    );

    // $server->wsdl->schemaTargetNamespace = $myNamespace;

    // function def.: nusoap/lib/class.soap_server.php (236)
    $server->service(isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '');

    //   DON'T UNCOMMENT THE FOLLOWING LINES!! - Don't call these headers explicitly,
    //   everything will be handled in function service() appropriately - I know it by experience that it's not a good choice...
    // output:wsdl
    // header('Content-Type: text/xml;charset=utf-8');
    // header('Content-Type: text/xml');
    // echo $server->wsdl->serialize();

    exit(0);

為此文件指定一個名稱,例如getStuffComplex.php ,然后將此文件復制到Web服務器上的某個位置,並記住其路徑。
例如,我本地網絡服務器上的一個域名是http://soap.local ,上面提到的PHP代碼可以在http://soap.local/getStuffComplex.php

假設您想通過SOAP客戶端從Visual Studio 2010下的控制台應用程序調用C#代碼中的getStuffs()函數 在這種情況下,您必須執行以下步驟:

  1. 創建一個新的控制台應用程序項
  2. 右鍵單擊“參考” - “添加服務參考”
  3. 點擊“高級...”
  4. 單擊“添加Web引用...”
  5. 粘貼先前保存的PHP文件的URL(包含上面的內容)的路徑,並在URL字段中附加“?wsdl”字符串。 例如在我的情況下: http://soap.local/getStuffComplex.php?wsdl
  6. 單擊綠色右箭頭( “開始” )或在填寫URL字段后按Enter鍵。 如果找到getStuff()方法,情況就有希望了。
  7. 為引用提供右側的名稱(Web引用名稱),例如“StuffServiceComplex” (我將在我的代碼中使用此名稱),而不是按Enter鍵。 現在你必須在“Web引用”下看到它。
  8. 將下面的代碼復制到Program.cs中,然后點擊F5或點擊綠色的“play”圖標進行測試。

C#代碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Services.Protocols;

namespace WebServiceTestComplex
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                StuffServiceComplex.MyStuffService myService = new StuffServiceComplex.MyStuffService();

                StuffServiceComplex.ResponseObject myRespObject = myService.getStuffs("someone", "1234");

                switch (myRespObject.responseCode)
                {
                    // Everything was OK, results can be output
                    case 1:
                        Console.WriteLine("Everything's OK, let's write the results to the standard output:");
                        foreach (var stuff in myRespObject.stuffArray)
                        {
                            Console.WriteLine("\t"+stuff.id + ".:\t" + stuff.name);
                        }
                        break;
                    // Authentication failed
                    case 2:
                    // Unknown error
                    case 0:
                    default:
                        Console.WriteLine("Error:");
                        Console.WriteLine("\tError code: "+myRespObject.responseCode);
                        Console.WriteLine("\tError message: " + myRespObject.responseMessage);
                        break;
                }

            }
            catch (SoapException e)
            {
                Console.WriteLine("=== SOAP EXCEPTION!! ===");
                Console.WriteLine(e);
            }
            catch (Exception e)
            {
                Console.WriteLine("=== OTHER EXCEPTION!! ===");
                Console.WriteLine(e.ToString());
            }


            Console.WriteLine();
            Console.WriteLine("Press a key...");
            Console.ReadKey();
        }
    }
}

輸出:

Everything's OK, let's write the results to the standard output:
        122.:   One stuff
        213.:   Another stuff
        435.:   Whatever stuff
        65.:    Cool Stuff
        92.:    Wow, what a stuff

Press a key...

我希望這可以幫助那些努力將PHP和SOAP和.NET結合在一起的人。

(注意:使用重音符號或任何特殊字母時請注意字符編碼。默認情況下,可以使用ANSI(但字符編碼必須相同)。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM