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:
Delphi-Quellcode:
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:
Delphi-Quellcode:
// ************************************************************************ //
// 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 =
nil)
and (HTTPRIO =
nil)
then
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 bitte um Eure mithilfe!
Danke im Voraus!