Announcement

Collapse
No announcement yet.

Daten kommen über Webservice beim Delphi Client nicht an

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Daten kommen über Webservice beim Delphi Client nicht an

    ** TEIL 1/2 **
    Hi,

    ich versuche Daten aus einer Datenbank im Internet über einen Webservice in PHP geschrieben anzuzapfen.

    Ich habe schon viel gelesen, und versucht aus allen Brocken die immer so von "Experten" ausgegeben werden ein konkretes Beispiel zu machen.

    Mein Service funktioniert soweit, dass ich Daten über den Webservice aus dem Internet bekommen, dieser aber in meiner Delphi 2009 Anwendung nicht angezeigt wird.

    Entweder ist meine WSDL-Datei fehlerhaft (was auch erklärt warum mir beim Import der WSDL-Datei die Typen nicht korrekt angelegt werden) oder mir fehlt etwas entscheidendes beim Füllen meiner Daten.

    Hier mal ein wenig Code

    So sieht meine MyWebServiceClass.php aus:
    PHP Code:
    <?

    class MyWebServiceClass
    {
        public function sagHallo($begruessung)
        { return 'Hallo ' . $begruessung; }
        
        public function addiere($a, $b)
        { return $a + $b; }
        
        public function LadeBereiche(){
        # set these values to match your setup
        $g_hostname      = "localhost";
        $g_db_username   = "user";
        $g_db_password   = "passwort";
        $g_database_name = "datenbank";
        $g_db_type       = "mysql";

          $db_link = @mysql_connect ($g_hostname, $g_db_username , $g_db_password);
          if ( ! $db_link )
            {
            die('keine Verbindung zur Zeit möglich - später probieren ');
            }
          $db_sel = mysql_select_db( MYSQL_DATENBANK )
             or die("Auswahl der Datenbank fehlgeschlagen");
          $sql = "SELECT * FROM `mantis_project_category_table` ";
          // ausführen des mysql-Befehls
          $db_erg = mysql_query( $sql );
          if ( ! $db_erg )
            {
               die('Ungültige Abfrage: ' . mysql_error());
            }
           
           while($row=mysql_fetch_array($db_erg)) {
             $arr[] = $row;
             }
           //print_r($arr) ;
           for($i=0; $i<count($arr); $i++){ 
             for($e=0; $e<count($arr[i]);$e++){
               $arr[$i][$e] = utf8_encode( $arr[$i][$e] ) ;
             }
           }
          mysql_free_result($db_erg);

          return $arr;
        }  
    }
    ?>
    Hier die server_klasse.php:
    PHP Code:
    <?
    require_once('MyWebServiceClass.php');
     
    $options = array('uri' => 'http://soap.prodas.de/test4/');
    $SOAPServer = new SoapServer(null, $options);
    $SOAPServer->setClass('MyWebServiceClass');
    $SOAPServer->handle();
    ?>
    Hier die dazugehörige WebService.wsdl Datei:
    HTML Code:
    <?xml version="1.0" encoding="UTF-8"?>
    
    <wsdl:definitions name="MyWebService" 
    	targetNamespace="http://soap.prodas.de/test4/" 
    	xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
    	xmlns:tns="http://soap.prodas.de/test4/" 
    	xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    	xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
    
        <wsdl:types>
            <wsdl:schema targetNamespace="http://www.softin.namespace">
                <wsdl:complexType name="Result">
                    <wsdl:sequence>
                        <wsdl:element maxOccurs="1" minOccurs="1" name="product_id" type="xs:int"/>
                        <wsdl:element maxOccurs="1" minOccurs="1" name="category" type="xs:string"/>
                        <wsdl:element maxOccurs="1" minOccurs="1" name="user_id" type="xs:int"/>
                    </wsdl:sequence>
                </wsdl:complexType>
                <wsdl:complexType name="ArrayOfResults">
                    <wsdl:complexContent>
                        <wsdl:restriction base="soapenc:Array">
                            <wsdl:sequence>
                                <wsdl:element maxOccurs="unbounded" minOccurs="0" name="item" type="softin:Result"/>
                            </wsdl:sequence>
                            <wsdl:attribute ref="soapenc:arrayType" wsdl:arrayType="softin:Result[]"/>
                        </wsdl:restriction>
                    </wsdl:complexContent>
                </wsdl:complexType>
                <wsdl:complexType name="Results">
                    <wsdl:sequence>
                        <wsdl:element name="results" type="softin:ArrayOfResults"/>
                    </wsdl:sequence>
                </wsdl:complexType>
            </wsdl:schema>
        </wsdl:types>                         
    	
    	
    	<wsdl:message name="sagHalloRequest">
    		<wsdl:part name="name" type="xsd:string">
    		</wsdl:part>
    	</wsdl:message>
        
    	<wsdl:message name="sagHalloResponse">
    		<wsdl:part name="begruessung" type="xsd:string">
    		</wsdl:part>
    	</wsdl:message>
    	
    	// LadeBereiche 
    	<wsdl:message name="LadeBereicheRequest">
    	</wsdl:message>
        
    	<wsdl:message name="LadeBereicheResponse">
    		<wsdl:part name="Recordlist" type="wsdl:Results">
    		</wsdl:part>
    	</wsdl:message>	
    
    	
    	<wsdl:portType name="MyWebServicePortType">
    	
    		<wsdl:operation name="sagHallo">
    			<wsdl:input message="tns:sagHalloRequest">
    			</wsdl:input>
    			<wsdl:output message="tns:sagHalloResponse">
    			</wsdl:output>
    		</wsdl:operation>
    		
    		<wsdl:operation name="LadeBereiche">
    			<wsdl:input message="tns:LadeBereicheRequest">
    			</wsdl:input>
    			<wsdl:output message="tns:LadeBereicheResponse">
    			</wsdl:output>
    		</wsdl:operation>		
    		
    	</wsdl:portType>
    
    	<wsdl:binding name="MyWebServiceBinding" type="tns:MyWebServicePortType">
    		<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
    		<wsdl:operation name="sagHallo">
    			<soap:operation soapAction="http://localhost/ws/sagHallo" />
    			<wsdl:input>
    				<soap:body use="literal" namespace="http://soap.prodas.de/test4/" />
    			</wsdl:input>
    			<wsdl:output>
    				<soap:body use="literal" namespace="http://soap.prodas.de/test4/" />
    			</wsdl:output>
    		</wsdl:operation>
    		<wsdl:operation name="LadeBereiche">
    			<soap:operation soapAction="http://localhost/ws/sagHallo" />
    			<wsdl:input>
    				<soap:body use="literal" namespace="http://soap.prodas.de/test4/" />
    			</wsdl:input>
    			<wsdl:output>
    				<soap:body use="literal" namespace="http://soap.prodas.de/test4/" />
    			</wsdl:output>
    		</wsdl:operation>		
    	</wsdl:binding>
    
    	<wsdl:service name="MyWebService">
    		<wsdl:port name="MyWebServicePort" 
    			binding="tns:MyWebServiceBinding">
    			<soap:address 
    				location="http://soap.prodas.de/test4/server_klasse.php"/>
    		</wsdl:port>
    	</wsdl:service>
    	</wsdl:definitions>
    ** ENDE TEIL 1/2**

  • #2
    WSDL SOAP WEBService tRemotetable

    ** TEIL 2/2 **

    Hier die Delphi-Unit uWebService.Pas mit den Typ-Deklarationen:
    Die von tRemoteTable abgeleiteten Klassen und die Registrierung habe ich mir aus Foren gesucht sie wurde nicht automatisch mit dem Import erzeugt.

    Code:
    // ************************************************************************ //
    // Die in dieser Datei deklarierten Typen wurden aus Daten generiert, die aus 
    // unten beschriebener WSDL-Datei stammen:
    // WSDL     : http://soap.prodas.de/test4/WebService.wsdl
    
    // Codierung : UTF-8// Version  : 1.0// (05.03.2011 16:41:35 - - $Rev: 19514 $)
    // ************************************************************************ //
    
    unit uWebService;
    
    interface
    
    uses InvokeRegistry, SOAPHTTPClient, Types, XSBuiltIns;
    
    const
      IS_OPTN = $0001;
      IS_UNBD = $0002;
      IS_NLBL = $0004;
      IS_UNQL = $0008;
    
    type
    
      // ************************************************************************ //
      // Die folgenden Typen, auf die im WSDL-Dokument Bezug genommen wird, sind in dieser Datei
      // nicht repräsentiert. Sie sind entweder Aliase(@) anderer repräsentierter Typen oder auf sie wurde Bezug genommen,
      // aber in diesem Dokument nicht deklariert (!). Die Typen aus letzterer Kategorie
      // sind normalerweise mit vordefinierten/bekannten XML- oder Borland-Typen verbunden; sie könnten aber auch ein Anzeichen 
      // für ein falsches WSDL-Dokument sein, das einen Schema-Typ nicht deklariert oder importiert..  // ************************************************************************ //
      // !:string          - "http://www.w3.org/2001/XMLSchema"[]
      // !:Results         - ""[]
    
      // ************************************************************************ //
      // XML       : media, global, <complexType>
      // Namespace : http://v2.service.egeko.odc.com/
      // ************************************************************************ //
      myResults = class(TRemotable)
      private
        FProject_ID : Integer;
        FProject_ID_Specified: boolean;
        FCategory: string;
        FCategory_Specified: boolean;
        fUser_id: Integer;
        fUser_id_Specified: boolean;
        procedure SetProject_id(Index: Integer; const AInt : Integer);
        function  Project_ID_Specified(Index: Integer): boolean;
        procedure SetCategory(Index: Integer; const Astring: string);
        function  Category_Specified(Index: Integer): boolean;
        procedure SetUser_ID(Index: Integer; const aInt : Integer);
        function  User_id_Specified(Index: Integer): boolean;
      published
        property Project_ID: integer  Index (IS_OPTN or IS_UNQL) read FProject_ID write SetProject_id stored Project_ID_Specified;
        property Category: string     Index (IS_OPTN or IS_UNQL) read FCategory write SetCategory stored Category_Specified;
        property User_id : integer    Index (IS_OPTN or IS_UNQL) read fUser_id write SetUser_ID stored User_id_Specified;
      end;
    
      Array_Of_myResults = array of myResults ;
    
      Results = class(TRemotable)
      private
        Fresults : array_of_myResults;
        Fresults_Specified: boolean;
        procedure Setresults(Index: Integer; const aResults : array_of_myResults);
        function  results_Specified(Index: Integer): boolean;
      published
        property results: array_of_myResults  Index (IS_OPTN or IS_UNQL) read Fresults write Setresults stored results_Specified;
      end;
    
      // ************************************************************************ //
      // Namespace : http://soap.prodas.de/test4/
      // soapAction: |http://localhost/ws/sagHallo|
      // Transport : http://schemas.xmlsoap.org/soap/http
      // Stil     : rpc
      // Bindung   : MyWebServiceBinding
      // Service   : MyWebService
      // Port      : MyWebServicePort
      // URL       : http://soap.prodas.de/test4/server_klasse.php
      // ************************************************************************ //
      MyWebServicePortType = interface(IInvokable)
      ['{EF19B6AE-3736-D6A6-DAB9-DE5FBFBDED51}']
        function  sagHallo(const name_: string): string; stdcall;
        function  LadeBereiche: Results; stdcall;
      end;
    
    function GetMyWebServicePortType(UseWSDL: Boolean=System.False; Addr: string=''; HTTPRIO: THTTPRIO = nil): MyWebServicePortType;
    
    
    implementation
      uses SysUtils;
    
    function GetMyWebServicePortType(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): MyWebServicePortType;
    const
      defWSDL = 'http://soap.prodas.de/test4/WebService.wsdl';
      defURL  = 'http://soap.prodas.de/test4/server_klasse.php';
      defSvc  = 'MyWebService';
      defPrt  = 'MyWebServicePort';
    var
      RIO: THTTPRIO;
    begin
      Result := nil;
      if (Addr = '') then
      begin
        if UseWSDL then
          Addr := defWSDL
        else
          Addr := defURL;
      end;
      if HTTPRIO = nil then
        RIO := THTTPRIO.Create(nil)
      else
        RIO := HTTPRIO;
      try
        Result := (RIO as MyWebServicePortType);
        if UseWSDL then
        begin
          RIO.WSDLLocation := Addr;
          RIO.Service := defSvc;
          RIO.Port := defPrt;
        end else
          RIO.URL := Addr;
      finally
        if (Result = nil) and (HTTPRIO = nil) then
          RIO.Free;
      end;
    end;
    
    
    { myResults }
    
    function myResults.Category_Specified(Index: Integer): boolean;
    begin
      Result := FCategory_Specified;
    end;
    
    function myResults.Project_ID_Specified(Index: Integer): boolean;
    begin
      Result := fProject_ID_Specified;
    end;
    
    function myResults.User_id_Specified(Index: Integer): boolean;
    begin
      Result := fUser_id_Specified;
    end;
    
    procedure myResults.SetCategory(Index: Integer; const Astring: string);
    begin
      FCategory := aString;
      FCategory_Specified := True;
    end;
    
    procedure myResults.SetProject_id(Index: Integer; const AInt: Integer);
    begin
      FProject_id := aInt ;
      FProject_id_Specified := True;
    end;
    
    procedure myResults.SetUser_ID(Index: Integer; const aInt: Integer);
    begin
      FProject_id := aInt ;
      FUser_id_Specified := True;
    end;
    
    
    { Results }
    
    function Results.results_Specified(Index: Integer): boolean;
    begin
      Result := fResults_Specified;
    end;
    
    procedure Results.Setresults(Index: Integer; const aResults: array_of_myResults);
    begin
      fResults := aResults ;
      fResults_Specified := True;
    end;
    
    initialization
      InvRegistry.RegisterInterface(TypeInfo(MyWebServicePortType), 'http://soap.prodas.de/test4/', 'UTF-8');
      InvRegistry.RegisterAllSOAPActions(TypeInfo(MyWebServicePortType), '|http://localhost/ws/sagHallo|');
      InvRegistry.RegisterExternalParamName(TypeInfo(MyWebServicePortType), 'sagHallo', 'name_', 'name');
      RemClassRegistry.RegisterXSClass(myResults, 'http://soap.prodas.de/test4/', 'myResults');
      RemClassRegistry.RegisterXSInfo(TypeInfo(Array_Of_myResults), 'http://soap.prodas.de/test4/', 'Array_Of_myResults');
      RemClassRegistry.RegisterXSClass(Results, 'http://soap.prodas.de/test4/', 'Results');
    
    end.
    Zum Schluss der Aufruf aus dem Test-Formular:

    Code:
    ...
    uses uWebService;
    
    {$R *.dfm}
    
    procedure TFormTestWSDL.Button1Click(Sender: TObject);
    var f : MyWebServicePortType ;
        r : Results ;
        I : Integer;
        c : Integer ;
    
    begin
      f := GetMyWebServicePortType (false) ;
      r := f.LadeBereiche ;
      c := high ( r.results ) ;
      memo1.lines.Add ( 'Anzahl : '+InttoStr ( c )) ;
      for I := 0 to high( r.Results ) do
        with r.Results[i] do
          memo1.lines.Add ( Format ( '%d, %s, %d', [ project_id, Category, user_id ] ) ) ;
    end;
    
    end.
    Mit einem Web-Schnüffel-Programm habe ich mir den Rückgabewert des Webservice angeschaut und bin mir auch nicht sicher ob die Felder Richtig sind.
    Hier ein Auszug:
    HTML Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:ns1="http://soap.prodas.de/test4/" 
    xmlns:ns2="http://xml.apache.org/xml-soap" 
    xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    <SOAP-ENV:Body>
      <ns1:LadeBereicheResponse>
        <return SOAP-ENC:arrayType="ns2:Map[35]" xsi:type="SOAP-ENC:Array">
    	  <item xsi:type="ns2:Map">
    	    <item>
    		  <key xsi:type="xsd:int">0</key>
    		  <value xsi:type="xsd:string">1</value>
    		</item>
    		<item>
    		  <key xsi:type="xsd:string">project_id</key>
    		  <value xsi:type="xsd:string">1</value>
    		</item>
    	    <item>
    		  <key ...
    Nach meiner Meinung dürft da nicht Item stehen sondern Result oder Results.

    Wie geschrieben basiert alles auf Codefetzen. Ich habe kein komplettes Beispiel gefunden wie eine komplexe Struktur in wsdl richtig definiert und richtig in Delphi eingelesen wird.

    Sollte jemand helfen können, wäre ich sehr dankbar.

    Gruß
    Ralf

    Comment


    • #3
      Welche Delphi-Version? Delphi ist nicht gerade dafür berühmt SOAP fehlerfrei und in allen Facetten zu unterstützen.

      Wieso überhaupt SOAP? Über eine JSON-Schnittstelle ist das doch ohne 99% Protokolloverhead zu realieren und läuft auch noch ressourcenschonender ab.

      Comment


      • #4
        Entwicklungsumgebung ist Delphi 2009.
        JSON kenn ich überhaupt nicht.

        Comment


        • #5
          Was ist JSON: JSON

          Comment


          • #6
            Mittlerweile weiß ich auch was JSON ist.
            Jedoch bin ich mir nicht sicher ob ich das Unterfangen hier einfach abbrechen sollte.

            Es muss doch auch so gehen.

            Comment

            Working...
            X