Einzelnen Beitrag anzeigen

cdev

Registriert seit: 6. Jun 2012
2 Beiträge
 
#1

Delphi Client für C# WCF-Service mit wsDualHttp-Binding

  Alt 6. Jun 2012, 21:03
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!
  Mit Zitat antworten Zitat