Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Webservice Rückgabe komplexe Datenstruktur (https://www.delphipraxis.net/160912-webservice-rueckgabe-komplexe-datenstruktur.html)

af99 7. Jun 2011 15:37

Webservice Rückgabe komplexe Datenstruktur
 
Hallo Zusammen,

ich versuche verzweifelt eine Antwort von einem Webservice zu erhalten leider scheitert scheinbar schon der Aufruf an der Datenstruktur.
Ich arbeite mit Delphi XE und habe die WSDL Datei mit dem Assistenten importiert.
Hier der Aufruf
Code:
procedure TForm4.BitBtn1Click(Sender: TObject);
var
  gi: messageout;
  rein: messagein;
  myArray : array[0..1] of ItemType;
  myItemType : ItemType;

begin
  gi := messageout.Create;
  rein := messagein.Create;

  myItemType := ItemType.Create;
  myItemType.Article := '10000100';
  myItemType.Quantity := 1;

  myArray[0] := myItemType;

  rein.CustomerNo := 1;
  rein.Item[0] := myItemType;

  gi := (soe as web_getInventory).getInventory(rein);
  showmessage(inttostr(gi.Inventory.Item.Quantity));
  rein.Destroy;
  gi.Destroy;
end;
Hier die WSDL Datei
Code:
unit web;

interface

uses InvokeRegistry, SOAPHTTPClient, Types, XSBuiltIns;

const
  IS_OPTN = $0001;
  IS_UNBD = $0002;
  IS_UNQL = $0008;
  IS_REF = $0080;


type
ItemTypeOut         = class;                  MessageIn           = class;                  ItemType            = class;                  InventoryType       = class;                  MessageOut          = class;                
Array_Of_ItemType = array of ItemType;
ItemTypeOut = class(TRemotable)
  private
    FArticle: string;
    FQuantity: Integer;
    FAvailabilityState: string;
    FAvailabilityQuantity: Integer;
    FAvailabilityQuantity_Specified: boolean;
    FAvailabiltyText: string;
    FAvailabiltyText_Specified: boolean;
    FArticleDescription_1: string;
    FArticleDescription_1_Specified: boolean;
    FArticleDescription_2: string;
    FArticleDescription_2_Specified: boolean;
    FArticleState: Integer;
    FArticleState_Specified: boolean;
    FArticleStateText: string;
    FArticleStateText_Specified: boolean;
    procedure SetAvailabilityQuantity(Index: Integer; const AInteger: Integer);
    function AvailabilityQuantity_Specified(Index: Integer): boolean;
    procedure SetAvailabiltyText(Index: Integer; const Astring: string);
    function AvailabiltyText_Specified(Index: Integer): boolean;
    procedure SetArticleDescription_1(Index: Integer; const Astring: string);
    function ArticleDescription_1_Specified(Index: Integer): boolean;
    procedure SetArticleDescription_2(Index: Integer; const Astring: string);
    function ArticleDescription_2_Specified(Index: Integer): boolean;
    procedure SetArticleState(Index: Integer; const AInteger: Integer);
    function ArticleState_Specified(Index: Integer): boolean;
    procedure SetArticleStateText(Index: Integer; const Astring: string);
    function ArticleStateText_Specified(Index: Integer): boolean;
  published
    property Article:             string  Index (IS_UNQL) read FArticle write FArticle;
    property Quantity:            Integer Index (IS_UNQL) read FQuantity write FQuantity;
    property AvailabilityState:   string  Index (IS_UNQL) read FAvailabilityState write FAvailabilityState;
    property AvailabilityQuantity: Integer Index (IS_OPTN or IS_UNQL) read FAvailabilityQuantity write SetAvailabilityQuantity stored AvailabilityQuantity_Specified;
    property AvailabiltyText:     string  Index (IS_OPTN or IS_UNQL) read FAvailabiltyText write SetAvailabiltyText stored AvailabiltyText_Specified;
    property ArticleDescription_1: string  Index (IS_OPTN or IS_UNQL) read FArticleDescription_1 write SetArticleDescription_1 stored ArticleDescription_1_Specified;
    property ArticleDescription_2: string  Index (IS_OPTN or IS_UNQL) read FArticleDescription_2 write SetArticleDescription_2 stored ArticleDescription_2_Specified;
    property ArticleState:        Integer Index (IS_OPTN or IS_UNQL) read FArticleState write SetArticleState stored ArticleState_Specified;
    property ArticleStateText:    string  Index (IS_OPTN or IS_UNQL) read FArticleStateText write SetArticleStateText stored ArticleStateText_Specified;
  end;
  MessageIn = class(TRemotable)
  private
    FCustomerNo: Integer;
    FItem: Array_Of_ItemType;
  public
    constructor Create; override;
    destructor Destroy; override;
  published
    property CustomerNo: Integer           Index (IS_UNQL) read FCustomerNo write FCustomerNo;
    property Item:      Array_Of_ItemType Index (IS_UNBD or IS_UNQL) read FItem write FItem;
  end;
  ItemType = class(TRemotable)
  private
    FArticle: string;
    FQuantity: Integer;
  published
    property Article: string  Index (IS_UNQL) read FArticle write FArticle;
    property Quantity: Integer Index (IS_UNQL) read FQuantity write FQuantity;
  end;

  InventoryType = class(TRemotable)
  private
    FCustomerNo: Integer;
    FItem: ItemTypeOut;
  public
    destructor Destroy; override;
  published
    property CustomerNo: Integer     Index (IS_UNQL) read FCustomerNo write FCustomerNo;
    property Item:      ItemTypeOut Index (IS_UNQL) read FItem write FItem;
  end;
  MessageOut = class(TRemotable)
  private
    FInventory: InventoryType;
  public
    constructor Create; override;
    destructor Destroy; override;
  published
    property Inventory: InventoryType Index (IS_UNQL) read FInventory write FInventory;
  end;
 web_getInventory = interface(IInvokable)
  ['{7ECC6115-0305-FA86-1773-54264E557E44}']

    // Entpacken nicht möglich:
    //     - Eingabe-Part verweist auf kein Element
    //     - Ausgabe-Part verweist auf kein Element
    function getInventory(const getInventoryIn: MessageIn): MessageOut; stdcall;
  end;

function Getweb_getInventory(UseWSDL: Boolean=System.False; Addr: string=''; HTTPRIO: THTTPRIO = nil): web_getInventory;


implementation
  uses SysUtils;
...
Wenn ich das Programm nun schrittweise ausführe Taste "F8" dann springt die Ausführung komischerweise immer von der Programmzeile
rein.Item[0] := myItemType;
zur Programmzeile
end;
der Procedure procedure TForm4.BitBtn1Click(Sender: TObject); (siehe Source1) ohne die Programmzeilen dazwischen auszuführen. Auf dem End; kommt dann eine Exception.

Was mache ich falsch ???

Bernhard Geyer 7. Jun 2011 15:40

AW: Webservice Rückgabe komplexe Datenstruktur
 
Zitat:

Zitat von af99 (Beitrag 1105095)
... kommt dann eine Exception.

Und welche? Der Meldungstext ist hier oft hilfreich bei der Fehlersuche.

af99 7. Jun 2011 15:54

AW: Webservice Rückgabe komplexe Datenstruktur
 
Zugriffsverletzung bei Adresse 005612DE im Modul 'ws_client.exe'. Schreiben von Adresse 000000000.

daywalker9 7. Jun 2011 17:25

AW: Webservice Rückgabe komplexe Datenstruktur
 
Zitat:

Zitat von af99 (Beitrag 1105104)
Zugriffsverletzung bei Adresse 005612DE im Modul 'ws_client.exe'. Schreiben von Adresse 000000000.

`

Und in welcher Zeile?

Edit: Steht dort ja, nicht gesehen

t0by 8. Jun 2011 07:19

AW: Webservice Rückgabe komplexe Datenstruktur
 
Als "Anfänger" sieht das für mich sieht das so aus als wenn
Delphi-Quellcode:
rein.Item[0]
keine Länge bekommen hat, da Item ja via "array of ItemType;" deklariert wurde.

Kann es sein das dort ein
Delphi-Quellcode:
SetLength(rein.Item, 1);
fehlt?

VG Toby

af99 8. Jun 2011 07:42

AW: Webservice Rückgabe komplexe Datenstruktur
 
hmmmmm, ich bin mir nicht sicher ob ich das
SetLength(rein.Item, 1);
brauche.
Ich bekomme jedenfalls folgenden Fehler
[DCC Fehler] main.pas(61): E2197 Konstantenobjekt kann nicht als Var-Parameter weitergegeben werden

af99 8. Jun 2011 11:59

AW: Webservice Rückgabe komplexe Datenstruktur
 
schups

mkinzler 8. Jun 2011 12:03

AW: Webservice Rückgabe komplexe Datenstruktur
 
Du kennst unsere Richtlinie zum Thema Pushen?

af99 15. Jun 2011 15:29

AW: Webservice Rückgabe komplexe Datenstruktur
 
Weis denn wirklich keiner was ???

dominikkv 15. Jun 2011 15:55

AW: Webservice Rückgabe komplexe Datenstruktur
 
Wo und wie erstellst du Soe? Schau dir Getweb_getInventory an.

af99 15. Jun 2011 16:45

AW: Webservice Rückgabe komplexe Datenstruktur
 
soe ist die soap komponente THTTPRIO.

Es tut mir leid ich habe von Webservices leider noch nicht viel Ahnung. Was soll ich mir bei Getweb_getInventory ansehen??? Ich habe halt das Problem das ich zum Aufruf dem Webservice folgende Werte übergeben muss.
- CustomerNo
- Article
- Quantity

Wobei Customerno vom Type integer ist. Das klappt auch. Wenn ich dem Webservice nur die Customerno übergebe wird der Service auch aufgerufen und ich bekomme die Antwort das halt Article und Quantity fehlt.

Wenn ich nun Item vom Typ Array_Of_ItemType belegen möchte um hier Article und Quantity zu übergeben dann springt das Programm direkt vom Befehl
rein.Item[0] := myItemType;
zur Programmzeile
end;

Ich habe es auch folgendermassen probiert

Code:
...
rein := messagein.Create;
rein.CustomerNo := 1;
rein.Item[0].Quantity := 1;
rein.Item[0].Article := '10000100';
web.Getweb_getInventory.getInventory(rein);
...
Also ohne soap Komponente.. hat aber den gleicehn Effekt. Das Programm springt beim Ausführen von rein.Item[0].Quantity := 1;
zum end;

Keldorn 15. Jun 2011 20:24

AW: Webservice Rückgabe komplexe Datenstruktur
 
Hallo,

ich rufe den Webservice immer anders auf, kann Dir aber nicht sagen, was dort der Unterschied ist.

Delphi-Quellcode:
Var Webservice:web_getInventory;
    Erg:MessageOut;
begin
  Webservice:=Getweb_getInventory(false,'',HTTPRIO1);

  rein:=...
 
  erg:=Webservice.getInventory(rein);
                   
end;
Httprio1: ist eine HTTPRio-Kompo, die du mit auf die Form ziehst. Die braucht Du im Normalfall gar nicht. Aber wenn Du Dir anschauen willst, was da übertragen wird und wieder zurückkommt, fülle noch OnBeforeExecute und OnAfterExecute:

Delphi-Quellcode:
procedure TForm2.HTTPRIO1AfterExecute(const MethodName: string;
  SOAPResponse: TStream);
Var sl:Tstrings;
begin
  sl:=TStringList.Create;
  try
    SOAPResponse.Position:=0;
    sl.LoadFromStream(SOAPResponse);

    sl.SaveToFile(irgendwohin+'SoapResponse-Test.xml');
  finally
    sl.free;
  end;
end;

procedure TForm2.HTTPRIO1BeforeExecute(const MethodName: string;
  var SOAPRequest: WideString);
Var sl:Tstrings;
begin
  sl:=TStringList.Create;
  try
    sl.Text:=SOAPRequest;

    sl.SaveToFile(irgendwohin+'Soaprequest-Test.xml');
  finally
    sl.free;
  end;
end;
bist Du dir sicher, daß das funktionieren kann:
Delphi-Quellcode:
  myArray : array[0..1] of ItemType;

...

  myItemType := ItemType.Create;
  myItemType.Article := '10000100';
  myItemType.Quantity := 1;

  myArray[0] := myItemType;
Du hast ja damit ein Array mit 2 Feldern, belegst und erstellst aber nur das erste.
Für mich wäre logischer, wenn du das als dynamisches Aray deklarierst

Delphi-Quellcode:
Var
  myArray : Array_Of_ItemType; -> Array_Of_ItemType siehe die Wsdl

...
  setlength(myArray,1);
  rein.item:= myArray;

  myItemType := ItemType.Create;
  myItemType.Article := '10000100';
  myItemType.Quantity := 1;

  rein.item[0]:=myItemType;
Gruß Frank

af99 16. Jun 2011 14:48

AW: Webservice Rückgabe komplexe Datenstruktur
 
Hallo Frank,

Du bist mein Held. Hat super geklappt :-D:-D:-D:-D

Ich kann nun den Service ansprechen und bekomme eine Antwort zurück So sieht es nun aus.
Code:
var
  gi: messageout;
  rein: messagein;
  myArray : Array_Of_ItemType;
  myItemType : ItemType;

begin
  gi := messageout.Create;
  rein := messagein.Create;
  myItemType := ItemType.Create;

  setlength(myArray,1);
  rein.item:= myArray;

  rein.CustomerNo := 1;
  myItemType.Article := '10000100';
  myItemType.Quantity := 1;

  myArray[0] := myItemType;

  gi := (soe as web_getInventory).getInventory(rein);
...
Nun habe ich leider ein weiteres Problem.
Der Service muss folgendermassen angefragt werden.
Code:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header/>
   <soapenv:Body>
      <getInventoryIn>
         <CustomerNo>13635000</CustomerNo>
         <!--1 or more repetitions:-->
         <Item>
            <Article>101000500</Article>
            <Quantity>10</Quantity>
         </Item>
      </getInventoryIn>
   </soapenv:Body>
</soapenv:Envelope>
ich generiere aber (Habe ich dank deines Tipps aus der Datei des Ereignisses soeBeforeExecute)

Code:
  <?xml version="1.0" ?>
- <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <SOAP-ENV:Body>
- <MessageIn xmlns="http://www.soennecken.de/web.getInventory/">
  <CustomerNo xmlns="">1</CustomerNo>
- <Item xmlns="">
  <Article>10000100</Article>
  <Quantity>1</Quantity>
  </Item>
  </MessageIn>
  </SOAP-ENV:Body>
  </SOAP-ENV:Envelope>
Ich muss also statt meines
<MessageIn lns="http://www.soennecken.de/web.getInventory/">
ein
<getInventoryIn>
übergeben :(

Wie soll ich denn nun das anstellen.

Vielen Vielen Dank schon mal für Eure Hilfe
Gruß
Andreas

Keldorn 16. Jun 2011 15:23

AW: Webservice Rückgabe komplexe Datenstruktur
 
Sorry, muß gleich zu ner Feier und hab nicht viel Zeit ;-)

such mal hier im Forum zu Webservice oder soap, hier gab es vor kurzem ein gleiches Problem.
Es gibt da immer ein Problem mit namespaces, die irgendwie falsch gesetzt werden.

Du kannst aber die zu übertragende Soapnachricht im onbeforeexecute manuell mit etwas Fleiß und pos+delete etc ändern ...


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:28 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz