AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi Delphi Client für C# WCF-Service mit wsDualHttp-Binding
Thema durchsuchen
Ansicht
Themen-Optionen

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

Ein Thema von cdev · begonnen am 6. Jun 2012 · letzter Beitrag vom 12. Jun 2012
Antwort Antwort
cdev

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

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

  Alt 6. Jun 2012, 22: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
mjustin

Registriert seit: 14. Apr 2008
3.006 Beiträge
 
Delphi 2009 Professional
 
#2

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

  Alt 8. Jun 2012, 15:36

Wenn
man aber den Befehl ausführt kommt die Meldung das an der Adresse ffffffff ein
Fehler aufgetreten ist.

Delphi-Quellcode:
var ws:IDuplexDemo;
param:Add;
begin
    param.n := 2.2;
    param.m := 2.8;

     ws:=GetIDuplexDemo(false);
     ws.Add(param);
end;
Sicher muss erst ein Add erzeugt werden (ffff deutet schon darauf hin):

Delphi-Quellcode:
var
  ws:IDuplexDemo;
  param:Add;
begin
  params := Add.Create;

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

  ws:=GetIDuplexDemo(false);
  ws.Add(param);
end;
Michael Justin
  Mit Zitat antworten Zitat
cdev

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

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

  Alt 12. Jun 2012, 09:20
Hallo,
vielen Dank für die Antwort! Ich habe es getestet. Jetzt kommt ein Timeout:
Das Zeitlimit für den Vorgang wurde erreicht. -URL:http://localhost:1234/DuplexDemo - SOAPAction:http://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!
  Mit Zitat antworten Zitat
mjustin

Registriert seit: 14. Apr 2008
3.006 Beiträge
 
Delphi 2009 Professional
 
#4

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

  Alt 12. Jun 2012, 12:37
Hallo,
vielen Dank für die Antwort! Ich habe es getestet. Jetzt kommt ein Timeout:
Das Zeitlimit für den Vorgang wurde erreicht. -URL:http://localhost:1234/DuplexDemo - SOAPAction:http://tempuri.org/IDuplexDemo/Add.
Der C# WCF Server will zur Übermittlung des Results einen HTTP Request an den Client senden, der dann quasi als SOAP Service Server arbeiten muss, und dieser reagiert nicht, da er nur in Richtung Server Verbindungen ausführt und keine annimmt. (Implementing Callback using WCF)

Um den Callback verarbeiten zu können, benötigt die Delphi Seite einen HTTP Server basierten SOAP Service.

Eventuell ist dieser Stackoverflow Artikel hilfreich bei der Implementierung eines Indy-basierten SOAP Servers:

SOAP server and client application VCL+indy demo for Delphi XE?
Michael Justin
habarisoft.com
  Mit Zitat antworten Zitat
Elvis

Registriert seit: 25. Nov 2005
Ort: München
1.909 Beiträge
 
Delphi 2010 Professional
 
#5

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

  Alt 12. Jun 2012, 13:41
Wäre es nicht viel einfacher und stabiler, wenn du dir in C# eine Client library baust, die du dann von Delphi aus benutzt? (geht auch ohne COM und Krampf)
Der SOAP-Stack in Delphi war IMO schon immer viel zu unflexibel.
Um wieviele Klassen geht es hier?
Robert Giesecke
I’m a great believer in “Occam’s Razor,” the principle which says:
“If you say something complicated, I’ll slit your throat.”
  Mit Zitat antworten Zitat
Antwort Antwort

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:43 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz