Autor Beitrag
cdev
Hält's aus hier
Beiträge: 2



BeitragVerfasst: Mi 06.06.12 21:19 
Hallo Zusammen,

ich möchte in Delphi 2007 Methoden in einer WCF abrufen, welche in C#, also .net gehostet wird. Das funktioniert mit basicHttp-Binding auch. Da ich aber Callbacks implementieren muss kommt das nicht in Frage. Duplex-Bindings sind netTcp-Binding und wsDualHttp-Binding. netTcp Binding kann auf Grund fehlender Interoperabilität nicht in Delphi verwendet werden.

WsDualHttp-Binding ist laut MSDN interoperabel. Ich kann in Delphi die wsdl-Datei fehlerfrei kompilieren und das Programm startet dann auch. Wenn man aber den Befehl ausführt kommt die Meldung das an der Adresse ffffffff ein Fehler aufgetreten ist.

Ich habe mal ein Demoprojekt erstellt um das ganze zu testen. Es soll eine Methode aufgerufen werden, welche zwei double als Parameter erhält. Diese Methode addiert beide Variablen und soll das Ergebnis über die Callbackmethode an den Delphi-Client senden.
Die WCF bietet eine Methode an: void Add(double n, double m);
Die Callback-Methode: void Result(double result);

Was mir noch überhaupt nicht klar ist: Wie definiere ich die Callback-Methode? Der Callback-Contract ist mit IDuplexDemoCallback bezeichnet. Diese Bezeichnung findet man in der vom wsdl-Importer erstellten Unit nicht.

Hier der aufrufende Quelltext:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
var ws:IDuplexDemo;
param:Add;
begin
    param.n := 2.2;
    param.m := 2.8;

     ws:=GetIDuplexDemo(false);
     ws.Add(param);
end;


und hier die Unit, die vom Delphi wsdl-Importer erstellt wurde:

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
// ************************************************************************ //
// Die in dieser Datei deklarierten Typen wurden aus Daten der unten
// beschriebenen WSDL-Datei generiert:

// WSDL     : http://localhost:1235/DuplexDemo
//  >Import : http://localhost:1235/DuplexDemo>0
//  >Import : http://localhost:1235/DuplexDemo?xsd=xsd0
//  >Import : http://localhost:1235/DuplexDemo?xsd=xsd1
// Codierung : utf-8
// Version: 1.0
// (06.06.2012 20:09:31 - - $Rev: 45757 $)
// ************************************************************************ //

unit DuplexDemo;

interface

uses InvokeRegistry, SOAPHTTPClient, Types, XSBuiltIns;

const
  IS_OPTN = $0001;
  IS_REF  = $0080;


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 sie sind in diesem Dokument nicht[!] deklariert. Die Typen aus letzterer Kategorie
  // sind in der Regel vordefinierten/bekannten XML- oder Embarcadero-Typen zugeordnet; sie könnten aber auf 
  // ein inkorrektes WSDL-Dokument hinweisen, das einen Schematyp nicht deklariert oder importiert hat.
  // ************************************************************************ //
  // !:double          - "http://www.w3.org/2001/XMLSchema"[Gbl]

  Add                  = class;                 { "http://tempuri.org/"[Lit][GblElm] }
  Result               = class;                 { "http://tempuri.org/"[Lit][GblElm] }



  // ************************************************************************ //
  // XML       : Add, global, <element>
  // Namespace : http://tempuri.org/
  // Serializtn: [xoLiteralParam]
  // Info      : Wrapper
  // ************************************************************************ //
  Add = class(TRemotable)
  private
    Fn: Double;
    Fn_Specified: boolean;
    Fm: Double;
    Fm_Specified: boolean;
    procedure Setn(Index: Integer; const ADouble: Double);
    function  n_Specified(Index: Integer): boolean;
    procedure Setm(Index: Integer; const ADouble: Double);
    function  m_Specified(Index: Integer): boolean;
  public
    constructor Create; override;
  published
    property n: Double  Index (IS_OPTN) read Fn write Setn stored n_Specified;
    property m: Double  Index (IS_OPTN) read Fm write Setm stored m_Specified;
  end;



  // ************************************************************************ //
  // XML       : Result, global, <element>
  // Namespace : http://tempuri.org/
  // Serializtn: [xoLiteralParam]
  // Info      : Wrapper
  // ************************************************************************ //
  Result = class(TRemotable)
  private
    Fresult: Double;
    Fresult_Specified: boolean;
    procedure Setresult(Index: Integer; const ADouble: Double);
    function  result_Specified(Index: Integer): boolean;
  public
    constructor Create; override;
  published
    property result: Double  Index (IS_OPTN) read Fresult write Setresult stored result_Specified;
  end;


  // ************************************************************************ //
  // Namespace : http://tempuri.org/
  // soapAction: http://tempuri.org/IDuplexDemo/%operationName%
  // Transport : http://schemas.xmlsoap.org/soap/http
  // Stil     : document
  // Verwenden von       : literal
  // Bindung   : WSDualHttpBinding_IDuplexDemo
  // Service   : CalculatorService
  // Port      : WSDualHttpBinding_IDuplexDemo
  // URL       : http://192.168.0.224:1234/DuplexDemo
  // ************************************************************************ //
  IDuplexDemo = interface(IInvokable)
  ['{DEDB3533-FA08-88C8-BB25-8388A7E5AA41}']
    procedure Add(const parameters: Add); stdcall;
    function  Result: Result; stdcall;
  end;

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


implementation
  uses SysUtils;

function GetIDuplexDemo(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): IDuplexDemo;
const
  defWSDL = 'http://localhost:1235/DuplexDemo';
  defURL  = 'http://192.168.0.224:1234/DuplexDemo';
  defSvc  = 'CalculatorService';
  defPrt  = 'WSDualHttpBinding_IDuplexDemo';
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 IDuplexDemo);
    if UseWSDL then
    begin
      RIO.WSDLLocation := Addr;
      RIO.Service := defSvc;
      RIO.Port := defPrt;
    end else
      RIO.URL := Addr;
  finally
    if (Result = niland (HTTPRIO = nilthen
      RIO.Free;
  end;
end;


constructor Add.Create;
begin
  inherited Create;
  FSerializationOptions := [xoLiteralParam];
end;

procedure Add.Setn(Index: Integer; const ADouble: Double);
begin
  Fn := ADouble;
  Fn_Specified := True;
end;

function Add.n_Specified(Index: Integer): boolean;
begin
  Result := Fn_Specified;
end;

procedure Add.Setm(Index: Integer; const ADouble: Double);
begin
  Fm := ADouble;
  Fm_Specified := True;
end;

function Add.m_Specified(Index: Integer): boolean;
begin
  Result := Fm_Specified;
end;

constructor Result.Create;
begin
  inherited Create;
  FSerializationOptions := [xoLiteralParam];
end;

procedure Result.Setresult(Index: Integer; const ADouble: Double);
begin
  Fresult := ADouble;
  Fresult_Specified := True;
end;

function Result.result_Specified(Index: Integer): boolean;
begin
  Result := Fresult_Specified;
end;

initialization
  { IDuplexDemo }
  InvRegistry.RegisterInterface(TypeInfo(IDuplexDemo), 'http://tempuri.org/''utf-8');
  InvRegistry.RegisterDefaultSOAPAction(TypeInfo(IDuplexDemo), 'http://tempuri.org/IDuplexDemo/%operationName%');
  InvRegistry.RegisterInvokeOptions(TypeInfo(IDuplexDemo), ioDocument);
  InvRegistry.RegisterInvokeOptions(TypeInfo(IDuplexDemo), ioLiteral);
  InvRegistry.RegisterInvokeOptions(TypeInfo(IDuplexDemo), ioSOAP12);
  RemClassRegistry.RegisterXSClass(Add, 'http://tempuri.org/''Add');
  RemClassRegistry.RegisterSerializeOptions(Add, [xoLiteralParam]);
  RemClassRegistry.RegisterXSClass(Result, 'http://tempuri.org/''Result');
  RemClassRegistry.RegisterSerializeOptions(Result, [xoLiteralParam]);

end.


Ich kenne mich in Delphi absolut nicht aus. Ich bitte um Eure mithilfe!
Danke im Voraus!
cdev Threadstarter
Hält's aus hier
Beiträge: 2



BeitragVerfasst: Di 12.06.12 09:25 
Hallo Zusammen,
die Variable param war anscheinend im Speicher nicht erzeugt worden. Mit
ausblenden Delphi-Quelltext
1:
Param := Add.Create;					

habe ich dieses Problem behoben. Der Aufruf sieht nun also so aus:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
var 
ws:IDuplexDemo;
param:Add;
begin
params := Add.Create;

param.n := 2.2;
param.m := 2.8;

ws:=GetIDuplexDemo(false);
ws.Add(param);
end;


Jetzt kommt ein Timeout:
Das Zeitlimit für den Vorgang wurde erreicht. -URL:localhost:1234/DuplexDemo - SOAPAction:tempuri.org/IDuplexDemo/Add.
Auch wenn ich die Timeouts erhöhe kommt es zu diesem Fehler.
Hat jemand eine Idee an was das liegen könnte? Mir ist auch immer noch nicht klar wie ich die Callback-Methode, die vom Server abgerufen wird, implementiere.
Danke im Voraus!