2011-08-08 28 views
8

Tôi muốn truy vấn một số nội dung thông qua SOAP bằng cách tạo WSDL với NuSOAP.
Tôi biết có rất nhiều câu hỏi liên quan đến chủ đề này, nhưng tôi đã không thành công trong việc điều chỉnh mã cho vấn đề cụ thể của mình.Tạo WSDL với NuSOAP - trả về cấu trúc với các loại khác nhau (int, string, array of structs)

Tôi đã thành công trong việc tạo mã WSDL chỉ trả về một mảng cấu trúc (mảng kết hợp), NHƯNG Tôi muốn trả về một đối tượng (struct) có chứa biến số nguyên, biến chuỗi VÀ mảng cấu trúc.

Vì vậy, đây là đoạn code mà làm việc cho trả lại một mảng của cấu trúc:

<?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(); 

?> 

Trong C# Console Application, sau khi thêm một Web Reference gọi là "StuffService" với biểu tượng "? Wsdl" nối vào URL thích hợp nơi này PHP-tập tin có thể được tìm thấy, mã này làm việc, tôi hoàn toàn có thể truy vấn các giá trị stuff_array như thế này:

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(); 
     } 
    } 
} 

Đó là mát mẻ, nhưng tôi muốn để phát triển mã này để trả lại một đối tượng như thế này:

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; 
} 

mã NuSOAP thích hợp là gì cho điều đó?
Cảm ơn !! :)

Tôi hy vọng tôi có thể làm rõ những gì tôi muốn đạt được: trả về cấu trúc chứa int, chuỗi và mảng cấu trúc, nhưng không biết cách viết mã NuSOAP thích hợp cho điều đó. Bằng cách này, trước hết tôi có thể kiểm tra mã phản hồi và xử lý nó bằng các thông báo lỗi thích hợp HOẶC xuất ra nội dungArray, v.v.

Trả lời

11

Sau một vài giờ thử nghiệm, tôi đã tìm ra giải pháp!

Vì vậy, trả về một cấu trúc chứa ba thành viên - một responseCode int, một chuỗi responseMessage và một mảng các cấu trúc được gọi là stuffArray trong ví dụ - thông qua SOAP với NuSOAP (PHP) trông như dưới đây, tôi đưa một số nhận xét vào mã để làm cho nó rõ ràng hơn:

<?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); 

đưa tập tin này một cái tên, ví dụ getStuffComplex.php, và sau đó sao chép tập tin này ở đâu đó trên máy chủ web của bạn, và ghi nhớ đường đi của nó.
Ví dụ: một tên miền trên máy chủ web cục bộ của tôi là http://soap.local và mã PHP được đề cập ở trên có thể đạt được tại http://soap.local/getStuffComplex.php.

Giả sử bạn muốn gọi hàm getStuffs() trong mã C# thông qua ứng dụng khách SOAP, từ Ứng dụng bảng điều khiển trong Visual Studio 2010. Trong trường hợp này bạn phải làm các bước sau:

  1. Tạo một dự án Console Application mới
  2. Nhấp chuột phải "Tham khảo" - "Thêm dịch vụ tham khảo"
  3. Bấm "Nâng cao ..."
  4. Bấm "Add Web Reference ..."
  5. Dán con đường URL đã lưu trước đó PHP-file (với các nội dung trên) và thêm biểu tượng "? Wsdl" chuỗi trong trường URL. Ví Ví dụ trong trường hợp của tôi: http://soap.local/getStuffComplex.php?wsdl
  6. Nhấp vào mũi tên màu xanh lá cây bên phải ("Go") hoặc nhấn Enter sau khi điền vào trường URL Nếu getStuff() phương pháp được tìm thấy, tình hình là hy vọng
  7. cho tham khảo a.. tên ở bên phải (tên tham chiếu web), ví dụ: "StuffServiceComplex" (Tôi sẽ sử dụng tên này trong mã của tôi), hơn nhấn Enter. Bây giờ bạn phải xem nó dưới "Tham khảo web".
  8. Sao chép mã bên dưới vào Program.cs và kiểm tra mã bằng cách nhấn F5 hoặc nhấp vào biểu tượng "phát" màu lục.

Mã # 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(); 
     } 
    } 
} 

Sản lượng:

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... 

Tôi hy vọng điều này sẽ giúp những người phải vật lộn với việc đưa PHP và SOAP và NET với nhau.

(Lưu ý: chú ý đến mã ký tự khi sử dụng dấu trọng âm hoặc bất kỳ chữ cái đặc biệt nào. Theo mặc định, ANSI có thể được sử dụng (nhưng mã hóa ký tự phải giống nhau).

Các vấn đề liên quan